@crisp-ui-kit/crisp 0.57.3 → 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 (169) 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 +1 -1
  5. package/dist/button.layered.css +1 -1
  6. package/dist/cjs/components/button/button.recipe.js +15 -10
  7. package/dist/cjs/components/datatable/datatable.js +6 -3
  8. package/dist/cjs/components/datatable/datatable.recipe.js +35 -2
  9. package/dist/cjs/components/menu/menu.js +48 -8
  10. package/dist/cjs/components/multiselect/multiselect.js +3 -0
  11. package/dist/cjs/components/multiselect/multiselect.recipe.js +18 -0
  12. package/dist/cjs/components/select/select.js +2 -2
  13. package/dist/cjs/components/select/select.recipe.js +19 -0
  14. package/dist/cjs/core/index.js +2 -1
  15. package/dist/cjs/core/place-floating.js +38 -0
  16. package/dist/cjs/index.js +8 -0
  17. package/dist/cjs/product/assigneepicker/assigneepicker.js +127 -0
  18. package/dist/cjs/product/assigneepicker/assigneepicker.recipe.js +36 -0
  19. package/dist/cjs/product/assigneepicker/index.js +7 -0
  20. package/dist/cjs/product/notesgallery/index.js +7 -0
  21. package/dist/cjs/product/notesgallery/notesgallery.js +80 -0
  22. package/dist/cjs/product/notesgallery/notesgallery.recipe.js +46 -0
  23. package/dist/cjs/product/objectpagemenu/index.js +17 -0
  24. package/dist/cjs/product/objectpagemenu/objectpagemenu.js +26 -0
  25. package/dist/cjs/product/objectpagemenu/objectpagemenu.recipe.js +30 -0
  26. package/dist/cjs/product/objectsettings/objectsettings.js +107 -14
  27. package/dist/cjs/product/recordpage/recordpage.js +64 -5
  28. package/dist/cjs/product/recordpage/recordpage.recipe.js +38 -0
  29. package/dist/cjs/product/recordpicker/index.js +7 -0
  30. package/dist/cjs/product/recordpicker/recordpicker.js +100 -0
  31. package/dist/cjs/product/recordpicker/recordpicker.recipe.js +36 -0
  32. package/dist/cjs/product/savedviews/index.js +2 -1
  33. package/dist/cjs/product/savedviews/savedviews.js +22 -0
  34. package/dist/cjs/product/savedviews/savedviews.recipe.js +47 -0
  35. package/dist/cjs/product/share/index.js +7 -0
  36. package/dist/cjs/product/share/share.js +179 -0
  37. package/dist/cjs/product/share/share.recipe.js +114 -0
  38. package/dist/cjs/product/shortcutssheet/index.js +17 -0
  39. package/dist/cjs/product/shortcutssheet/shortcutssheet.js +125 -0
  40. package/dist/cjs/product/shortcutssheet/shortcutssheet.recipe.js +50 -0
  41. package/dist/cjs/product/taskeditpopover/index.js +7 -0
  42. package/dist/cjs/product/taskeditpopover/taskeditpopover.js +159 -0
  43. package/dist/cjs/product/taskeditpopover/taskeditpopover.recipe.js +68 -0
  44. package/dist/cjs/product/workspaceswitchermenu/index.js +17 -0
  45. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.js +38 -0
  46. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +34 -0
  47. package/dist/cjs/tokens/palette.js +27 -0
  48. package/dist/cjs/tokens/semantic.js +20 -0
  49. package/dist/datatable.css +40 -7
  50. package/dist/datatable.layered.css +40 -7
  51. package/dist/esm/components/button/button.recipe.js +15 -10
  52. package/dist/esm/components/datatable/datatable.js +6 -3
  53. package/dist/esm/components/datatable/datatable.recipe.js +35 -2
  54. package/dist/esm/components/menu/menu.js +47 -7
  55. package/dist/esm/components/multiselect/multiselect.js +3 -0
  56. package/dist/esm/components/multiselect/multiselect.recipe.js +18 -0
  57. package/dist/esm/components/select/select.js +2 -2
  58. package/dist/esm/components/select/select.recipe.js +19 -0
  59. package/dist/esm/core/index.js +1 -1
  60. package/dist/esm/core/place-floating.js +37 -0
  61. package/dist/esm/index.js +8 -0
  62. package/dist/esm/product/assigneepicker/assigneepicker.js +91 -0
  63. package/dist/esm/product/assigneepicker/assigneepicker.recipe.js +33 -0
  64. package/dist/esm/product/assigneepicker/index.js +2 -0
  65. package/dist/esm/product/notesgallery/index.js +2 -0
  66. package/dist/esm/product/notesgallery/notesgallery.js +44 -0
  67. package/dist/esm/product/notesgallery/notesgallery.recipe.js +43 -0
  68. package/dist/esm/product/objectpagemenu/index.js +1 -0
  69. package/dist/esm/product/objectpagemenu/objectpagemenu.js +23 -0
  70. package/dist/esm/product/objectpagemenu/objectpagemenu.recipe.js +27 -0
  71. package/dist/esm/product/objectsettings/objectsettings.js +106 -13
  72. package/dist/esm/product/recordpage/recordpage.js +64 -5
  73. package/dist/esm/product/recordpage/recordpage.recipe.js +38 -0
  74. package/dist/esm/product/recordpicker/index.js +2 -0
  75. package/dist/esm/product/recordpicker/recordpicker.js +64 -0
  76. package/dist/esm/product/recordpicker/recordpicker.recipe.js +33 -0
  77. package/dist/esm/product/savedviews/index.js +1 -1
  78. package/dist/esm/product/savedviews/savedviews.js +22 -1
  79. package/dist/esm/product/savedviews/savedviews.recipe.js +47 -0
  80. package/dist/esm/product/share/index.js +2 -0
  81. package/dist/esm/product/share/share.js +143 -0
  82. package/dist/esm/product/share/share.recipe.js +111 -0
  83. package/dist/esm/product/shortcutssheet/index.js +1 -0
  84. package/dist/esm/product/shortcutssheet/shortcutssheet.js +88 -0
  85. package/dist/esm/product/shortcutssheet/shortcutssheet.recipe.js +47 -0
  86. package/dist/esm/product/taskeditpopover/index.js +2 -0
  87. package/dist/esm/product/taskeditpopover/taskeditpopover.js +123 -0
  88. package/dist/esm/product/taskeditpopover/taskeditpopover.recipe.js +65 -0
  89. package/dist/esm/product/workspaceswitchermenu/index.js +1 -0
  90. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.js +35 -0
  91. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +31 -0
  92. package/dist/esm/tokens/palette.js +27 -0
  93. package/dist/esm/tokens/semantic.js +20 -0
  94. package/dist/multiselect.css +18 -0
  95. package/dist/multiselect.layered.css +18 -0
  96. package/dist/native/tokens.d.ts +1 -1
  97. package/dist/native/tokens.js +56 -4
  98. package/dist/notesgallery.css +15 -0
  99. package/dist/notesgallery.d.ts +7 -0
  100. package/dist/notesgallery.layered.css +17 -0
  101. package/dist/objectpagemenu.css +3 -0
  102. package/dist/objectpagemenu.d.ts +7 -0
  103. package/dist/objectpagemenu.layered.css +5 -0
  104. package/dist/recordpage.css +36 -0
  105. package/dist/recordpage.layered.css +36 -0
  106. package/dist/recordpicker.css +13 -0
  107. package/dist/recordpicker.d.ts +7 -0
  108. package/dist/recordpicker.layered.css +15 -0
  109. package/dist/savedviews.css +47 -0
  110. package/dist/savedviews.layered.css +47 -0
  111. package/dist/select.css +19 -0
  112. package/dist/select.layered.css +19 -0
  113. package/dist/share.css +84 -0
  114. package/dist/share.d.ts +7 -0
  115. package/dist/share.layered.css +86 -0
  116. package/dist/shortcutssheet.css +24 -0
  117. package/dist/shortcutssheet.d.ts +7 -0
  118. package/dist/shortcutssheet.layered.css +26 -0
  119. package/dist/styles.css +387 -8
  120. package/dist/styles.layered.css +387 -8
  121. package/dist/taskeditpopover.css +36 -0
  122. package/dist/taskeditpopover.d.ts +7 -0
  123. package/dist/taskeditpopover.layered.css +38 -0
  124. package/dist/tokens.css +26 -0
  125. package/dist/tokens.json +56 -4
  126. package/dist/types/components/button/button.recipe.d.ts +2 -3
  127. package/dist/types/components/datatable/datatable.d.ts +8 -0
  128. package/dist/types/components/menu/menu.d.ts +50 -7
  129. package/dist/types/components/multiselect/multiselect.d.ts +9 -0
  130. package/dist/types/components/select/select.d.ts +10 -0
  131. package/dist/types/core/index.d.ts +1 -1
  132. package/dist/types/core/place-floating.d.ts +37 -0
  133. package/dist/types/index.d.ts +8 -0
  134. package/dist/types/product/assigneepicker/assigneepicker.d.ts +36 -0
  135. package/dist/types/product/assigneepicker/assigneepicker.recipe.d.ts +3 -0
  136. package/dist/types/product/assigneepicker/index.d.ts +2 -0
  137. package/dist/types/product/notesgallery/index.d.ts +2 -0
  138. package/dist/types/product/notesgallery/notesgallery.d.ts +54 -0
  139. package/dist/types/product/notesgallery/notesgallery.recipe.d.ts +3 -0
  140. package/dist/types/product/objectpagemenu/index.d.ts +1 -0
  141. package/dist/types/product/objectpagemenu/objectpagemenu.d.ts +40 -0
  142. package/dist/types/product/objectpagemenu/objectpagemenu.recipe.d.ts +17 -0
  143. package/dist/types/product/objectsettings/objectsettings.d.ts +71 -15
  144. package/dist/types/product/recordpage/index.d.ts +1 -1
  145. package/dist/types/product/recordpage/recordpage.d.ts +96 -1
  146. package/dist/types/product/recordpicker/index.d.ts +2 -0
  147. package/dist/types/product/recordpicker/recordpicker.d.ts +38 -0
  148. package/dist/types/product/recordpicker/recordpicker.recipe.d.ts +3 -0
  149. package/dist/types/product/savedviews/index.d.ts +1 -1
  150. package/dist/types/product/savedviews/savedviews.d.ts +36 -0
  151. package/dist/types/product/share/index.d.ts +2 -0
  152. package/dist/types/product/share/share.d.ts +85 -0
  153. package/dist/types/product/share/share.recipe.d.ts +3 -0
  154. package/dist/types/product/shortcutssheet/index.d.ts +1 -0
  155. package/dist/types/product/shortcutssheet/shortcutssheet.d.ts +49 -0
  156. package/dist/types/product/shortcutssheet/shortcutssheet.recipe.d.ts +3 -0
  157. package/dist/types/product/taskeditpopover/index.d.ts +2 -0
  158. package/dist/types/product/taskeditpopover/taskeditpopover.d.ts +67 -0
  159. package/dist/types/product/taskeditpopover/taskeditpopover.recipe.d.ts +3 -0
  160. package/dist/types/product/workspaceswitchermenu/index.d.ts +1 -0
  161. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.d.ts +54 -0
  162. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.recipe.d.ts +19 -0
  163. package/dist/types/tokens/contract.d.ts +13 -0
  164. package/dist/types/tokens/palette.d.ts +52 -0
  165. package/dist/types/tokens/semantic.d.ts +20 -0
  166. package/dist/workspaceswitchermenu.css +4 -0
  167. package/dist/workspaceswitchermenu.d.ts +7 -0
  168. package/dist/workspaceswitchermenu.layered.css +6 -0
  169. package/package.json +41 -1
package/dist/tokens.css CHANGED
@@ -97,6 +97,19 @@
97
97
  --crisp-stroke-select-divider: #00000010;
98
98
  --crisp-fg-select-placeholder: #b0b3ba;
99
99
  --crisp-shadow-select: #0000001f;
100
+ --crisp-bg-tag-swatch1: #fff3cc;
101
+ --crisp-bg-tag-swatch2: #f4fbcb;
102
+ --crisp-bg-tag-swatch3: #fdf7c4;
103
+ --crisp-bg-tag-swatch4: #feecf3;
104
+ --crisp-bg-tag-swatch5: #e0fced;
105
+ --crisp-bg-tag-swatch6: #ddf7ff;
106
+ --crisp-bg-tag-swatch7: #f6f7f7;
107
+ --crisp-bg-tag-swatch8: #ffebeb;
108
+ --crisp-bg-tag-swatch9: #feeee1;
109
+ --crisp-bg-tag-swatch10: #e5eeff;
110
+ --crisp-bg-tag-swatch11: #f5f0ff;
111
+ --crisp-bg-tag-swatch12: #fdedff;
112
+ --crisp-fg-tag-swatch: #000000;
100
113
  }
101
114
 
102
115
  [data-theme="dark"] {
@@ -170,6 +183,19 @@
170
183
  --crisp-stroke-select-divider: #ffffff17;
171
184
  --crisp-fg-select-placeholder: #868b94;
172
185
  --crisp-shadow-select: #000000cc;
186
+ --crisp-bg-tag-swatch1: #fff3cc;
187
+ --crisp-bg-tag-swatch2: #f4fbcb;
188
+ --crisp-bg-tag-swatch3: #fdf7c4;
189
+ --crisp-bg-tag-swatch4: #feecf3;
190
+ --crisp-bg-tag-swatch5: #e0fced;
191
+ --crisp-bg-tag-swatch6: #ddf7ff;
192
+ --crisp-bg-tag-swatch7: #f6f7f7;
193
+ --crisp-bg-tag-swatch8: #ffebeb;
194
+ --crisp-bg-tag-swatch9: #feeee1;
195
+ --crisp-bg-tag-swatch10: #e5eeff;
196
+ --crisp-bg-tag-swatch11: #f5f0ff;
197
+ --crisp-bg-tag-swatch12: #fdedff;
198
+ --crisp-fg-tag-swatch: #000000;
173
199
  }
174
200
 
175
201
  :root {
package/dist/tokens.json CHANGED
@@ -70,7 +70,20 @@
70
70
  "strokeSelectInvalid": "#fa342c",
71
71
  "strokeSelectDivider": "#00000010",
72
72
  "fgSelectPlaceholder": "#b0b3ba",
73
- "shadowSelect": "#0000001f"
73
+ "shadowSelect": "#0000001f",
74
+ "bgTagSwatch1": "#fff3cc",
75
+ "bgTagSwatch2": "#f4fbcb",
76
+ "bgTagSwatch3": "#fdf7c4",
77
+ "bgTagSwatch4": "#feecf3",
78
+ "bgTagSwatch5": "#e0fced",
79
+ "bgTagSwatch6": "#ddf7ff",
80
+ "bgTagSwatch7": "#f6f7f7",
81
+ "bgTagSwatch8": "#ffebeb",
82
+ "bgTagSwatch9": "#feeee1",
83
+ "bgTagSwatch10": "#e5eeff",
84
+ "bgTagSwatch11": "#f5f0ff",
85
+ "bgTagSwatch12": "#fdedff",
86
+ "fgTagSwatch": "#000000"
74
87
  },
75
88
  "dark": {
76
89
  "bgBrandSolid": "#0298d9",
@@ -142,7 +155,20 @@
142
155
  "strokeSelectInvalid": "#ff6e60",
143
156
  "strokeSelectDivider": "#ffffff17",
144
157
  "fgSelectPlaceholder": "#868b94",
145
- "shadowSelect": "#000000cc"
158
+ "shadowSelect": "#000000cc",
159
+ "bgTagSwatch1": "#fff3cc",
160
+ "bgTagSwatch2": "#f4fbcb",
161
+ "bgTagSwatch3": "#fdf7c4",
162
+ "bgTagSwatch4": "#feecf3",
163
+ "bgTagSwatch5": "#e0fced",
164
+ "bgTagSwatch6": "#ddf7ff",
165
+ "bgTagSwatch7": "#f6f7f7",
166
+ "bgTagSwatch8": "#ffebeb",
167
+ "bgTagSwatch9": "#feeee1",
168
+ "bgTagSwatch10": "#e5eeff",
169
+ "bgTagSwatch11": "#f5f0ff",
170
+ "bgTagSwatch12": "#fdedff",
171
+ "fgTagSwatch": "#000000"
146
172
  }
147
173
  },
148
174
  "palette": {
@@ -212,7 +238,20 @@
212
238
  "selectInvalidStroke": "#fa342c",
213
239
  "selectDivider": "#00000010",
214
240
  "selectPlaceholder": "#b0b3ba",
215
- "selectShadow": "#0000001f"
241
+ "selectShadow": "#0000001f",
242
+ "tagSwatch1": "#fff3cc",
243
+ "tagSwatch2": "#f4fbcb",
244
+ "tagSwatch3": "#fdf7c4",
245
+ "tagSwatch4": "#feecf3",
246
+ "tagSwatch5": "#e0fced",
247
+ "tagSwatch6": "#ddf7ff",
248
+ "tagSwatch7": "#f6f7f7",
249
+ "tagSwatch8": "#ffebeb",
250
+ "tagSwatch9": "#feeee1",
251
+ "tagSwatch10": "#e5eeff",
252
+ "tagSwatch11": "#f5f0ff",
253
+ "tagSwatch12": "#fdedff",
254
+ "tagSwatchInk": "#000000"
216
255
  },
217
256
  "dark": {
218
257
  "gray00": "#0a0a0a",
@@ -280,7 +319,20 @@
280
319
  "selectInvalidStroke": "#ff6e60",
281
320
  "selectDivider": "#ffffff17",
282
321
  "selectPlaceholder": "#868b94",
283
- "selectShadow": "#000000cc"
322
+ "selectShadow": "#000000cc",
323
+ "tagSwatch1": "#fff3cc",
324
+ "tagSwatch2": "#f4fbcb",
325
+ "tagSwatch3": "#fdf7c4",
326
+ "tagSwatch4": "#feecf3",
327
+ "tagSwatch5": "#e0fced",
328
+ "tagSwatch6": "#ddf7ff",
329
+ "tagSwatch7": "#f6f7f7",
330
+ "tagSwatch8": "#ffebeb",
331
+ "tagSwatch9": "#feeee1",
332
+ "tagSwatch10": "#e5eeff",
333
+ "tagSwatch11": "#f5f0ff",
334
+ "tagSwatch12": "#fdedff",
335
+ "tagSwatchInk": "#000000"
284
336
  }
285
337
  },
286
338
  "space": {
@@ -102,9 +102,8 @@ declare const spec: {
102
102
  readonly xs: {
103
103
  readonly height: "20px";
104
104
  readonly paddingInline: `var(--${string})`;
105
- readonly fontSize: "10px";
106
- readonly fontWeight: `var(--${string})`;
107
- readonly lineHeight: "15px";
105
+ readonly fontSize: `var(--${string})`;
106
+ readonly lineHeight: "16px";
108
107
  readonly letterSpacing: "normal";
109
108
  readonly borderRadius: `var(--${string})`;
110
109
  readonly gap: `var(--${string})`;
@@ -87,6 +87,14 @@ export type DataTableColumn<T> = {
87
87
  resizable?: boolean;
88
88
  /** Tone overrides for `status`/`tags` values (else a stable colour per value). */
89
89
  tones?: Record<string, string>;
90
+ /**
91
+ * One of Attio's 12 fixed tag/option colours (your-moon/crisp#998), 1-12,
92
+ * per `status`/`tags` value -- renders that value's chip as a filled
93
+ * pill from Attio's own enumerable palette (measured: flat black text,
94
+ * no ring) instead of `tones`'/`toneFor`'s semantic 7-tone family. Wins
95
+ * over `tones` for a value present in both.
96
+ */
97
+ swatches?: Record<string, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12>;
90
98
  /** `type: "date"`/`"datetime"` only: render this cell in Attio's own
91
99
  * measured overdue/danger red (`fgDanger`, `#eb3b3b` — the same token
92
100
  * `TasksTable`'s own overdue due-date already uses, crisp#462) when the
@@ -4,8 +4,19 @@ export type MenuProps = {
4
4
  trigger: React.ReactElement;
5
5
  children: React.ReactNode;
6
6
  /** Align the menu to the trigger's inline `start` or `end` edge — the left
7
- * edge in an LTR document, the right one in RTL. */
7
+ * edge in an LTR document, the right one in RTL. Ignored when
8
+ * `placement="submenu"`, which decides its own side (see there). */
8
9
  align?: "start" | "end";
10
+ /**
11
+ * `"menu"` (default): a dropdown below/above the trigger, `placeFloating`'s
12
+ * own placement. `"submenu"` (crisp#616): a cascade BESIDE the trigger —
13
+ * give it a `MenuItem` (with a `trailingIcon` chevron) as `trigger`, nested
14
+ * inside an outer `Menu`'s children, the way Attio's own "Notifications ›"
15
+ * row opens "Connect Slack workspace". Reuses the same outside-click/Escape
16
+ * machinery below (registered as its own floating layer), so it composes
17
+ * with the outer Menu for free.
18
+ */
19
+ placement?: "menu" | "submenu";
9
20
  /** Controlled open state. Omit to let Menu manage it (see defaultOpen). */
10
21
  open?: boolean;
11
22
  /** Initially open, when uncontrolled. */
@@ -31,11 +42,11 @@ export type MenuProps = {
31
42
  * typeahead, Enter/Space select, Esc closes and returns focus to the trigger);
32
43
  * closes on outside click. Flips up / right-aligns when space is tight.
33
44
  */
34
- export declare function Menu({ trigger, children, align, open: openProp, defaultOpen, onOpenChange, className, contentClassName, "aria-label": ariaLabel, }: MenuProps): React.JSX.Element;
45
+ export declare function Menu({ trigger, children, align, placement, open: openProp, defaultOpen, onOpenChange, className, contentClassName, "aria-label": ariaLabel, }: MenuProps): React.JSX.Element;
35
46
  export declare namespace Menu {
36
47
  var displayName: string;
37
48
  }
38
- export type MenuItemProps = {
49
+ export type MenuItemProps = Omit<React.ComponentPropsWithoutRef<"button">, "children" | "disabled" | "onSelect"> & {
39
50
  children: React.ReactNode;
40
51
  icon?: React.ReactNode;
41
52
  shortcut?: string;
@@ -45,16 +56,48 @@ export type MenuItemProps = {
45
56
  * `count` prop uses, not bare text.
46
57
  */
47
58
  count?: React.ReactNode;
59
+ /**
60
+ * A trailing indicator after everything else — a submenu chevron
61
+ * (crisp#616: give this item a nested `<Menu placement="submenu">` as its
62
+ * `trigger`, with a `ChevronRight` here). Plain content, not a second
63
+ * `icon` slot — nothing else currently needs two.
64
+ */
65
+ trailingIcon?: React.ReactNode;
48
66
  danger?: boolean;
49
67
  disabled?: boolean;
50
68
  onSelect?: () => void;
51
69
  /** Keep the menu open after selecting (default closes). */
52
70
  closeOnSelect?: boolean;
53
71
  };
54
- export declare function MenuItem({ children, icon, shortcut, count, danger, disabled, onSelect, closeOnSelect, }: MenuItemProps): React.JSX.Element;
55
- export declare namespace MenuItem {
56
- var displayName: string;
57
- }
72
+ /**
73
+ * A row inside a `Menu`. Forwards its ref and spreads unrecognised button
74
+ * props (crisp#616) so it can double as another `Menu`'s own `trigger` —
75
+ * `Menu` clones its trigger with `ref`/`onClick`/`aria-*`, which a plain
76
+ * function component would silently drop.
77
+ */
78
+ export declare const MenuItem: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "children" | "disabled" | "onSelect"> & {
79
+ children: React.ReactNode;
80
+ icon?: React.ReactNode;
81
+ shortcut?: string;
82
+ /**
83
+ * A trailing count badge (crisp#875) — e.g. a saved-filter item showing
84
+ * how many rows match. Same measured neutral chip `ToolbarTool`'s own
85
+ * `count` prop uses, not bare text.
86
+ */
87
+ count?: React.ReactNode;
88
+ /**
89
+ * A trailing indicator after everything else — a submenu chevron
90
+ * (crisp#616: give this item a nested `<Menu placement="submenu">` as its
91
+ * `trigger`, with a `ChevronRight` here). Plain content, not a second
92
+ * `icon` slot — nothing else currently needs two.
93
+ */
94
+ trailingIcon?: React.ReactNode;
95
+ danger?: boolean;
96
+ disabled?: boolean;
97
+ onSelect?: () => void;
98
+ /** Keep the menu open after selecting (default closes). */
99
+ closeOnSelect?: boolean;
100
+ } & React.RefAttributes<HTMLButtonElement>>;
58
101
  export type MenuCheckboxItemProps = {
59
102
  children: React.ReactNode;
60
103
  checked?: boolean;
@@ -4,6 +4,15 @@ export type MultiSelectOption = {
4
4
  label: string;
5
5
  /** Chip colour tone; falls back to a deterministic pastel per value. */
6
6
  tone?: string;
7
+ /**
8
+ * One of Attio's 12 fixed tag/option colours (your-moon/crisp#998), 1-12
9
+ * -- measured off Attio's own multi-select field option pills (flat
10
+ * black text, no ring, 7px radius). Wins over `tone` when both are set:
11
+ * `tone` is crisp's own semantic 7-tone chip family (with a ring), this
12
+ * is Attio's separate, workspace-admin-assigned enumerable palette,
13
+ * reproduced verbatim rather than mapped onto the existing tones.
14
+ */
15
+ swatch?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
7
16
  /**
8
17
  * Group heading, rendered above this option (#343). A header renders once
9
18
  * per run of consecutive options sharing the same `group` — like native
@@ -11,6 +11,16 @@ export type SelectOption = {
11
11
  keywords?: string;
12
12
  /** A status colour dot shown before the label (status/select fields). */
13
13
  color?: string;
14
+ /**
15
+ * One of Attio's 12 fixed tag/option colours (your-moon/crisp#998),
16
+ * 1-12 -- renders the label itself as a filled pill (measured: 22px,
17
+ * 7px radius, flat black text) rather than the small `color` dot beside
18
+ * it. The two are mutually exclusive; `swatch` wins if both are set.
19
+ * Distinct from `color`: that one is an arbitrary CSS value for a
20
+ * status-style dot, this is Attio's own enumerable, workspace-admin-
21
+ * assigned palette, reproduced verbatim.
22
+ */
23
+ swatch?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
14
24
  disabled?: boolean;
15
25
  /**
16
26
  * Group heading, rendered above this option (#343). A header renders once
@@ -9,7 +9,7 @@ export { hasNestedFloatingLayer, hasOpenFloatingLayer, isInsideLaterFloatingLaye
9
9
  export { formValueStyle } from "./form-value";
10
10
  export { type CrispComponentDefaults, type CrispMessages, CrispMessagesProvider, useCrispComponentDefaults, useCrispMessage, useCrispMessages, } from "./i18n";
11
11
  export { type MentionAnchor, type MentionMatch, matchMentionTrigger, } from "./mention";
12
- export { type FloatingAlign, type PlaceFloatingOptions, placeFloating, } from "./place-floating";
12
+ export { type FloatingAlign, type PlacedSubmenu, type PlaceFloatingOptions, type PlaceSubmenuOptions, placeFloating, placeSubmenu, } from "./place-floating";
13
13
  export { Primitive } from "./primitive";
14
14
  export { resolveRecipe } from "./resolve";
15
15
  export * from "./rtl";
@@ -38,3 +38,40 @@ export type PlacedFloating = {
38
38
  * against would still be physical.
39
39
  */
40
40
  export declare function placeFloating({ rect, align, gap, flipBelow, anchor, }: PlaceFloatingOptions): PlacedFloating;
41
+ export type PlaceSubmenuOptions = {
42
+ /** The item's own box that opens the submenu (already shifted up by the
43
+ * surface's own top padding, so the FIRST row of the submenu lines up
44
+ * with the item rather than the submenu's outer edge). */
45
+ rect: DOMRect;
46
+ /** The submenu surface's own rendered size (it's already in the DOM,
47
+ * just not yet positioned, when `Menu` calls this — a real measurement,
48
+ * not a guessed threshold). */
49
+ size: {
50
+ width: number;
51
+ height: number;
52
+ };
53
+ /** Gap between the item and the submenu. */
54
+ gap: number;
55
+ anchor?: Element | null;
56
+ };
57
+ export type PlacedSubmenu = {
58
+ style: React.CSSProperties;
59
+ /** Which side it opened on, in logical terms — for the caller's own
60
+ * animation-origin hint (reuses the same vocabulary `align` does). */
61
+ align: FloatingAlign;
62
+ /** True when it flipped to a bottom anchor instead of the item's top. */
63
+ up: boolean;
64
+ };
65
+ /**
66
+ * Where a cascading submenu goes, BESIDE the item that opens it — not below
67
+ * it, the way `placeFloating`'s own dropdown does. Opens toward the inline
68
+ * end by default (further into the reading direction) and flips to the
69
+ * inline start when the surface's measured width doesn't fit there.
70
+ *
71
+ * Live-measured on Attio's own object-page "…" menu (crisp#616): the
72
+ * Notifications submenu sits with NO gap against the item's opposite edge
73
+ * (its own edge lines up exactly with the item's), so callers pass `gap: 0`
74
+ * for this specific cascade rather than the 4px a dropdown uses against its
75
+ * trigger.
76
+ */
77
+ export declare function placeSubmenu({ rect, size, gap, anchor, }: PlaceSubmenuOptions): PlacedSubmenu;
@@ -68,6 +68,7 @@ export * from "./components/wheelpicker";
68
68
  export * from "./core";
69
69
  export * from "./product/activityfeed";
70
70
  export * from "./product/appshell";
71
+ export * from "./product/assigneepicker";
71
72
  export * from "./product/authshell";
72
73
  export * from "./product/board";
73
74
  export * from "./product/command";
@@ -81,20 +82,27 @@ export * from "./product/inbox";
81
82
  export * from "./product/listpage";
82
83
  export * from "./product/memberssettings";
83
84
  export * from "./product/navitem";
85
+ export * from "./product/notesgallery";
84
86
  export * from "./product/notificationssettings";
87
+ export * from "./product/objectpagemenu";
85
88
  export * from "./product/objectsettings";
86
89
  export * from "./product/onboarding";
87
90
  export * from "./product/recordpage";
88
91
  export * from "./product/recordpanel";
92
+ export * from "./product/recordpicker";
89
93
  export * from "./product/richtext";
90
94
  export * from "./product/savedviews";
91
95
  export * from "./product/settingssection";
92
96
  export * from "./product/settingsshell";
97
+ export * from "./product/share";
98
+ export * from "./product/shortcutssheet";
93
99
  export * from "./product/sidebar";
94
100
  export * from "./product/statlist";
101
+ export * from "./product/taskeditpopover";
95
102
  export * from "./product/tasklist";
96
103
  export * from "./product/themepicker";
97
104
  export * from "./product/trialbanner";
98
105
  export * from "./product/viewtoggle";
99
106
  export * from "./product/workspacegeneralsettings";
107
+ export * from "./product/workspaceswitchermenu";
100
108
  export * from "./tokens";
@@ -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";
@@ -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;