@crisp-ui-kit/crisp 0.54.7 → 0.54.9

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 (130) hide show
  1. package/dist/authshell.css +5 -1
  2. package/dist/authshell.layered.css +5 -1
  3. package/dist/badge.css +5 -5
  4. package/dist/badge.layered.css +5 -5
  5. package/dist/board.css +36 -8
  6. package/dist/board.layered.css +36 -8
  7. package/dist/button.css +3 -1
  8. package/dist/button.layered.css +3 -1
  9. package/dist/cjs/components/badge/badge.recipe.js +28 -5
  10. package/dist/cjs/components/button/button.js +33 -2
  11. package/dist/cjs/components/button/button.recipe.js +31 -5
  12. package/dist/cjs/components/contextmenu/contextmenu.js +2 -2
  13. package/dist/cjs/components/contextmenu/contextmenu.recipe.js +24 -0
  14. package/dist/cjs/components/datatable/datatable.js +590 -41
  15. package/dist/cjs/components/datatable/datatable.recipe.js +118 -5
  16. package/dist/cjs/components/dialog/dialog.js +72 -5
  17. package/dist/cjs/components/dialog/dialog.recipe.js +15 -1
  18. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +49 -5
  19. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +365 -49
  20. package/dist/cjs/components/tabletoolbar/tabletoolbar.recipe.js +78 -0
  21. package/dist/cjs/components/tabs/tabs.recipe.js +11 -2
  22. package/dist/cjs/components/tooltip/tooltip.js +23 -9
  23. package/dist/cjs/components/tooltip/tooltip.recipe.js +10 -9
  24. package/dist/cjs/product/authshell/authshell.js +14 -1
  25. package/dist/cjs/product/authshell/authshell.recipe.js +13 -1
  26. package/dist/cjs/product/board/board.js +175 -46
  27. package/dist/cjs/product/board/board.recipe.js +56 -4
  28. package/dist/cjs/product/comments/comments.js +34 -12
  29. package/dist/cjs/product/comments/comments.recipe.js +31 -7
  30. package/dist/cjs/product/formdialog/formdialog.js +10 -4
  31. package/dist/cjs/product/navitem/navitem.js +7 -2
  32. package/dist/cjs/product/navitem/navitem.recipe.js +16 -0
  33. package/dist/cjs/product/objectsettings/index.js +1 -2
  34. package/dist/cjs/product/objectsettings/objectsettings.js +3 -13
  35. package/dist/cjs/product/recordstable/recordstable.js +1 -17
  36. package/dist/cjs/product/richtext/richtext.js +76 -1
  37. package/dist/cjs/product/savedviews/savedviews.js +55 -24
  38. package/dist/cjs/product/savedviews/savedviews.recipe.js +27 -0
  39. package/dist/cjs/product/sidebar/sidebar.js +68 -15
  40. package/dist/cjs/product/sidebar/sidebar.recipe.js +6 -1
  41. package/dist/cjs/tokens/palette.js +32 -1
  42. package/dist/cjs/tokens/semantic.js +11 -0
  43. package/dist/comments.css +50 -14
  44. package/dist/comments.layered.css +50 -14
  45. package/dist/contextmenu.css +24 -0
  46. package/dist/contextmenu.layered.css +24 -0
  47. package/dist/datatable.css +101 -37
  48. package/dist/datatable.layered.css +101 -37
  49. package/dist/dialog.css +13 -1
  50. package/dist/dialog.layered.css +13 -1
  51. package/dist/esm/components/badge/badge.recipe.js +28 -5
  52. package/dist/esm/components/button/button.js +34 -3
  53. package/dist/esm/components/button/button.recipe.js +31 -5
  54. package/dist/esm/components/contextmenu/contextmenu.js +2 -2
  55. package/dist/esm/components/contextmenu/contextmenu.recipe.js +24 -0
  56. package/dist/esm/components/datatable/datatable.js +590 -42
  57. package/dist/esm/components/datatable/datatable.recipe.js +119 -6
  58. package/dist/esm/components/dialog/dialog.js +72 -5
  59. package/dist/esm/components/dialog/dialog.recipe.js +15 -1
  60. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +49 -5
  61. package/dist/esm/components/tabletoolbar/tabletoolbar.js +366 -50
  62. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +80 -2
  63. package/dist/esm/components/tabs/tabs.recipe.js +11 -2
  64. package/dist/esm/components/tooltip/tooltip.js +23 -9
  65. package/dist/esm/components/tooltip/tooltip.recipe.js +10 -9
  66. package/dist/esm/product/authshell/authshell.js +15 -2
  67. package/dist/esm/product/authshell/authshell.recipe.js +13 -1
  68. package/dist/esm/product/authshell/index.js +1 -1
  69. package/dist/esm/product/board/board.js +176 -47
  70. package/dist/esm/product/board/board.recipe.js +56 -4
  71. package/dist/esm/product/comments/comments.js +35 -13
  72. package/dist/esm/product/comments/comments.recipe.js +31 -7
  73. package/dist/esm/product/formdialog/formdialog.js +10 -4
  74. package/dist/esm/product/navitem/index.js +1 -1
  75. package/dist/esm/product/navitem/navitem.js +7 -2
  76. package/dist/esm/product/navitem/navitem.recipe.js +16 -0
  77. package/dist/esm/product/objectsettings/index.js +1 -1
  78. package/dist/esm/product/objectsettings/objectsettings.js +2 -12
  79. package/dist/esm/product/recordstable/recordstable.js +2 -18
  80. package/dist/esm/product/richtext/richtext.js +76 -1
  81. package/dist/esm/product/savedviews/savedviews.js +57 -26
  82. package/dist/esm/product/savedviews/savedviews.recipe.js +27 -0
  83. package/dist/esm/product/sidebar/sidebar.js +69 -16
  84. package/dist/esm/product/sidebar/sidebar.recipe.js +6 -1
  85. package/dist/esm/tokens/palette.js +32 -1
  86. package/dist/esm/tokens/semantic.js +11 -0
  87. package/dist/native/tokens.d.ts +1 -1
  88. package/dist/native/tokens.js +16 -2
  89. package/dist/navitem.css +7 -0
  90. package/dist/navitem.layered.css +7 -0
  91. package/dist/recordstable.css +34 -32
  92. package/dist/recordstable.layered.css +34 -32
  93. package/dist/savedviews.css +27 -0
  94. package/dist/savedviews.layered.css +27 -0
  95. package/dist/sidebar.css +6 -1
  96. package/dist/sidebar.layered.css +6 -1
  97. package/dist/styles.css +369 -106
  98. package/dist/styles.layered.css +369 -106
  99. package/dist/tabletoolbar.css +47 -3
  100. package/dist/tabletoolbar.layered.css +47 -3
  101. package/dist/tabs.css +1 -1
  102. package/dist/tabs.layered.css +1 -1
  103. package/dist/tokens.css +9 -1
  104. package/dist/tokens.json +16 -2
  105. package/dist/tooltip.css +1 -1
  106. package/dist/tooltip.layered.css +1 -1
  107. package/dist/types/components/badge/badge.recipe.d.ts +5 -1
  108. package/dist/types/components/button/button.recipe.d.ts +18 -5
  109. package/dist/types/components/contextmenu/contextmenu.d.ts +8 -1
  110. package/dist/types/components/datatable/datatable.d.ts +98 -1
  111. package/dist/types/components/dialog/dialog.d.ts +25 -2
  112. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +113 -3
  113. package/dist/types/components/tooltip/tooltip.d.ts +12 -4
  114. package/dist/types/components/tooltip/tooltip.recipe.d.ts +1 -1
  115. package/dist/types/product/authshell/authshell.d.ts +26 -2
  116. package/dist/types/product/authshell/index.d.ts +1 -1
  117. package/dist/types/product/board/board.d.ts +53 -6
  118. package/dist/types/product/comments/comments.d.ts +16 -3
  119. package/dist/types/product/formdialog/formdialog.d.ts +2 -1
  120. package/dist/types/product/navitem/index.d.ts +1 -1
  121. package/dist/types/product/navitem/navitem.d.ts +23 -0
  122. package/dist/types/product/objectsettings/index.d.ts +1 -1
  123. package/dist/types/product/objectsettings/objectsettings.d.ts +0 -10
  124. package/dist/types/product/recordstable/recordstable.d.ts +0 -1
  125. package/dist/types/product/savedviews/savedviews.d.ts +45 -8
  126. package/dist/types/product/sidebar/sidebar.d.ts +33 -5
  127. package/dist/types/tokens/contract.d.ts +4 -0
  128. package/dist/types/tokens/palette.d.ts +13 -1
  129. package/dist/types/tokens/semantic.d.ts +11 -0
  130. package/package.json +1 -1
@@ -22,6 +22,25 @@ export type DialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title" |
22
22
  "aria-label"?: string;
23
23
  /** aria-label on the close button (default "Close") — override for non-English UIs. */
24
24
  closeLabel?: string;
25
+ /**
26
+ * `"panel"` (default): the frosted content dialog measured everywhere
27
+ * else in crisp — top-anchored 15vh from the viewport, a bordered
28
+ * header with a close button, `role="dialog"`.
29
+ *
30
+ * `"alert"` (crisp#677): a small confirm — Attio's own "Discard changes"
31
+ * measured live, both themes: vertically centered (not top-anchored), a
32
+ * plain `bgPopover` surface with `elevation.floating` (not the frosted
33
+ * bezel), `radius.xl` (12px, not the panel's 16px), NO close button, and
34
+ * `role="alertdialog"`. Pairs with `description` below — a plain
35
+ * `title` alone reads oddly stacked with no border under it, since the
36
+ * alert variant has no header chrome to separate title from body.
37
+ */
38
+ variant?: "panel" | "alert";
39
+ /** `variant="alert"` only: the confirm's body sentence, stacked directly
40
+ * under `title` with no divider (Attio's own two-line shape — a bold
41
+ * title, then a muted sentence). Wired to Zag's `getDescriptionProps()`
42
+ * so `aria-describedby` follows it automatically. */
43
+ description?: React.ReactNode;
25
44
  children?: React.ReactNode;
26
45
  };
27
46
  /**
@@ -29,7 +48,7 @@ export type DialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title" |
29
48
  * Escape / outside-click dismissal) with the measured modal surface.
30
49
  * Compose the body with `DialogBody` and actions with `DialogFooter`.
31
50
  */
32
- export declare function Dialog({ open, onOpenChange, title, icon, width, "aria-label": ariaLabel, closeLabel: closeLabelProp, children, className, style, "aria-describedby": describedBy, ...rest }: DialogProps): React.JSX.Element | null;
51
+ export declare function Dialog({ open, onOpenChange, title, icon, width, variant, description, "aria-label": ariaLabel, closeLabel: closeLabelProp, children, className, style, "aria-describedby": describedBy, ...rest }: DialogProps): React.JSX.Element | null;
33
52
  export declare namespace Dialog {
34
53
  var displayName: string;
35
54
  }
@@ -37,6 +56,10 @@ export declare function DialogBody({ children, className, }: {
37
56
  children?: React.ReactNode;
38
57
  className?: string;
39
58
  }): React.JSX.Element;
40
- export declare function DialogFooter({ children }: {
59
+ export declare function DialogFooter({ children, variant, }: {
41
60
  children?: React.ReactNode;
61
+ /** Matches the owning `Dialog`'s own `variant` (crisp#677) — `"alert"`
62
+ * is a shorter bar (45px vs. the panel's 56px) with uniform 8px padding
63
+ * instead of the panel's 0/16px, measured off Attio's discard confirm. */
64
+ variant?: "panel" | "alert";
42
65
  }): React.JSX.Element;
@@ -8,11 +8,21 @@ export type ToolbarSort = {
8
8
  key: string;
9
9
  dir: SortDir;
10
10
  };
11
- export type ToolbarFilterOp = "contains" | "doesnotcontain" | "startswith" | "endswith" | "is" | "isnot" | "isanyof" | "empty" | "notempty";
11
+ export type ToolbarFilterOp = "contains" | "doesnotcontain" | "startswith" | "endswith" | "is" | "isnot" | "isanyof" | "empty" | "notempty"
12
+ /** Number columns only (#593). */
13
+ | "lessthan" | "greaterthan"
14
+ /** Date columns only (#593). */
15
+ | "before" | "after";
12
16
  export type ToolbarFilter = {
13
17
  id: string;
14
18
  key: string;
15
- op: ToolbarFilterOp;
19
+ /**
20
+ * Unset right after the field is (re)chosen — measured live, 2026-09-25:
21
+ * Attio's own chip shows "Select condition" until an operator is actually
22
+ * picked, rather than defaulting silently to one. Once set, it never goes
23
+ * back to unset short of changing the field, which resets it.
24
+ */
25
+ op?: ToolbarFilterOp;
16
26
  value: string;
17
27
  /** Selected values for `"isanyof"` — ignored by every other op. */
18
28
  values?: string[];
@@ -29,6 +39,48 @@ export type TableToolbarColumn = {
29
39
  * for a free-text column; there is nothing to check off.
30
40
  */
31
41
  values?: string[];
42
+ /**
43
+ * The column's value kind, gating which operators (and which value editor)
44
+ * its condition offers (#593). Defaults to a free-text column: `contains`/
45
+ * `does not contain`/`starts with`/`ends with`/`is`/`is not`/`empty`/
46
+ * `not empty`. `"number"` swaps in `is`/`is not`/`less than`/`greater
47
+ * than`/`empty`/`not empty` with a spinner number input; `"date"` swaps in
48
+ * `is`/`is not`/`before`/`after`/`empty`/`not empty` with a calendar +
49
+ * Today/Tomorrow/Next week quick-picks — both sets, and the number
50
+ * spinner, measured live against Attio's own column-typed filter menus.
51
+ * `"select"` (#715) swaps in `is`/`is not`/`empty`/`not empty` — a
52
+ * closed-vocabulary column's text-search operators (`contains`/`starts
53
+ * with`/…) mean nothing against a fixed value set. Pair it with `values`
54
+ * to also offer `"is any of"`, the same as every other type.
55
+ */
56
+ type?: "text" | "number" | "date" | "select";
57
+ /**
58
+ * This column's own related object's attributes, reachable as a
59
+ * "Parent › Child" path in the Filter field picker (#592) — a
60
+ * relationship field (Attio's own "Team 26", a company's linked people,
61
+ * e.g.) expands into a nested picker over these instead of only
62
+ * offering the relationship field itself. Recurses: a nested column can
63
+ * carry its own `nestedColumns` too (Team → Company → …, confirmed
64
+ * reachable live) with no depth limit built in here. The relationship
65
+ * field itself stays independently selectable (its own operators, e.g.
66
+ * `contains`/`does not contain`/`empty`/`not empty` for a person
67
+ * relationship, measured live) — drilling in doesn't remove that option,
68
+ * it adds the nested one alongside it, matching Attio's own picker
69
+ * exactly (its nested screen lists the relationship field itself first,
70
+ * checked when it's the chip's current field, then its children).
71
+ */
72
+ nestedColumns?: TableToolbarColumn[];
73
+ /**
74
+ * The related object's own singular noun, used once a consumer drills
75
+ * into this column: the nested picker's placeholder reads `Search
76
+ * ${nestedObjectLabel} attributes…` — measured live, e.g. "person" for a
77
+ * Team/People relationship, "company" for a Company relationship. Only
78
+ * meaningful alongside `nestedColumns`. Falls back to this column's own
79
+ * `label`, lowercased, when omitted — a plain fallback, since Attio's
80
+ * own noun is the *related object's* name, not usually the field's own
81
+ * label lowercased ("Team" the field vs. "person" the related object).
82
+ */
83
+ nestedObjectLabel?: string;
32
84
  };
33
85
  export type TableToolbarProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
34
86
  /**
@@ -121,6 +173,25 @@ export type TableToolbarProps = Omit<React.ComponentPropsWithoutRef<"div">, "chi
121
173
  */
122
174
  inline?: boolean;
123
175
  className?: string;
176
+ /**
177
+ * Renders the Sort trigger (and its popover) when true (default). Set
178
+ * `false` for a table with no client-side sort at all — GRC's Audit log,
179
+ * server-filtered with nothing for a sort control to do, is the case that
180
+ * added this (your-moon/crisp#714, internal/grc !146): the trigger was
181
+ * inert chrome, not a real control. The divider that otherwise separates
182
+ * Sort from Filter is dropped along with it, so Filter becomes the row's
183
+ * first tool rather than leaving a leading divider with nothing before it.
184
+ */
185
+ showSort?: boolean;
186
+ /**
187
+ * Renders the View settings trigger (and its popover) when true (default).
188
+ * Set `false` when a consumer renders its own view-settings control —
189
+ * GRC's Tasks page (internal/grc !149) rendered its own alongside
190
+ * `TableToolbar`'s, ending up with two "View settings" buttons; this is
191
+ * the opt-out (your-moon/crisp#714). The divider that otherwise separates
192
+ * the filter chips from View settings is dropped along with it.
193
+ */
194
+ showViewSettings?: boolean;
124
195
  /**
125
196
  * The full set of attributes View settings offers — every attribute on
126
197
  * the object, shown or not. Defaults to `columns`. Omit both, along with
@@ -152,6 +223,45 @@ export type TableToolbarProps = Omit<React.ComponentPropsWithoutRef<"div">, "chi
152
223
  addAttributeToViewLabel?: string;
153
224
  /** Placeholder in the add-attribute search box (default "Search attributes…"). */
154
225
  searchAttributesPlaceholder?: string;
226
+ /**
227
+ * Text on the Import/Export trigger (default "Import / Export"). The
228
+ * trigger only renders when at least one of `onImportCsv`/`onExportCsv`/
229
+ * `onExportExcel`/`importExportHelpHref` is given — an unwired menu has
230
+ * nothing to do, the same "still renders empty" contract other triggers
231
+ * here make doesn't fit a menu that would just be blank.
232
+ */
233
+ importExportLabel?: string;
234
+ /** The menu's "Import CSV" item — omit to leave it out. */
235
+ onImportCsv?: () => void;
236
+ /** The menu's "Export view as CSV" item — omit to leave it out. */
237
+ onExportCsv?: () => void;
238
+ /** The menu's "Export view as Excel" item — omit to leave it out. */
239
+ onExportExcel?: () => void;
240
+ /** Shows a "Learn about imports and exports" link in the menu when set —
241
+ * same pattern as Sort's own `helpHref`. */
242
+ importExportHelpHref?: string;
243
+ /** Label on the "Import CSV" item (default "Import CSV"). */
244
+ importCsvLabel?: string;
245
+ /** Label on the "Export view as CSV" item (default "Export view as CSV"). */
246
+ exportCsvLabel?: string;
247
+ /** Label on the "Export view as Excel" item (default "Export view as Excel"). */
248
+ exportExcelLabel?: string;
249
+ /** Text of the Import/Export menu's help link (default "Learn about
250
+ * imports and exports"). */
251
+ learnImportExportLabel?: string;
252
+ /** aria-label on the Filter field picker's back control, shown once
253
+ * drilled into a `nestedColumns` column (default "Back"). */
254
+ backLabel?: string;
255
+ /**
256
+ * Placeholder in the field picker's own search box once drilled into a
257
+ * `nestedColumns` column — receives that column's `nestedObjectLabel`
258
+ * (or its `label`, lowercased). Defaults to `Search ${noun} attributes…`,
259
+ * matching Attio's own measured wording ("Search person attributes…",
260
+ * drilled into a Team/People relationship) — a formatter, like
261
+ * `sortTriggerLabel` above, since the noun sits mid-sentence and a fixed
262
+ * template doesn't survive every language's word order.
263
+ */
264
+ nestedFieldPlaceholder?: (noun: string) => string;
155
265
  };
156
266
  /**
157
267
  * Applies a toolbar's filter conditions to any row array. Reads the raw value
@@ -178,7 +288,7 @@ export declare function applySorts<T>(rows: T[], sorts: ToolbarSort[], get?: (ro
178
288
  * this (Sort: Due date/Assignee/Creation date; Filter: Assignee/Record/
179
289
  * Created by), which one shared list can't reproduce.
180
290
  */
181
- export declare function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: filterColumnsProp, sorts: sortsProp, defaultSorts, onSortsChange, filters: filtersProp, defaultFilters, onFiltersChange, count, children, helpHref, className, sortLabel: sortLabelProp, filterLabel: filterLabelProp, reorderSortLabel: reorderSortLabelProp, noSortsLabel: noSortsLabelProp, addSortLabel: addSortLabelProp, learnSortingLabel: learnSortingLabelProp, selectConditionLabel: selectConditionLabelProp, sortFieldLabel: sortFieldLabelProp, sortDirectionLabel: sortDirectionLabelProp, removeSortLabel: removeSortLabelProp, filterFieldLabel: filterFieldLabelProp, filterFieldPlaceholder: filterFieldPlaceholderProp, filterValuePlaceholder: filterValuePlaceholderProp, filterOptionsLabel: filterOptionsLabelProp, deleteFilterLabel: deleteFilterLabelProp, ascendingLabel: ascendingLabelProp, descendingLabel: descendingLabelProp, sortTriggerLabel, filterTriggerLabel, inline, viewColumns: viewColumnsProp, shownKeys: shownKeysProp, defaultShownKeys, onShownKeysChange, viewSettingsLabel: viewSettingsLabelProp, reorderAttributeLabel: reorderAttributeLabelProp, hideAttributeLabel, addAttributeToViewLabel: addAttributeToViewLabelProp, searchAttributesPlaceholder: searchAttributesPlaceholderProp, ...rest }: TableToolbarProps): React.JSX.Element;
291
+ export declare function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: filterColumnsProp, sorts: sortsProp, defaultSorts, onSortsChange, filters: filtersProp, defaultFilters, onFiltersChange, count, children, helpHref, className, sortLabel: sortLabelProp, filterLabel: filterLabelProp, reorderSortLabel: reorderSortLabelProp, noSortsLabel: noSortsLabelProp, addSortLabel: addSortLabelProp, learnSortingLabel: learnSortingLabelProp, selectConditionLabel: selectConditionLabelProp, sortFieldLabel: sortFieldLabelProp, sortDirectionLabel: sortDirectionLabelProp, removeSortLabel: removeSortLabelProp, filterFieldLabel: filterFieldLabelProp, filterFieldPlaceholder: filterFieldPlaceholderProp, filterValuePlaceholder: filterValuePlaceholderProp, filterOptionsLabel: filterOptionsLabelProp, deleteFilterLabel: deleteFilterLabelProp, ascendingLabel: ascendingLabelProp, descendingLabel: descendingLabelProp, sortTriggerLabel, filterTriggerLabel, inline, showSort, showViewSettings, viewColumns: viewColumnsProp, shownKeys: shownKeysProp, defaultShownKeys, onShownKeysChange, viewSettingsLabel: viewSettingsLabelProp, reorderAttributeLabel: reorderAttributeLabelProp, hideAttributeLabel, addAttributeToViewLabel: addAttributeToViewLabelProp, searchAttributesPlaceholder: searchAttributesPlaceholderProp, importExportLabel: importExportLabelProp, onImportCsv, onExportCsv, onExportExcel, importExportHelpHref, importCsvLabel: importCsvLabelProp, exportCsvLabel: exportCsvLabelProp, exportExcelLabel: exportExcelLabelProp, learnImportExportLabel: learnImportExportLabelProp, backLabel: backLabelProp, nestedFieldPlaceholder, ...rest }: TableToolbarProps): React.JSX.Element;
182
292
  export type ToolbarToolProps = React.ComponentPropsWithoutRef<"button"> & {
183
293
  /** Drawn the way Sort/Filter are once a condition is set (#399). */
184
294
  active?: boolean;
@@ -11,8 +11,12 @@ export type TooltipProps = Omit<React.ComponentPropsWithoutRef<"span">, "content
11
11
  * renders and hovers correctly but can't carry either.
12
12
  */
13
13
  children: React.ReactNode;
14
- /** Preferred side; flips to the other axis end when there's no room. */
15
- side?: "top" | "bottom";
14
+ /** Preferred side; "top"/"bottom" flip to the other axis end when there's
15
+ * no room. "right" (crisp#633: the sidebar's hotkey hint, measured 8px off
16
+ * the trigger's end edge, vertically centred) never flips -- every known
17
+ * user pins its trigger to the viewport's left edge, so there is always
18
+ * room. */
19
+ side?: "top" | "bottom" | "right";
16
20
  /** Delay in ms before showing (default 350). Hides immediately. */
17
21
  delay?: number;
18
22
  /** Controlled open state. Omit to let Tooltip manage it (see defaultOpen).
@@ -71,8 +75,12 @@ export declare const Tooltip: React.ForwardRefExoticComponent<Omit<Omit<React.De
71
75
  * renders and hovers correctly but can't carry either.
72
76
  */
73
77
  children: React.ReactNode;
74
- /** Preferred side; flips to the other axis end when there's no room. */
75
- side?: "top" | "bottom";
78
+ /** Preferred side; "top"/"bottom" flip to the other axis end when there's
79
+ * no room. "right" (crisp#633: the sidebar's hotkey hint, measured 8px off
80
+ * the trigger's end edge, vertically centred) never flips -- every known
81
+ * user pins its trigger to the viewport's left edge, so there is always
82
+ * room. */
83
+ side?: "top" | "bottom" | "right";
76
84
  /** Delay in ms before showing (default 350). Hides immediately. */
77
85
  delay?: number;
78
86
  /** Controlled open state. Omit to let Tooltip manage it (see defaultOpen).
@@ -14,7 +14,7 @@ declare const spec: {
14
14
  readonly fontSize: `var(--${string})`;
15
15
  readonly fontWeight: `var(--${string})`;
16
16
  readonly lineHeight: "1.45";
17
- readonly boxShadow: "0 4px 14px -2px rgba(28,40,64,0.28), 0 0 0 1px rgba(255,255,255,0.04)";
17
+ readonly boxShadow: "rgb(33,34,36) 0 0 0 1px inset, rgba(0,0,0,0.04) 0 0 2px 0, rgba(0,0,0,0.12) 0 1px 3px 0";
18
18
  readonly opacity: 1;
19
19
  readonly transition: "opacity 0.12s ease";
20
20
  };
@@ -1,9 +1,33 @@
1
1
  import type * as React from "react";
2
+ /**
3
+ * A multi-part brand mark — an icon badge beside a bold wordmark and an
4
+ * optional tagline (your-moon/crisp#728) — for a consumer whose logo isn't a
5
+ * single flat image the way Attio's own `/login` mark is. `AuthShell` lays
6
+ * this out itself (badge + two-line stack, `authshell.recipe.ts`), so a
7
+ * consumer never writes its own `style`/`className` to compose one. Not
8
+ * measured against Attio: its own login has no such compound mark, so
9
+ * there's nothing to measure past what `.crisp-authshell-logo` already
10
+ * establishes (the 24px floor, the 32px top margin).
11
+ */
12
+ export type AuthShellBrand = {
13
+ /** A small glyph, rendered inside a 32px rounded brand-tone badge. */
14
+ icon: React.ReactNode;
15
+ /** The bold wordmark line. */
16
+ title: React.ReactNode;
17
+ /** An optional second line under the wordmark. */
18
+ subtitle?: React.ReactNode;
19
+ };
2
20
  export type AuthShellProps = Omit<React.ComponentPropsWithoutRef<"div">, "title"> & {
3
21
  /** 0–1. Omit for no progress bar. */
4
22
  progress?: number;
5
- /** Brand mark above the card (measured 96x24). */
6
- logo?: React.ReactNode;
23
+ /** Brand mark above the card (measured 96x24 on Attio's own logged-out
24
+ * `/login`). The slot's own `min-height` is 24px, not a fixed height
25
+ * (your-moon/crisp#722) — a taller lockup (an icon beside a two-line
26
+ * wordmark, say) grows the slot instead of getting clipped to it. Pass a
27
+ * plain node for a single flat mark (Attio's own shape), or an
28
+ * `AuthShellBrand` (`{ icon, title, subtitle? }`, your-moon/crisp#728)
29
+ * for a compound one `AuthShell` lays out itself. */
30
+ logo?: React.ReactNode | AuthShellBrand;
7
31
  /** Card heading. */
8
32
  title?: React.ReactNode;
9
33
  /** The form / body content. */
@@ -1,2 +1,2 @@
1
- export { AuthShell, type AuthShellProps } from "./authshell";
1
+ export { AuthShell, type AuthShellBrand, type AuthShellProps, } from "./authshell";
2
2
  export { authshellRecipe } from "./authshell.recipe";
@@ -1,4 +1,9 @@
1
1
  import * as React from "react";
2
+ /** crisp/#718 — Attio's own two independent density toggles: "collapse"
3
+ * (columns narrow to a 52px vertical rail; cards shrink to a 40px row) or
4
+ * "expand" (the normal width/height), measured live on the Deals
5
+ * pipeline. */
6
+ export type BoardDensity = "expand" | "collapse";
2
7
  export type BoardColumn = {
3
8
  id: string;
4
9
  title: string;
@@ -24,10 +29,51 @@ export type BoardProps<T extends BoardCard> = Omit<React.ComponentPropsWithoutRe
24
29
  cards: T[];
25
30
  /** Called with the next cards after a drag moves one between columns. */
26
31
  onCardsChange?: (cards: T[]) => void;
27
- renderCard: (card: T) => React.ReactNode;
32
+ /**
33
+ * The second argument is the board's CURRENT card density (crisp/#718) —
34
+ * `renderCard` decides what a collapsed (40px row) card actually shows,
35
+ * since Board only knows the card is a `T`, never its display shape.
36
+ * Ignoring the argument (a plain `(card) => ...`) keeps every existing
37
+ * call site valid; `cardDensity` then just resolves to `"expand"` always,
38
+ * exactly as before this prop existed.
39
+ */
40
+ renderCard: (card: T, cardDensity: BoardDensity) => React.ReactNode;
28
41
  /** When set, each column shows a "+ {newCardLabel}" button and its header +. */
29
42
  onNewCard?: (columnId: string) => void;
30
43
  newCardLabel?: string;
44
+ /**
45
+ * Shows the density toolbar above the board — Attio's own two
46
+ * independent "Collapse/Expand columns" and "Collapse/Expand cards"
47
+ * segmented toggles (crisp/#718, measured live). Default `false`: an
48
+ * existing `Board` renders no toolbar and no extra chrome, exactly as
49
+ * before this prop existed.
50
+ */
51
+ density?: boolean;
52
+ /** Controlled column density (omit for uncontrolled, seeded "expand"). */
53
+ columnDensity?: BoardDensity;
54
+ onColumnDensityChange?: (density: BoardDensity) => void;
55
+ /** Controlled card density (omit for uncontrolled, seeded "expand") —
56
+ * also the value `renderCard`'s second argument resolves to. */
57
+ cardDensity?: BoardDensity;
58
+ onCardDensityChange?: (density: BoardDensity) => void;
59
+ collapseColumnsLabel?: string;
60
+ expandColumnsLabel?: string;
61
+ collapseCardsLabel?: string;
62
+ expandCardsLabel?: string;
63
+ /** aria-label for the column-density toggle's own `role="radiogroup"`
64
+ * wrapper (Attio's own markup uses a plain `role="group"` with no name —
65
+ * crisp names both groups, the more correct ARIA shape for a set of
66
+ * mutually-exclusive `role="radio"` buttons). */
67
+ columnDensityGroupLabel?: string;
68
+ cardDensityGroupLabel?: string;
69
+ /**
70
+ * Renders a trailing 52×52px dashed "+" slot after the last column —
71
+ * Attio's own "Add stage" (crisp/#718, measured live). Omit to skip it
72
+ * entirely, matching every other opt-in affordance here (`onNewCard`,
73
+ * `calc`).
74
+ */
75
+ onAddStage?: () => void;
76
+ addStageLabel?: string;
31
77
  /**
32
78
  * Accessible name for a card. Also used in the move announcement. Without it
33
79
  * a card is announced by whatever `renderCard` puts in it, which is usually
@@ -48,12 +94,13 @@ export type BoardProps<T extends BoardCard> = Omit<React.ComponentPropsWithoutRe
48
94
  className?: string;
49
95
  };
50
96
  /**
51
- * A kanban board with native drag-and-drop between columns. Cards are
52
- * `draggable`; dropping one on a column reparents it via `onCardsChange`
53
- * (the parent owns the cards, so the move is a controlled state update).
54
- * Measured from a deals pipeline.
97
+ * A kanban board with pointer-events drag-and-drop between columns (#674 —
98
+ * Attio's own mechanism, confirmed live: mousedown, several mousemoves,
99
+ * mouseup, no `[draggable]` anywhere). Dropping a card on a column reparents
100
+ * it via `onCardsChange` (the parent owns the cards, so the move is a
101
+ * controlled state update). Measured from a deals pipeline.
55
102
  */
56
- export declare function Board<T extends BoardCard>({ columns, cards, onCardsChange, renderCard, onNewCard, newCardLabel: newCardLabelProp, getCardLabel, announceMove: announceMoveProp, calc, className, ...rest }: BoardProps<T>): React.JSX.Element;
103
+ export declare function Board<T extends BoardCard>({ columns, cards, onCardsChange, renderCard, onNewCard, newCardLabel: newCardLabelProp, getCardLabel, announceMove: announceMoveProp, calc, density, columnDensity: columnDensityProp, onColumnDensityChange, cardDensity: cardDensityProp, onCardDensityChange, collapseColumnsLabel: collapseColumnsLabelProp, expandColumnsLabel: expandColumnsLabelProp, collapseCardsLabel: collapseCardsLabelProp, expandCardsLabel: expandCardsLabelProp, columnDensityGroupLabel: columnDensityGroupLabelProp, cardDensityGroupLabel: cardDensityGroupLabelProp, onAddStage, addStageLabel: addStageLabelProp, className, ...rest }: BoardProps<T>): React.JSX.Element;
57
104
  export declare namespace Board {
58
105
  var displayName: string;
59
106
  }
@@ -99,11 +99,19 @@ export type CommentsPanelProps = Omit<React.ComponentPropsWithoutRef<"div">, "ch
99
99
  * live DOM, which is why a caret placed anywhere in the field, including
100
100
  * on top of a mention, can't corrupt what gets posted. */
101
101
  onPost: (text: string, threadId: string | null) => void;
102
- onReact: (threadId: string, commentId: string, emoji: string) => void;
102
+ /** Omit for a consumer with no reaction capability of its own (crisp#705's
103
+ * follow-up) — the hover "React" trigger and the reactions row's own
104
+ * "add" button both disappear, the same way omitting `onResolve` already
105
+ * drops "Resolve". Existing `comment.reactions` still render, read-only. */
106
+ onReact?: (threadId: string, commentId: string, emoji: string) => void;
103
107
  /** Resolving only ever applies to the thread as a whole (its root),
104
108
  * matching the live behaviour -- no per-reply resolve was found. */
105
109
  onResolve?: (threadId: string) => void;
106
- onDelete: (threadId: string, commentId: string) => void;
110
+ /** Omit for a consumer whose comments can't be deleted at all (crisp#705's
111
+ * follow-up — an audit-trail/sign-off record, e.g.) — the "Delete"
112
+ * item drops out of the row's "…" menu (Copy link, the only other item
113
+ * there, is unaffected) and the confirm dialog never opens. */
114
+ onDelete?: (threadId: string, commentId: string) => void;
107
115
  /** Defaults to copying `#comment-{commentId}` appended to the current
108
116
  * URL -- override for a real permalink scheme. */
109
117
  onCopyLink?: (threadId: string, commentId: string) => void;
@@ -112,7 +120,12 @@ export type CommentsPanelProps = Omit<React.ComponentPropsWithoutRef<"div">, "ch
112
120
  emojiOptions?: string[];
113
121
  mentionTrigger?: string;
114
122
  renderMentionPicker?: (state: CommentMentionTriggerState) => React.ReactNode;
115
- onClose: () => void;
123
+ /** Omit for a consumer with no separate open/close state of its own —
124
+ * embedded in a tab pane rather than a true slide-over/drawer, e.g.
125
+ * (crisp#738, the same reasoning #721 already applied to
126
+ * `onReact`/`onDelete`) — the header's close "✕" drops out rather than
127
+ * sitting there as a button that visibly does nothing. */
128
+ onClose?: () => void;
116
129
  closeLabel?: string;
117
130
  backLabel?: string;
118
131
  title?: string;
@@ -34,6 +34,7 @@ export type FormDialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title
34
34
  createMoreLabel?: string;
35
35
  cancelLabel?: string;
36
36
  discardTitle?: string;
37
+ discardDescription?: string;
37
38
  discardConfirmLabel?: string;
38
39
  discardCancelLabel?: string;
39
40
  };
@@ -51,7 +52,7 @@ export type FormDialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title
51
52
  * per-field wiring). A record needs several fields at once to be valid,
52
53
  * which is why records are not created by inline editing.
53
54
  */
54
- export declare function FormDialog({ title, submitLabel, onSubmit, onClose, busy, error, children, wide, size, createMode, createMoreLabel: createMoreLabelProp, cancelLabel: cancelLabelProp, discardTitle: discardTitleProp, discardConfirmLabel: discardConfirmLabelProp, discardCancelLabel: discardCancelLabelProp, className, ...rest }: FormDialogProps): React.JSX.Element;
55
+ export declare function FormDialog({ title, submitLabel, onSubmit, onClose, busy, error, children, wide, size, createMode, createMoreLabel: createMoreLabelProp, cancelLabel: cancelLabelProp, discardTitle: discardTitleProp, discardDescription: discardDescriptionProp, discardConfirmLabel: discardConfirmLabelProp, discardCancelLabel: discardCancelLabelProp, className, ...rest }: FormDialogProps): React.JSX.Element;
55
56
  export declare namespace FormDialog {
56
57
  var displayName: string;
57
58
  }
@@ -1 +1 @@
1
- export { NavItem, type NavItemProps } from "./navitem";
1
+ export { NavItem, type NavItemProps, type NavItemShortcut, } from "./navitem";
@@ -1,4 +1,21 @@
1
1
  import * as React from "react";
2
+ /**
3
+ * A row's hotkey hint (crisp#633, P-108) -- Attio's own "G then <letter>"
4
+ * tooltip, measured live on `product/companies`, `/people`, `/home`, etc.
5
+ * `description` is the tooltip's full sentence ("Go to all companies page"),
6
+ * NOT derived from the row's `children` (the short label) -- Attio's copy
7
+ * differs per row ("Go to all companies page" vs "Go to home page") in a way
8
+ * a template can't guess. `keys` is the whole chord in press order
9
+ * (`["g","c"]`), lower-case, same as Attio's own DOM text -- the visible
10
+ * upper-case letters are a CSS `text-transform`, not the source text a
11
+ * screen reader gets. Only some rows have one: Deals/Users/Workspaces/Calls/
12
+ * Sequences/Workflows showed no tooltip at all after a 1.2s hover, measured
13
+ * across repeated attempts -- left unset rather than guessed.
14
+ */
15
+ export type NavItemShortcut = {
16
+ description: string;
17
+ keys: string[];
18
+ };
2
19
  export type NavItemProps = React.ComponentPropsWithoutRef<"a"> & {
3
20
  asChild?: boolean;
4
21
  active?: boolean;
@@ -6,6 +23,9 @@ export type NavItemProps = React.ComponentPropsWithoutRef<"a"> & {
6
23
  icon?: React.ReactNode;
7
24
  /** Right-aligned content (count badge / options). */
8
25
  trailing?: React.ReactNode;
26
+ /** The hotkey hint tooltip (see `NavItemShortcut`). Omit for no tooltip
27
+ * (unchanged default). */
28
+ shortcut?: NavItemShortcut;
9
29
  };
10
30
  export declare const NavItem: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "ref"> & {
11
31
  asChild?: boolean;
@@ -14,4 +34,7 @@ export declare const NavItem: React.ForwardRefExoticComponent<Omit<React.Detaile
14
34
  icon?: React.ReactNode;
15
35
  /** Right-aligned content (count badge / options). */
16
36
  trailing?: React.ReactNode;
37
+ /** The hotkey hint tooltip (see `NavItemShortcut`). Omit for no tooltip
38
+ * (unchanged default). */
39
+ shortcut?: NavItemShortcut;
17
40
  } & React.RefAttributes<HTMLAnchorElement>>;
@@ -1,2 +1,2 @@
1
- export { ATTRIBUTE_AI_AUTOFILL_OPTIONS, ATTRIBUTE_TYPE_OPTIONS, type AttributeRow, AttributesTable, type AttributesTableProps, type AttributeTypeOption, AttributeTypeSelect, type AttributeTypeSelectProps, CreateAttributeDialog, type CreateAttributeDialogProps, ObjectAppearanceSection, type ObjectAppearanceSectionProps, ObjectDetailPage, type ObjectDetailPageProps, type ObjectDetailTab, ObjectGeneralSection, type ObjectGeneralSectionProps, ObjectSettings, type ObjectSummary, ObjectsList, type ObjectsListProps, } from "./objectsettings";
1
+ export { ATTRIBUTE_AI_AUTOFILL_OPTIONS, ATTRIBUTE_TYPE_OPTIONS, type AttributeRow, AttributesTable, type AttributesTableProps, type AttributeTypeOption, AttributeTypeSelect, type AttributeTypeSelectProps, CreateAttributeDialog, type CreateAttributeDialogProps, ObjectAppearanceSection, type ObjectAppearanceSectionProps, ObjectDetailPage, type ObjectDetailPageProps, type ObjectDetailTab, ObjectGeneralSection, type ObjectGeneralSectionProps, type ObjectSummary, ObjectsList, type ObjectsListProps, } from "./objectsettings";
2
2
  export { objectsettingsRecipe } from "./objectsettings.recipe";
@@ -249,13 +249,3 @@ export declare function CreateAttributeDialog({ type, onTypeChange, typeOptions,
249
249
  export declare namespace CreateAttributeDialog {
250
250
  var displayName: string;
251
251
  }
252
- /**
253
- * This folder holds several components (`ObjectsList`, `ObjectDetailPage`,
254
- * `AttributesTable`, `CreateAttributeDialog`, …), not one named after the
255
- * slug — unlike every other product dir, whose docs `<ManualInstallation>`
256
- * resolves an import binding from the folder slug ("avatargroup" →
257
- * `AvatarGroup`) by reading this file's exports. This alias exists only so
258
- * that resolver finds a match for "objectsettings"; consumers should import
259
- * the real names above, never this one.
260
- */
261
- export declare const ObjectSettings: typeof ObjectsList;
@@ -228,7 +228,6 @@ export type RecordsTableLabels = {
228
228
  selectionAnnouncement: (count: number) => string;
229
229
  delete: string;
230
230
  sendEmail: string;
231
- exportCsv: string;
232
231
  runWorkflow: string;
233
232
  calculate: string;
234
233
  emptyPlaceholder: string;
@@ -6,6 +6,27 @@ export type SavedView = {
6
6
  icon?: React.ReactNode;
7
7
  /** Renders a small shared-view indicator next to the name. */
8
8
  shared?: boolean;
9
+ /**
10
+ * Text matched against the switcher's own search box (#618) when `name`
11
+ * isn't a plain string — same fallback `Select`'s own `keywords` already
12
+ * gives a non-string `label`. Falls back to `id` when `name` is also
13
+ * non-string and this is omitted, the same way `Select`'s own
14
+ * `optionText` falls back to `value` — a view with a rich, non-string
15
+ * name and no `keywords` still matches SOME query (its own id) rather
16
+ * than becoming permanently unfindable by search.
17
+ */
18
+ keywords?: string;
19
+ /**
20
+ * "Created by …" — the first line of the kebab menu's own footer row
21
+ * (#618, measured live: "Created by Attio system" / "26th Aug 2026
22
+ * 12:20 PM", two stacked lines). Renders only the line(s) actually
23
+ * given — omit both for a view with no author/date metadata and the
24
+ * footer (and its divider) don't render at all.
25
+ */
26
+ createdBy?: React.ReactNode;
27
+ /** The footer's second line — a pre-formatted date/time, since crisp
28
+ * doesn't own locale formatting. See `createdBy`. */
29
+ createdAt?: React.ReactNode;
9
30
  };
10
31
  export type SavedViewsProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "onSelect"> & {
11
32
  /** The trigger's label when no view is active (Attio's "All Companies"). */
@@ -32,6 +53,18 @@ export type SavedViewsProps = Omit<React.ComponentPropsWithoutRef<"div">, "child
32
53
  viewOptionsLabel?: string;
33
54
  /** aria-label for the panel itself (defaults to the resolved trigger label). */
34
55
  "aria-label"?: string;
56
+ /** Placeholder on the panel's own search box (default "Search views..." —
57
+ * Attio's own text, measured live: 3 literal dots, not an ellipsis
58
+ * glyph). */
59
+ searchPlaceholder?: string;
60
+ /** aria-label on the search box (default "Filter views" — Attio's own
61
+ * measured aria-label, distinct from its placeholder text). */
62
+ searchLabel?: string;
63
+ /** Shown in place of the view list when a search matches nothing (default
64
+ * "No results" — the same text and contract `Select`'s own `searchable`
65
+ * empty state already uses). The "Create new view" row still renders
66
+ * below it either way. */
67
+ emptyLabel?: string;
35
68
  className?: string;
36
69
  };
37
70
  /**
@@ -40,16 +73,20 @@ export type SavedViewsProps = Omit<React.ComponentPropsWithoutRef<"div">, "child
40
73
  * row (leading coloured icon, name, a hover-revealed kebab of
41
74
  * rename/duplicate/delete), plus a trailing "Create new view" row. The
42
75
  * active view is marked `aria-selected`/`aria-current="page"` and mirrored
43
- * onto the trigger's own icon/label.
76
+ * onto the trigger's own icon/label. The panel opens on a "Search views..."
77
+ * box (#618, P-007) — real DOM focus moves there (`requestAnimationFrame`,
78
+ * same race `Select`'s own `searchable` variant already guards against),
79
+ * not virtual focus on the trigger.
44
80
  *
45
- * Keyboard: while the trigger has focus and the panel is open, ↑/↓ move a
46
- * virtual highlight (`aria-activedescendant`, the same "focus stays on the
47
- * trigger" model `Select`/`MultiSelect` use without a search field), Enter
48
- * chooses the highlighted row, Escape closes — deferring to a still-open
49
- * kebab submenu first (`hasOpenFloatingLayer`), so Escape closes one layer
50
- * at a time.
81
+ * Keyboard: while the panel is open, focus lives on the search input — ↑/↓
82
+ * move a virtual highlight (`aria-activedescendant`) over the (possibly
83
+ * filtered) view list, Enter chooses the highlighted row, Escape closes,
84
+ * deferring to a still-open kebab submenu first (`hasOpenFloatingLayer`),
85
+ * so Escape closes one layer at a time — the same split `Select`'s own
86
+ * `searchable` variant already uses between its trigger and its own search
87
+ * input.
51
88
  */
52
- export declare function SavedViews({ label, icon, views, activeId, onSelect, onCreate, onRename, onDuplicate, onDelete, onToggleFavorite, createLabel: createLabelProp, renameLabel: renameLabelProp, duplicateLabel: duplicateLabelProp, deleteLabel: deleteLabelProp, favoriteLabel: favoriteLabelProp, viewOptionsLabel: viewOptionsLabelProp, className, "aria-label": ariaLabel, ...rest }: SavedViewsProps): React.JSX.Element;
89
+ export declare function SavedViews({ label, icon, views, activeId, onSelect, onCreate, onRename, onDuplicate, onDelete, onToggleFavorite, createLabel: createLabelProp, renameLabel: renameLabelProp, duplicateLabel: duplicateLabelProp, deleteLabel: deleteLabelProp, favoriteLabel: favoriteLabelProp, viewOptionsLabel: viewOptionsLabelProp, searchPlaceholder: searchPlaceholderProp, searchLabel: searchLabelProp, emptyLabel: emptyLabelProp, className, "aria-label": ariaLabel, ...rest }: SavedViewsProps): React.JSX.Element;
53
90
  export declare namespace SavedViews {
54
91
  var displayName: string;
55
92
  }