@crisp-ui-kit/crisp 0.57.2 → 0.57.4

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 (200) hide show
  1. package/dist/assigneepicker.css +13 -0
  2. package/dist/assigneepicker.d.ts +7 -0
  3. package/dist/assigneepicker.layered.css +15 -0
  4. package/dist/button.css +3 -0
  5. package/dist/button.d.ts +2 -2
  6. package/dist/button.layered.css +3 -0
  7. package/dist/chip.css +1 -1
  8. package/dist/chip.layered.css +1 -1
  9. package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
  10. package/dist/cjs/components/button/button.recipe.js +33 -0
  11. package/dist/cjs/components/chip/chip.recipe.js +3 -1
  12. package/dist/cjs/components/datatable/datatable.js +6 -3
  13. package/dist/cjs/components/datatable/datatable.recipe.js +45 -6
  14. package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
  15. package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
  16. package/dist/cjs/components/menu/menu.js +65 -9
  17. package/dist/cjs/components/multiselect/multiselect.js +3 -0
  18. package/dist/cjs/components/multiselect/multiselect.recipe.js +18 -0
  19. package/dist/cjs/components/select/select.js +2 -2
  20. package/dist/cjs/components/select/select.recipe.js +19 -0
  21. package/dist/cjs/components/table/table.recipe.js +7 -1
  22. package/dist/cjs/core/floating-portal.js +7 -4
  23. package/dist/cjs/core/index.js +2 -1
  24. package/dist/cjs/core/place-floating.js +38 -0
  25. package/dist/cjs/index.js +8 -0
  26. package/dist/cjs/product/assigneepicker/assigneepicker.js +127 -0
  27. package/dist/cjs/product/assigneepicker/assigneepicker.recipe.js +36 -0
  28. package/dist/cjs/product/assigneepicker/index.js +7 -0
  29. package/dist/cjs/product/inbox/inbox.js +11 -3
  30. package/dist/cjs/product/notesgallery/index.js +7 -0
  31. package/dist/cjs/product/notesgallery/notesgallery.js +80 -0
  32. package/dist/cjs/product/notesgallery/notesgallery.recipe.js +46 -0
  33. package/dist/cjs/product/objectpagemenu/index.js +17 -0
  34. package/dist/cjs/product/objectpagemenu/objectpagemenu.js +26 -0
  35. package/dist/cjs/product/objectpagemenu/objectpagemenu.recipe.js +30 -0
  36. package/dist/cjs/product/objectsettings/objectsettings.js +107 -14
  37. package/dist/cjs/product/recordpage/index.js +2 -1
  38. package/dist/cjs/product/recordpage/recordpage.js +112 -7
  39. package/dist/cjs/product/recordpage/recordpage.recipe.js +63 -0
  40. package/dist/cjs/product/recordpicker/index.js +7 -0
  41. package/dist/cjs/product/recordpicker/recordpicker.js +100 -0
  42. package/dist/cjs/product/recordpicker/recordpicker.recipe.js +36 -0
  43. package/dist/cjs/product/savedviews/index.js +2 -1
  44. package/dist/cjs/product/savedviews/savedviews.js +22 -0
  45. package/dist/cjs/product/savedviews/savedviews.recipe.js +47 -0
  46. package/dist/cjs/product/share/index.js +7 -0
  47. package/dist/cjs/product/share/share.js +179 -0
  48. package/dist/cjs/product/share/share.recipe.js +114 -0
  49. package/dist/cjs/product/shortcutssheet/index.js +17 -0
  50. package/dist/cjs/product/shortcutssheet/shortcutssheet.js +125 -0
  51. package/dist/cjs/product/shortcutssheet/shortcutssheet.recipe.js +50 -0
  52. package/dist/cjs/product/taskeditpopover/index.js +7 -0
  53. package/dist/cjs/product/taskeditpopover/taskeditpopover.js +159 -0
  54. package/dist/cjs/product/taskeditpopover/taskeditpopover.recipe.js +68 -0
  55. package/dist/cjs/product/workspaceswitchermenu/index.js +17 -0
  56. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.js +38 -0
  57. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +34 -0
  58. package/dist/cjs/tokens/palette.js +27 -0
  59. package/dist/cjs/tokens/semantic.js +20 -0
  60. package/dist/datatable.css +50 -11
  61. package/dist/datatable.layered.css +50 -11
  62. package/dist/datepickerfield.css +8 -2
  63. package/dist/datepickerfield.d.ts +2 -2
  64. package/dist/datepickerfield.layered.css +8 -2
  65. package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
  66. package/dist/esm/components/button/button.recipe.js +33 -0
  67. package/dist/esm/components/chip/chip.recipe.js +3 -1
  68. package/dist/esm/components/datatable/datatable.js +6 -3
  69. package/dist/esm/components/datatable/datatable.recipe.js +45 -6
  70. package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
  71. package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
  72. package/dist/esm/components/menu/menu.js +64 -8
  73. package/dist/esm/components/multiselect/multiselect.js +3 -0
  74. package/dist/esm/components/multiselect/multiselect.recipe.js +18 -0
  75. package/dist/esm/components/select/select.js +2 -2
  76. package/dist/esm/components/select/select.recipe.js +19 -0
  77. package/dist/esm/components/table/table.recipe.js +7 -1
  78. package/dist/esm/core/floating-portal.js +7 -4
  79. package/dist/esm/core/index.js +1 -1
  80. package/dist/esm/core/place-floating.js +37 -0
  81. package/dist/esm/index.js +8 -0
  82. package/dist/esm/product/assigneepicker/assigneepicker.js +91 -0
  83. package/dist/esm/product/assigneepicker/assigneepicker.recipe.js +33 -0
  84. package/dist/esm/product/assigneepicker/index.js +2 -0
  85. package/dist/esm/product/inbox/inbox.js +11 -3
  86. package/dist/esm/product/notesgallery/index.js +2 -0
  87. package/dist/esm/product/notesgallery/notesgallery.js +44 -0
  88. package/dist/esm/product/notesgallery/notesgallery.recipe.js +43 -0
  89. package/dist/esm/product/objectpagemenu/index.js +1 -0
  90. package/dist/esm/product/objectpagemenu/objectpagemenu.js +23 -0
  91. package/dist/esm/product/objectpagemenu/objectpagemenu.recipe.js +27 -0
  92. package/dist/esm/product/objectsettings/objectsettings.js +106 -13
  93. package/dist/esm/product/recordpage/index.js +1 -1
  94. package/dist/esm/product/recordpage/recordpage.js +112 -8
  95. package/dist/esm/product/recordpage/recordpage.recipe.js +63 -0
  96. package/dist/esm/product/recordpicker/index.js +2 -0
  97. package/dist/esm/product/recordpicker/recordpicker.js +64 -0
  98. package/dist/esm/product/recordpicker/recordpicker.recipe.js +33 -0
  99. package/dist/esm/product/savedviews/index.js +1 -1
  100. package/dist/esm/product/savedviews/savedviews.js +22 -1
  101. package/dist/esm/product/savedviews/savedviews.recipe.js +47 -0
  102. package/dist/esm/product/share/index.js +2 -0
  103. package/dist/esm/product/share/share.js +143 -0
  104. package/dist/esm/product/share/share.recipe.js +111 -0
  105. package/dist/esm/product/shortcutssheet/index.js +1 -0
  106. package/dist/esm/product/shortcutssheet/shortcutssheet.js +88 -0
  107. package/dist/esm/product/shortcutssheet/shortcutssheet.recipe.js +47 -0
  108. package/dist/esm/product/taskeditpopover/index.js +2 -0
  109. package/dist/esm/product/taskeditpopover/taskeditpopover.js +123 -0
  110. package/dist/esm/product/taskeditpopover/taskeditpopover.recipe.js +65 -0
  111. package/dist/esm/product/workspaceswitchermenu/index.js +1 -0
  112. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.js +35 -0
  113. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +31 -0
  114. package/dist/esm/tokens/palette.js +27 -0
  115. package/dist/esm/tokens/semantic.js +20 -0
  116. package/dist/multiselect.css +18 -0
  117. package/dist/multiselect.layered.css +18 -0
  118. package/dist/native/tokens.d.ts +1 -1
  119. package/dist/native/tokens.js +56 -4
  120. package/dist/notesgallery.css +15 -0
  121. package/dist/notesgallery.d.ts +7 -0
  122. package/dist/notesgallery.layered.css +17 -0
  123. package/dist/objectpagemenu.css +3 -0
  124. package/dist/objectpagemenu.d.ts +7 -0
  125. package/dist/objectpagemenu.layered.css +5 -0
  126. package/dist/recordpage.css +59 -0
  127. package/dist/recordpage.layered.css +59 -0
  128. package/dist/recordpicker.css +13 -0
  129. package/dist/recordpicker.d.ts +7 -0
  130. package/dist/recordpicker.layered.css +15 -0
  131. package/dist/savedviews.css +47 -0
  132. package/dist/savedviews.layered.css +47 -0
  133. package/dist/select.css +19 -0
  134. package/dist/select.layered.css +19 -0
  135. package/dist/share.css +84 -0
  136. package/dist/share.d.ts +7 -0
  137. package/dist/share.layered.css +86 -0
  138. package/dist/shortcutssheet.css +24 -0
  139. package/dist/shortcutssheet.d.ts +7 -0
  140. package/dist/shortcutssheet.layered.css +26 -0
  141. package/dist/styles.css +438 -16
  142. package/dist/styles.layered.css +438 -16
  143. package/dist/table.css +7 -2
  144. package/dist/table.layered.css +7 -2
  145. package/dist/taskeditpopover.css +36 -0
  146. package/dist/taskeditpopover.d.ts +7 -0
  147. package/dist/taskeditpopover.layered.css +38 -0
  148. package/dist/tokens.css +26 -0
  149. package/dist/tokens.json +56 -4
  150. package/dist/types/components/breadcrumb/breadcrumb.d.ts +9 -1
  151. package/dist/types/components/button/button.d.ts +2 -0
  152. package/dist/types/components/button/button.recipe.d.ts +12 -0
  153. package/dist/types/components/chip/chip.recipe.d.ts +1 -1
  154. package/dist/types/components/datatable/datatable.d.ts +8 -0
  155. package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
  156. package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
  157. package/dist/types/components/menu/menu.d.ts +50 -7
  158. package/dist/types/components/multiselect/multiselect.d.ts +9 -0
  159. package/dist/types/components/select/select.d.ts +10 -0
  160. package/dist/types/core/floating-portal.d.ts +6 -5
  161. package/dist/types/core/index.d.ts +1 -1
  162. package/dist/types/core/place-floating.d.ts +37 -0
  163. package/dist/types/index.d.ts +8 -0
  164. package/dist/types/product/assigneepicker/assigneepicker.d.ts +36 -0
  165. package/dist/types/product/assigneepicker/assigneepicker.recipe.d.ts +3 -0
  166. package/dist/types/product/assigneepicker/index.d.ts +2 -0
  167. package/dist/types/product/inbox/inbox.d.ts +13 -1
  168. package/dist/types/product/notesgallery/index.d.ts +2 -0
  169. package/dist/types/product/notesgallery/notesgallery.d.ts +54 -0
  170. package/dist/types/product/notesgallery/notesgallery.recipe.d.ts +3 -0
  171. package/dist/types/product/objectpagemenu/index.d.ts +1 -0
  172. package/dist/types/product/objectpagemenu/objectpagemenu.d.ts +40 -0
  173. package/dist/types/product/objectpagemenu/objectpagemenu.recipe.d.ts +17 -0
  174. package/dist/types/product/objectsettings/objectsettings.d.ts +71 -15
  175. package/dist/types/product/recordpage/index.d.ts +1 -1
  176. package/dist/types/product/recordpage/recordpage.d.ts +142 -1
  177. package/dist/types/product/recordpicker/index.d.ts +2 -0
  178. package/dist/types/product/recordpicker/recordpicker.d.ts +38 -0
  179. package/dist/types/product/recordpicker/recordpicker.recipe.d.ts +3 -0
  180. package/dist/types/product/savedviews/index.d.ts +1 -1
  181. package/dist/types/product/savedviews/savedviews.d.ts +36 -0
  182. package/dist/types/product/share/index.d.ts +2 -0
  183. package/dist/types/product/share/share.d.ts +85 -0
  184. package/dist/types/product/share/share.recipe.d.ts +3 -0
  185. package/dist/types/product/shortcutssheet/index.d.ts +1 -0
  186. package/dist/types/product/shortcutssheet/shortcutssheet.d.ts +49 -0
  187. package/dist/types/product/shortcutssheet/shortcutssheet.recipe.d.ts +3 -0
  188. package/dist/types/product/taskeditpopover/index.d.ts +2 -0
  189. package/dist/types/product/taskeditpopover/taskeditpopover.d.ts +67 -0
  190. package/dist/types/product/taskeditpopover/taskeditpopover.recipe.d.ts +3 -0
  191. package/dist/types/product/workspaceswitchermenu/index.d.ts +1 -0
  192. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.d.ts +54 -0
  193. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.recipe.d.ts +19 -0
  194. package/dist/types/tokens/contract.d.ts +13 -0
  195. package/dist/types/tokens/palette.d.ts +52 -0
  196. package/dist/types/tokens/semantic.d.ts +20 -0
  197. package/dist/workspaceswitchermenu.css +4 -0
  198. package/dist/workspaceswitchermenu.d.ts +7 -0
  199. package/dist/workspaceswitchermenu.layered.css +6 -0
  200. package/package.json +41 -1
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+ export type AssigneePickerUser = {
3
+ id: string;
4
+ name: string;
5
+ /** A photo URL; falls back to a per-name hashed-colour initials tile,
6
+ * same as `PersonChip`'s own. */
7
+ avatar?: string;
8
+ };
9
+ export type AssigneePickerProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
10
+ /** Candidate users, already excluding nobody in particular -- the
11
+ * current `assignee` is filtered out of the list automatically. */
12
+ users: AssigneePickerUser[];
13
+ /** The task's current single assignee, or `null`/omitted for none. */
14
+ assignee?: AssigneePickerUser | null;
15
+ onAssigneeChange?: (user: AssigneePickerUser | null) => void;
16
+ /** Controlled search query. Omit to let the picker manage it. */
17
+ query?: string;
18
+ onQueryChange?: (query: string) => void;
19
+ searchLabel?: string;
20
+ removeLabel?: string;
21
+ emptyLabel?: React.ReactNode;
22
+ className?: string;
23
+ };
24
+ /**
25
+ * The picker behind a task's "Assigned to" chip -- measured live on
26
+ * app.attio.com's Tasks page ("Edit task" -> "Assigned to You" -> its own
27
+ * sub-popover, `Popover`-sized at the same measured 350px): a "Find a
28
+ * user..." search, the current assignee as a removable pill, then a plain
29
+ * option list, or "No users" when nothing matches. Attio's task assignment
30
+ * is single-user (one pill, replaced by picking another), unlike a
31
+ * multi-value field.
32
+ */
33
+ export declare function AssigneePicker({ users, assignee, onAssigneeChange, query: queryProp, onQueryChange, searchLabel: searchLabelProp, removeLabel: removeLabelProp, emptyLabel: emptyLabelProp, className, ...rest }: AssigneePickerProps): React.JSX.Element;
34
+ export declare namespace AssigneePicker {
35
+ var displayName: string;
36
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const assigneepickerRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { AssigneePicker, type AssigneePickerProps, type AssigneePickerUser, } from "./assigneepicker";
2
+ export { assigneepickerRecipe } from "./assigneepicker.recipe";
@@ -15,6 +15,14 @@ export type InboxTab = {
15
15
  label: React.ReactNode;
16
16
  count?: number;
17
17
  disabled?: boolean;
18
+ /**
19
+ * Empty-state copy for this tab only, e.g. Notifications vs. Requests
20
+ * ("Requests from other users will be displayed here."). Falls back to
21
+ * the instance-level `emptyTitle`/`emptySubtitle`/`emptyAction` when unset.
22
+ */
23
+ emptyTitle?: React.ReactNode;
24
+ emptySubtitle?: React.ReactNode;
25
+ emptyAction?: React.ReactNode;
18
26
  };
19
27
  export type InboxProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "title"> & {
20
28
  notifications?: InboxNotification[];
@@ -23,7 +31,11 @@ export type InboxProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"
23
31
  tabs?: InboxTab[];
24
32
  activeTab?: string;
25
33
  onTabChange?: (id: string) => void;
26
- /** Empty-state text (shown when there are no notifications). */
34
+ /**
35
+ * Empty-state text (shown when there are no notifications). A tab in
36
+ * `tabs` that sets its own `emptyTitle`/`emptySubtitle` overrides this
37
+ * for that tab only.
38
+ */
27
39
  emptyTitle?: React.ReactNode;
28
40
  emptySubtitle?: React.ReactNode;
29
41
  /** Optional action under the empty state (e.g. a Settings button). */
@@ -0,0 +1,2 @@
1
+ export { NotesGallery, type NotesGalleryGroup, type NotesGalleryNote, type NotesGalleryProps, } from "./notesgallery";
2
+ export { notesgalleryRecipe } from "./notesgallery.recipe";
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ export type NotesGalleryNote = {
3
+ id: string;
4
+ /** Rendered in the card's leading author-row slot — Attio's own is a
5
+ * linked-record icon+name, not the note's author (that's the footer). */
6
+ linkedRecord?: React.ReactNode;
7
+ title: React.ReactNode;
8
+ excerpt?: React.ReactNode;
9
+ /** Footer row content, e.g. an avatar+name. */
10
+ author?: React.ReactNode;
11
+ date?: React.ReactNode;
12
+ onClick?: () => void;
13
+ };
14
+ export type NotesGalleryGroup = {
15
+ id: string;
16
+ /** e.g. "Created last month". */
17
+ label: React.ReactNode;
18
+ count: number;
19
+ notes: NotesGalleryNote[];
20
+ };
21
+ export type NotesGalleryProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
22
+ notesCount: number;
23
+ templatesCount: number;
24
+ /** "notes" | "templates" (or any consumer-chosen values via `tabValues`). */
25
+ activeTab?: string;
26
+ defaultActiveTab?: string;
27
+ onActiveTabChange?: (value: string) => void;
28
+ notesLabel?: string;
29
+ templatesLabel?: string;
30
+ /** e.g. a "Sorted by Creation date" trigger. */
31
+ leading?: React.ReactNode;
32
+ /** e.g. a list/grid `ViewToggle`, "View settings", "+ New note". */
33
+ trailing?: React.ReactNode;
34
+ favoritesLabel?: string;
35
+ /** Favorited note cards. Omit (or pass an empty array) for the measured
36
+ * dashed empty panel. */
37
+ favorites?: NotesGalleryNote[];
38
+ favoritesEmptyLabel?: string;
39
+ groups: NotesGalleryGroup[];
40
+ emptyLabel?: React.ReactNode;
41
+ className?: string;
42
+ };
43
+ /**
44
+ * The standalone Notes gallery -- measured live on app.attio.com's Notes
45
+ * page: "Notes N"/"Templates N" sub-tabs, a toolbar (Sort/View
46
+ * toggle/settings/New note, all consumer-composed), a dashed "Favorites"
47
+ * region, and date-grouped card sections. The card itself is `EntityCard`
48
+ * (crisp#474's own "measured from a Notes grid" component) — this shell
49
+ * only adds the gallery chrome around it.
50
+ */
51
+ export declare function NotesGallery({ notesCount, templatesCount, activeTab: activeTabProp, defaultActiveTab, onActiveTabChange, notesLabel: notesLabelProp, templatesLabel: templatesLabelProp, leading, trailing, favoritesLabel: favoritesLabelProp, favorites, favoritesEmptyLabel: favoritesEmptyLabelProp, groups, emptyLabel: emptyLabelProp, className, ...rest }: NotesGalleryProps): React.JSX.Element;
52
+ export declare namespace NotesGallery {
53
+ var displayName: string;
54
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const notesgalleryRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1 @@
1
+ export * from "./objectpagemenu";
@@ -0,0 +1,40 @@
1
+ import type * as React from "react";
2
+ export type ObjectPageMenuProps = {
3
+ /** The element that opens the menu. Default: the measured 28px ghost
4
+ * icon button Attio uses for its own "…" — pass one only to change the
5
+ * trigger itself; the menu content below is fixed (Attio's own chrome,
6
+ * not app-specific data — the same reasoning `defaultCommandItems`
7
+ * already ships on). */
8
+ trigger?: React.ReactElement;
9
+ /** Fires when "Object settings" is selected. */
10
+ onObjectSettings?: () => void;
11
+ /** Fires when "Manage attributes" is selected. */
12
+ onManageAttributes?: () => void;
13
+ /** Fires when "Connect Slack workspace" is selected, inside the
14
+ * Notifications submenu. */
15
+ onConnectSlack?: () => void;
16
+ objectSettingsLabel?: string;
17
+ manageAttributesLabel?: string;
18
+ notificationsLabel?: string;
19
+ connectSlackLabel?: string;
20
+ /** Accessible name for the trigger button (unused when a custom
21
+ * `trigger` is given). */
22
+ "aria-label"?: string;
23
+ /** Which of the trigger's edges the menu lines up with (default `"end"`,
24
+ * matching Attio's own right-aligned placement under the "…" button at
25
+ * the far right of the page header). */
26
+ align?: "start" | "end";
27
+ };
28
+ /**
29
+ * The page-level "…" menu on Attio's object page: Object settings / Manage
30
+ * attributes / a Notifications submenu ("Connect Slack workspace") — crisp
31
+ * parity checklist rows G-020/P-005 (crisp#616). Live-measured on
32
+ * app.attio.com/techpartners/companies: 208×114 popover (12px radius, 4px
33
+ * padding, 32px rows), a hairline separator before Notifications, and its
34
+ * submenu opening flush against the item with no gap, flipping side when
35
+ * the measured width doesn't fit (`placeSubmenu`, core/place-floating.ts).
36
+ */
37
+ export declare function ObjectPageMenu({ trigger, onObjectSettings, onManageAttributes, onConnectSlack, objectSettingsLabel, manageAttributesLabel, notificationsLabel, connectSlackLabel, "aria-label": ariaLabelProp, align, }: ObjectPageMenuProps): React.JSX.Element;
38
+ export declare namespace ObjectPageMenu {
39
+ var displayName: string;
40
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `ObjectPageMenu` owns no styling of its own — every visible pixel is
3
+ * `Menu`/`MenuItem`'s own already-measured recipe. The one thing it DOES
4
+ * need is the RTL mirror for its Notifications submenu chevron (crisp#616):
5
+ * that icon is the first direction-bearing one ever passed as a `MenuItem`
6
+ * `trailingIcon`, so nothing already mirrors it.
7
+ *
8
+ * Not written as `${rtlFlipCss}` (core/rtl.ts): that string relies on native
9
+ * CSS nesting's `&` resolving to an ENCLOSING rule, which is exactly what
10
+ * `Menu`'s own recipe deliberately avoids for its portaled content (see its
11
+ * own doc comment) — nesting this under a `.crisp-objectpagemenu` root would
12
+ * need a root class this component doesn't have. A plain absolute selector,
13
+ * matching `Menu`'s own pattern for the identical reason.
14
+ */
15
+ declare const config: import("../..").RecipeConfig<{}>;
16
+ export declare const objectpagemenuRecipe: import("../..").RecipeFn<{}>;
17
+ export default config;
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { SelectOption } from "../../components/select";
2
3
  export type ObjectSummary = {
3
4
  id: string;
4
5
  name: React.ReactNode;
@@ -127,6 +128,9 @@ export type AttributeRow = {
127
128
  dataType: React.ReactNode;
128
129
  /** e.g. "Unique" — rendered as a plain constraint label per row. */
129
130
  constraint?: React.ReactNode;
131
+ /** The attribute's own slug (crisp#673, G-107) — "Copy slug" needs
132
+ * something to copy; omit on a row with no slug of its own yet. */
133
+ slug?: string;
130
134
  system?: boolean;
131
135
  enriched?: boolean;
132
136
  };
@@ -134,6 +138,21 @@ export type AttributesTableProps = {
134
138
  attributes: AttributeRow[];
135
139
  onOpenAttribute?: (id: string) => void;
136
140
  onEditAttribute?: (id: string) => void;
141
+ /** crisp#673, G-107. */
142
+ onDuplicateAttribute?: (id: string) => void;
143
+ /** Defaults to a real `navigator.clipboard.writeText(id)` when omitted —
144
+ * the same default-with-override shape `CommentsPanel`'s `onCopyLink`
145
+ * already has, so a consumer only needs this to know when it happened
146
+ * (a toast, analytics), not to implement the copy itself. */
147
+ onCopyId?: (id: string) => void;
148
+ /** Same default-clipboard-write shape as `onCopyId`, over the row's own
149
+ * `slug`. A row with no `slug` renders the item disabled rather than
150
+ * copying an empty string. */
151
+ onCopySlug?: (slug: string) => void;
152
+ /** Opens Attio's own rename-slug flow — crisp models no slug-editing UI
153
+ * of its own (out of scope, same reasoning as the plan-gated notices
154
+ * elsewhere), just the entry point into it. */
155
+ onChangeSlug?: (id: string) => void;
137
156
  onArchiveAttribute?: (id: string) => void;
138
157
  onReorder?: (rows: AttributeRow[]) => void;
139
158
  onCreateAttribute?: () => void;
@@ -149,14 +168,20 @@ export type AttributesTableProps = {
149
168
  systemLabel?: string;
150
169
  enrichedLabel?: string;
151
170
  editLabel?: string;
171
+ duplicateLabel?: string;
172
+ copyIdLabel?: string;
173
+ copySlugLabel?: string;
174
+ changeSlugLabel?: string;
152
175
  archiveLabel?: string;
153
176
  /** Overrides the row "…" menu entirely — return the `MenuItem`s a
154
- * consumer's own actions need (crisp#660). Attio's own row menu is
155
- * Edit/Archive (the default, unchanged when this is omitted); a
156
- * consumer whose data isn't Attio's own attribute model (no "archive"
157
- * concept, a different action set entirely) supplies its own instead of
158
- * working around two fixed items that don't fit. Receives the row so an
159
- * item's handler can close over its id. */
177
+ * consumer's own actions need (crisp#660). Attio's own row menu (crisp#673,
178
+ * G-107, corrects this comment's former "Edit/Archive" claim — the real
179
+ * menu has six items) is Edit attribute/Duplicate attribute/Copy ID/Copy
180
+ * slug/Change slug/Archive attribute (the default, unchanged when this is
181
+ * omitted); a consumer whose data isn't Attio's own attribute model (no
182
+ * "archive"/"slug" concept, a different action set entirely) supplies its
183
+ * own instead of working around six fixed items that don't fit. Receives
184
+ * the row so an item's handler can close over its id. */
160
185
  rowActions?: (row: AttributeRow) => React.ReactNode;
161
186
  emptyLabel?: React.ReactNode;
162
187
  };
@@ -169,7 +194,7 @@ export type AttributesTableProps = {
169
194
  * measures 40px here — a real, small divergence left to DataTable's owner
170
195
  * rather than patched locally (see the PR).
171
196
  */
172
- export declare function AttributesTable({ attributes, onOpenAttribute, onEditAttribute, onArchiveAttribute, onReorder, onCreateAttribute, title: titleProp, subtitle: subtitleProp, createLabel: createLabelProp, searchPlaceholder: searchPlaceholderProp, filterLabel: filterLabelProp, nameColumnLabel: nameColumnLabelProp, dataTypeColumnLabel: dataTypeColumnLabelProp, constraintsColumnLabel: constraintsColumnLabelProp, propertiesColumnLabel: propertiesColumnLabelProp, systemLabel: systemLabelProp, enrichedLabel: enrichedLabelProp, editLabel: editLabelProp, archiveLabel: archiveLabelProp, rowActions, emptyLabel, }: AttributesTableProps): React.JSX.Element;
197
+ export declare function AttributesTable({ attributes, onOpenAttribute, onEditAttribute, onDuplicateAttribute, onCopyId, onCopySlug, onChangeSlug, onArchiveAttribute, onReorder, onCreateAttribute, title: titleProp, subtitle: subtitleProp, createLabel: createLabelProp, searchPlaceholder: searchPlaceholderProp, filterLabel: filterLabelProp, nameColumnLabel: nameColumnLabelProp, dataTypeColumnLabel: dataTypeColumnLabelProp, constraintsColumnLabel: constraintsColumnLabelProp, propertiesColumnLabel: propertiesColumnLabelProp, systemLabel: systemLabelProp, enrichedLabel: enrichedLabelProp, editLabel: editLabelProp, duplicateLabel: duplicateLabelProp, copyIdLabel: copyIdLabelProp, copySlugLabel: copySlugLabelProp, changeSlugLabel: changeSlugLabelProp, archiveLabel: archiveLabelProp, rowActions, emptyLabel, }: AttributesTableProps): React.JSX.Element;
173
198
  export declare namespace AttributesTable {
174
199
  var displayName: string;
175
200
  }
@@ -212,6 +237,9 @@ export declare function AttributeTypeSelect({ value, onValueChange, options, aiA
212
237
  export declare namespace AttributeTypeSelect {
213
238
  var displayName: string;
214
239
  }
240
+ export declare const CURRENCY_DISPLAY_OPTIONS: SelectOption[];
241
+ export declare const CURRENCY_DECIMAL_PLACES_OPTIONS: SelectOption[];
242
+ export declare const CURRENCY_GROUPING_OPTIONS: SelectOption[];
215
243
  export type CreateAttributeDialogProps = {
216
244
  type: string;
217
245
  onTypeChange: (value: string) => void;
@@ -221,6 +249,27 @@ export type CreateAttributeDialogProps = {
221
249
  onNameChange: (value: string) => void;
222
250
  description: string;
223
251
  onDescriptionChange: (value: string) => void;
252
+ /** Currency's own extra fields (shown only while `type === "currency"`).
253
+ * See `CURRENCY_DISPLAY_OPTIONS`/`CURRENCY_DECIMAL_PLACES_OPTIONS`/
254
+ * `CURRENCY_GROUPING_OPTIONS` for the (small, fixed) defaults; there is
255
+ * no default `currencyOptions` — a real currency list is the consumer's
256
+ * own reference data. */
257
+ currency?: string;
258
+ onCurrencyChange?: (value: string) => void;
259
+ currencyOptions?: SelectOption[];
260
+ display?: string;
261
+ onDisplayChange?: (value: string) => void;
262
+ displayOptions?: SelectOption[];
263
+ decimalPlaces?: string;
264
+ onDecimalPlacesChange?: (value: string) => void;
265
+ decimalPlacesOptions?: SelectOption[];
266
+ grouping?: string;
267
+ onGroupingChange?: (value: string) => void;
268
+ groupingOptions?: SelectOption[];
269
+ currencyFieldLabel?: string;
270
+ displayFieldLabel?: string;
271
+ decimalPlacesFieldLabel?: string;
272
+ groupingFieldLabel?: string;
224
273
  aiAutofillEnabled?: boolean;
225
274
  onAiAutofillChange?: (enabled: boolean) => void;
226
275
  onSubmit: () => void;
@@ -237,15 +286,22 @@ export type CreateAttributeDialogProps = {
237
286
  createLabel?: string;
238
287
  };
239
288
  /**
240
- * "Create attribute" (crisp#637, P-125, verified live): Attribute Type
241
- * select (defaults to Text) + Name (autofocused) + Description (optional)
242
- * + an AI-autofill switch row, footer Cancel/Create. Built on `FormDialog`
243
- * in its plain (non-`createMode`) shape — Attio's own footer here has a
244
- * real Cancel button, unlike the record-create dialog `createMode` models
245
- * (crisp#548), so `createMode` would be the wrong fit even though the
246
- * button carries the same ⌘↵ hint; that hint is rendered locally instead.
289
+ * "Create attribute" (crisp#637/#673, P-125, verified live): Attribute Type
290
+ * select (defaults to Text, type-ahead search built in via `Select`'s own
291
+ * `searchable`) + Name (autofocused on open, and again after picking a type
292
+ * — G-106) + Description (optional) + Currency's own four extra required
293
+ * fields when `type === "currency"` (G-104) + an AI-autofill switch row,
294
+ * footer Cancel/Create. Built on `FormDialog` in its plain (non-`createMode`)
295
+ * shape — Attio's own footer here has a real Cancel button, unlike the
296
+ * record-create dialog `createMode` models (crisp#548), so `createMode`
297
+ * would be the wrong fit even though the button carries the same ⌘↵ hint;
298
+ * that hint is rendered locally instead. The outside-click/Escape
299
+ * "Discard changes" confirm gated on dirty state (G-105) needed no work
300
+ * here at all — `FormDialog` already tracks dirtiness generically and shows
301
+ * it, so this dialog inherited it for free; `CreateAttributeDialog`'s own
302
+ * tests below just pin the behaviour to this component specifically.
247
303
  */
248
- export declare function CreateAttributeDialog({ type, onTypeChange, typeOptions, aiAutofillTypeOptions, name, onNameChange, description, onDescriptionChange, aiAutofillEnabled, onAiAutofillChange, onSubmit, onClose, busy, error, title: titleProp, attributeTypeLabel: attributeTypeLabelProp, nameLabel: nameLabelProp, descriptionLabel: descriptionLabelProp, descriptionPlaceholder: descriptionPlaceholderProp, aiAutofillLabel: aiAutofillLabelProp, setUpAiAutofillLabel: setUpAiAutofillLabelProp, createLabel: createLabelProp, }: CreateAttributeDialogProps): React.JSX.Element;
304
+ export declare function CreateAttributeDialog({ type, onTypeChange, typeOptions, aiAutofillTypeOptions, name, onNameChange, description, onDescriptionChange, currency, onCurrencyChange, currencyOptions, display, onDisplayChange, displayOptions, decimalPlaces, onDecimalPlacesChange, decimalPlacesOptions, grouping, onGroupingChange, groupingOptions, currencyFieldLabel: currencyFieldLabelProp, displayFieldLabel: displayFieldLabelProp, decimalPlacesFieldLabel: decimalPlacesFieldLabelProp, groupingFieldLabel: groupingFieldLabelProp, aiAutofillEnabled, onAiAutofillChange, onSubmit, onClose, busy, error, title: titleProp, attributeTypeLabel: attributeTypeLabelProp, nameLabel: nameLabelProp, descriptionLabel: descriptionLabelProp, descriptionPlaceholder: descriptionPlaceholderProp, aiAutofillLabel: aiAutofillLabelProp, setUpAiAutofillLabel: setUpAiAutofillLabelProp, createLabel: createLabelProp, }: CreateAttributeDialogProps): React.JSX.Element;
249
305
  export declare namespace CreateAttributeDialog {
250
306
  var displayName: string;
251
307
  }
@@ -1,4 +1,4 @@
1
1
  export { type Column, type ColumnType, type EntityValue, type ReferenceOption, type Row, type StatusOption, tagTone, } from "./column";
2
2
  export { type EditableOption, editableInputType, useEditableField, } from "./editable-field";
3
- export { RecordDetails, type RecordDetailsProps, RecordPage, type RecordPageHighlight, type RecordPageLabels, type RecordPageLabelsInput, type RecordPageNote, type RecordPageProps, type RecordPageSection, type RecordPageTab, type RecordPageTask, recordPageLabels, } from "./recordpage";
3
+ export { RecordDetails, type RecordDetailsProps, RecordPage, type RecordPageHighlight, type RecordPageLabels, type RecordPageLabelsInput, RecordPageMain, type RecordPageMainProps, type RecordPageMenuAction, type RecordPageNote, type RecordPageProps, type RecordPageSection, type RecordPageTab, type RecordPageTask, recordPageLabels, } from "./recordpage";
4
4
  export { recordpageRecipe } from "./recordpage.recipe";
@@ -78,6 +78,22 @@ export type RecordPageQuickAction = {
78
78
  icon: LucideIcon;
79
79
  onSelect?: () => void;
80
80
  };
81
+ /**
82
+ * One consumer-supplied item in the "…" record-actions menu (crisp#1012) —
83
+ * appended after Attio's own fixed group (Merge records/Configure page/Copy
84
+ * page URL/Copy record ID, Add to favorites), before Delete. Own group,
85
+ * separator-delimited on both sides, never merged into Attio's own items —
86
+ * the same "caller's own list, not a merge" choice `tabs` (#379) and
87
+ * `highlights` (#528) already make.
88
+ */
89
+ export type RecordPageMenuAction = {
90
+ label: string;
91
+ icon: LucideIcon;
92
+ onSelect: () => void;
93
+ /** Red text/icon, `MenuItem`'s own `danger` — for a destructive action
94
+ * that isn't Delete itself (Delete has its own dedicated `onDelete`). */
95
+ danger?: boolean;
96
+ };
81
97
  export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
82
98
  record: Row;
83
99
  columns: Column[];
@@ -196,6 +212,74 @@ export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "child
196
212
  * convention) — Attio's own Share opens a dialog crisp has no measured
197
213
  * content for; only the entry point is in scope here (#864). */
198
214
  onShare?: () => void;
215
+ /**
216
+ * crisp#1012: the header entity's `Avatar` `shape` — defaults to
217
+ * `"rounded"` (Attio's own CRM entities), matching `DataTable`'s own
218
+ * `avatarShape` prop (#892) exactly, for a consumer whose record type
219
+ * reads as a person (GRC's Employee, `"circle"`) rather than a company/
220
+ * generic entity.
221
+ */
222
+ avatarShape?: "rounded" | "circle";
223
+ /**
224
+ * crisp#1012: wires the entity header's Pencil "edit record" button,
225
+ * which drew with no `onClick` at all before this. The button itself
226
+ * still always renders (same as Merge/Configure page/Copy page URL/Copy
227
+ * record ID below, and Compose email/Add to list's own documented "this
228
+ * component draws the chrome, a consumer wires the behaviour") — omit
229
+ * to keep it exactly as inert as it always was. Named `onEditRecord`,
230
+ * not `onEdit` — that name is already `onEdit`'s own per-FIELD commit
231
+ * handler above; reusing it here for a whole-record action would be two
232
+ * unrelated things behind one prop.
233
+ */
234
+ onEditRecord?: () => void;
235
+ /**
236
+ * crisp#1012: wires the "…" menu's "Delete record" item, chrome-only (no
237
+ * `onSelect` at all) before this. Delete itself always renders — it's
238
+ * one of Attio's own fixed 6 items (#621/#905), not a consumer-optional
239
+ * one — omit to leave it exactly as inert as Merge/Configure/Copy page
240
+ * URL/Copy record ID already are by default.
241
+ */
242
+ onDelete?: () => void;
243
+ /**
244
+ * crisp#1012: appends the caller's own items to the "…" menu, in their
245
+ * own separator-delimited group between Attio's fixed items and Delete
246
+ * — e.g. an object-specific "Mark reviewed", or routing "Edit" to a full
247
+ * external form instead of `RecordDetails`' own inline click-to-edit for
248
+ * an object where that's the only real editor (internal/grc's own
249
+ * `EDIT_OPENS_FORM`, the case this was built for). Omit for the built-in
250
+ * group alone.
251
+ */
252
+ actions?: RecordPageMenuAction[];
253
+ /**
254
+ * crisp#1019: hides the plain breadcrumb row (has no effect in peek mode
255
+ * — when `onClose` is set, the peek header replaces it entirely already).
256
+ * Default `true`, no change for an existing consumer — for one whose own
257
+ * app shell already renders a breadcrumb of its own (a second one would
258
+ * otherwise double up), pass `false`.
259
+ */
260
+ showBreadcrumb?: boolean;
261
+ /**
262
+ * crisp#1019: hides the topbar's Share button. Default `true` — Share
263
+ * itself is still unconditional chrome with no built-in dialog (`onShare`
264
+ * "renders regardless" per its own doc above); this is a SEPARATE,
265
+ * explicit opt-out, not tied to whether `onShare` is supplied — a missing
266
+ * handler must never silently hide a button an existing consumer already
267
+ * sees, the same reasoning #1012's `onEditRecord`/`onDelete` already
268
+ * settled for the "…" menu's own always-visible items.
269
+ */
270
+ showShare?: boolean;
271
+ /** crisp#1019: hides the topbar's "Ask AI" button — pure Attio branding
272
+ * chrome with no consumer hook of its own. Default `true`. */
273
+ showAskAttio?: boolean;
274
+ /**
275
+ * crisp#1019: hides the topbar's Comments toggle icon (which opens
276
+ * `RecordPage`'s own internal comments panel) — for a consumer whose
277
+ * Comments live somewhere else in its own UI already (a tab, say),
278
+ * rather than a second, competing entry point to the same feature.
279
+ * Default `true`. Independent of the `comments`/`onPostComment` props
280
+ * above, which control the panel's DATA, not this button's visibility.
281
+ */
282
+ showComments?: boolean;
199
283
  };
200
284
  /**
201
285
  * Every chrome string RecordPage renders. Supplied as a PARTIAL map, so
@@ -239,6 +323,40 @@ export type RecordPageLabels = {
239
323
  comments: string;
240
324
  /** Empty state under the Lists panel. */
241
325
  noLists: string;
326
+ /** Activity tab toolbar (#622). */
327
+ filters: string;
328
+ addMeeting: string;
329
+ /** Files tab empty state (#622): title, hint body, and its two actions. */
330
+ noFiles: string;
331
+ filesHint: string;
332
+ newFolder: string;
333
+ uploadFile: string;
334
+ /** aria-label on the Files tab empty state's "⋮" overflow button (#622). */
335
+ fileMoreActions: string;
336
+ /** Associated deals tab empty state (#622). */
337
+ noDealsFound: string;
338
+ noDealsHint: string;
339
+ newDeal: string;
340
+ /** Emails tab empty state (#987): the dedicated tab's own illustrated
341
+ * state, distinct from `noEmailsWith` (Overview's condensed embed). */
342
+ noEmails: string;
343
+ noEmailsHint: string;
344
+ configureMailbox: string;
345
+ /** Calls tab empty state (#988): chrome only, no real gating. */
346
+ upgradeToViewCalls: string;
347
+ callsUpgradeHint: string;
348
+ upgrade: string;
349
+ /** The "Run workflow" quick action's own popover (#620): title, search
350
+ * placeholder, empty state, and its "Create new workflow" link. Chrome
351
+ * only, like Compose email/Add to list above -- crisp has no workflow
352
+ * data model to search over yet. */
353
+ selectWorkflowTitle: string;
354
+ closeWorkflowPopover: string;
355
+ searchWorkflowsPlaceholder: string;
356
+ noWorkflows: string;
357
+ createNewWorkflow: string;
358
+ /** Footer keyboard hint under the "Select workflow" popover's empty list. */
359
+ navigate: string;
242
360
  highlights: string;
243
361
  recordDetails: string;
244
362
  searchFields: string;
@@ -347,6 +465,29 @@ export declare function RecordDetails({ record, columns, sections, onEdit, label
347
465
  export declare namespace RecordDetails {
348
466
  var displayName: string;
349
467
  }
468
+ export type RecordPageMainProps = React.ComponentPropsWithoutRef<"main">;
469
+ /**
470
+ * The main/tab-content column's own box, on its own (#750) — the same
471
+ * "standalone piece" `RecordDetails` already is for the Details column,
472
+ * mirrored to the other side of the layout. `RecordPage` composes this
473
+ * internally for its own tabbed body (below) — this exact box, not a second
474
+ * copy — so a consumer building a custom record page (its own tab set, its
475
+ * own menu, `RecordDetails` for the left column, but not the full
476
+ * `RecordPage`, which hardcodes the CRM tab set) gets the same
477
+ * Attio-measured inset: `flex: 1; min-width: 0; display: flex;
478
+ * flex-direction: column; min-height: 0; overflow-y: auto; padding: 12px
479
+ * 20px` (`recordpage.recipe.ts`'s own `.crisp-recordpage-main`) — without
480
+ * reaching for that internal class name directly, the only option before
481
+ * this existed.
482
+ *
483
+ * Needs the same single `.crisp-recordpage`-scoped ancestor `RecordDetails`
484
+ * already documents — wrap both in `recordpageRecipe()`, the way
485
+ * `RecordPage`'s own root does.
486
+ */
487
+ export declare function RecordPageMain({ className, children, ...rest }: RecordPageMainProps): React.JSX.Element;
488
+ export declare namespace RecordPageMain {
489
+ var displayName: string;
490
+ }
350
491
  /**
351
492
  * The full-page company record view — the page that opens when you click into a
352
493
  * record (as opposed to the peek [RecordPanel]). A top breadcrumb bar with
@@ -355,7 +496,7 @@ export declare namespace RecordDetails {
355
496
  * Emails sections (Notes & Tasks are live — add and check things off). Drop it
356
497
  * into the app's main content area.
357
498
  */
358
- export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, onClose, closeLabel, onPrevious, previousRecordLabel, onNext, nextRecordLabel, counterLabel, className, onEdit, tabs: tabsProp, defaultTab, notes: notesProp, onAddNote, tasks: tasksProp, onAddTask, onToggleTask, sections, highlights: highlightsProp, quickActions: quickActionsProp, comments: commentsProp, onPostComment, currentUser, onShare, ...rest }: RecordPageProps): React.JSX.Element;
499
+ export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, onClose, closeLabel, onPrevious, previousRecordLabel, onNext, nextRecordLabel, counterLabel, className, onEdit, tabs: tabsProp, defaultTab, notes: notesProp, onAddNote, tasks: tasksProp, onAddTask, onToggleTask, sections, highlights: highlightsProp, quickActions: quickActionsProp, comments: commentsProp, onPostComment, currentUser, onShare, avatarShape, onEditRecord, onDelete, actions, showBreadcrumb, showShare, showAskAttio, showComments, ...rest }: RecordPageProps): React.JSX.Element;
359
500
  export declare namespace RecordPage {
360
501
  var displayName: string;
361
502
  }
@@ -0,0 +1,2 @@
1
+ export { RecordPicker, type RecordPickerProps, type RecordPickerRecord, } from "./recordpicker";
2
+ export { recordpickerRecipe } from "./recordpicker.recipe";
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ export type RecordPickerRecord = {
3
+ id: string;
4
+ name: React.ReactNode;
5
+ /** Per-type icon, consumer-supplied -- crisp has no built-in
6
+ * object-type-to-icon mapping (same reasoning as `TaskList`'s own
7
+ * `record`/`meta` slots). */
8
+ icon?: React.ReactNode;
9
+ };
10
+ export type RecordPickerProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "onSelect"> & {
11
+ records: RecordPickerRecord[];
12
+ /** Shows the measured "Loading..." row instead of the list (the results
13
+ * are still in flight). */
14
+ loading?: boolean;
15
+ onSelect?: (record: RecordPickerRecord) => void;
16
+ query?: string;
17
+ onQueryChange?: (query: string) => void;
18
+ searchLabel?: string;
19
+ loadingLabel?: string;
20
+ emptyLabel?: React.ReactNode;
21
+ className?: string;
22
+ };
23
+ /**
24
+ * The record-search picker behind a task's "Add record" chip -- measured
25
+ * live on app.attio.com's Tasks page ("Edit task" -> "Add record"): a
26
+ * "Search..." row, then a FLAT list mixed across every object type (a
27
+ * person result sat first, ahead of several companies, with no section
28
+ * headers -- unlike the mention picker's own grouped Users/Records shape,
29
+ * crisp#646). Attio's own live search took a moment to resolve, showing a
30
+ * centred spinner + "Loading..." row meanwhile; not independently
31
+ * re-measured against a second empty-results case, so `emptyLabel`'s
32
+ * default copy ("No records") is inferred by symmetry with
33
+ * `AssigneePicker`'s own measured "No users", not itself pixel-measured.
34
+ */
35
+ export declare function RecordPicker({ records, loading, onSelect, query: queryProp, onQueryChange, searchLabel: searchLabelProp, loadingLabel: loadingLabelProp, emptyLabel: emptyLabelProp, className, ...rest }: RecordPickerProps): React.JSX.Element;
36
+ export declare namespace RecordPicker {
37
+ var displayName: string;
38
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const recordpickerRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -1,2 +1,2 @@
1
- export { type SavedView, SavedViews, type SavedViewsProps, } from "./savedviews";
1
+ export { type SavedView, SavedViews, type SavedViewsProps, SavedViewsSaveBar, type SavedViewsSaveBarProps, } from "./savedviews";
2
2
  export { savedviewsRecipe } from "./savedviews.recipe";
@@ -90,3 +90,39 @@ export declare function SavedViews({ label, icon, views, activeId, onSelect, onC
90
90
  export declare namespace SavedViews {
91
91
  var displayName: string;
92
92
  }
93
+ export type SavedViewsSaveBarProps = React.ComponentPropsWithoutRef<"div"> & {
94
+ /** Commits the live state (filters/sort/columns/…) back onto the loaded
95
+ * view — Attio's own "Save for everyone". */
96
+ onSave: () => void;
97
+ /** Reverts the live state to the loaded view's own saved snapshot. */
98
+ onDiscard: () => void;
99
+ /**
100
+ * Saves the live state as a brand-new view instead — the split button's
101
+ * own chevron menu (measured: exactly one item, "Save as new view").
102
+ * Omit to render a plain button with no chevron/menu.
103
+ */
104
+ onSaveAsNew?: () => void;
105
+ discardLabel?: string;
106
+ saveLabel?: string;
107
+ saveAsNewLabel?: string;
108
+ /** aria-label on the chevron trigger when `onSaveAsNew` is given. */
109
+ saveOptionsLabel?: string;
110
+ className?: string;
111
+ };
112
+ /**
113
+ * The "unsaved changes" bar for a currently loaded saved view — Attio's own
114
+ * "Discard changes" + a split "Save for everyone ▾" button, measured live
115
+ * (app.attio.com, a saved Companies view with its sort changed). Not a part
116
+ * of `SavedViews`' own trigger/panel: Attio renders this in the page
117
+ * toolbar's own trailing slot, replacing whatever sits there at rest
118
+ * (Import/Export, "+ New …") — the same slot `TableToolbar`'s own
119
+ * `children` prop already documents ("Right-aligned actions after the
120
+ * count"). A consumer swaps this in for that slot's usual content once its
121
+ * own dirty check (live filters/sort/columns vs. the loaded view's
122
+ * snapshot) is true, and swaps it back out once it's false — this
123
+ * component itself carries no dirty state or visibility toggle.
124
+ */
125
+ export declare function SavedViewsSaveBar({ onSave, onDiscard, onSaveAsNew, discardLabel: discardLabelProp, saveLabel: saveLabelProp, saveAsNewLabel: saveAsNewLabelProp, saveOptionsLabel: saveOptionsLabelProp, className, ...rest }: SavedViewsSaveBarProps): React.JSX.Element;
126
+ export declare namespace SavedViewsSaveBar {
127
+ var displayName: string;
128
+ }
@@ -0,0 +1,2 @@
1
+ export { type ShareMember, SharePopover, type SharePopoverProps, type ShareRoleOption, } from "./share";
2
+ export { shareRecipe } from "./share.recipe";