@crisp-ui-kit/crisp 0.54.0 → 0.54.2

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 (127) hide show
  1. package/dist/activityfeed.css +12 -0
  2. package/dist/activityfeed.d.ts +7 -0
  3. package/dist/activityfeed.layered.css +14 -0
  4. package/dist/badge.css +3 -0
  5. package/dist/badge.d.ts +2 -2
  6. package/dist/badge.layered.css +3 -0
  7. package/dist/cjs/components/badge/badge.recipe.js +10 -0
  8. package/dist/cjs/components/datatable/datatable.js +2 -1
  9. package/dist/cjs/components/datatable/datatable.recipe.js +4 -0
  10. package/dist/cjs/components/mentionchip/index.js +7 -0
  11. package/dist/cjs/components/mentionchip/mentionchip.js +57 -0
  12. package/dist/cjs/components/mentionchip/mentionchip.recipe.js +38 -0
  13. package/dist/cjs/components/table/table.recipe.js +15 -3
  14. package/dist/cjs/core/floating-stack.js +18 -0
  15. package/dist/cjs/core/index.js +2 -1
  16. package/dist/cjs/index.js +7 -0
  17. package/dist/cjs/product/activityfeed/activityfeed.js +38 -0
  18. package/dist/cjs/product/activityfeed/activityfeed.recipe.js +35 -0
  19. package/dist/cjs/product/activityfeed/index.js +10 -0
  20. package/dist/cjs/product/formdialog/formdialog.js +171 -0
  21. package/dist/cjs/product/formdialog/formdialog.recipe.js +26 -0
  22. package/dist/cjs/product/formdialog/index.js +8 -0
  23. package/dist/cjs/product/importdialog/importdialog.js +134 -0
  24. package/dist/cjs/product/importdialog/importdialog.recipe.js +92 -0
  25. package/dist/cjs/product/importdialog/index.js +18 -0
  26. package/dist/cjs/product/richtext/richtext.js +43 -0
  27. package/dist/cjs/product/savedviews/index.js +7 -0
  28. package/dist/cjs/product/savedviews/savedviews.js +207 -0
  29. package/dist/cjs/product/savedviews/savedviews.recipe.js +103 -0
  30. package/dist/cjs/product/taskstable/index.js +7 -0
  31. package/dist/cjs/product/taskstable/taskstable.js +27 -0
  32. package/dist/cjs/product/taskstable/taskstable.recipe.js +47 -0
  33. package/dist/cjs/product/themepicker/index.js +17 -0
  34. package/dist/cjs/product/themepicker/themepicker.js +32 -0
  35. package/dist/cjs/product/themepicker/themepicker.recipe.js +98 -0
  36. package/dist/cjs/tokens/palette.js +31 -0
  37. package/dist/cjs/tokens/semantic.js +11 -0
  38. package/dist/datatable.css +20 -21
  39. package/dist/datatable.layered.css +20 -21
  40. package/dist/esm/components/badge/badge.recipe.js +10 -0
  41. package/dist/esm/components/datatable/datatable.js +2 -1
  42. package/dist/esm/components/datatable/datatable.recipe.js +4 -0
  43. package/dist/esm/components/mentionchip/index.js +2 -0
  44. package/dist/esm/components/mentionchip/mentionchip.js +21 -0
  45. package/dist/esm/components/mentionchip/mentionchip.recipe.js +35 -0
  46. package/dist/esm/components/table/table.recipe.js +15 -3
  47. package/dist/esm/core/floating-stack.js +17 -0
  48. package/dist/esm/core/index.js +1 -1
  49. package/dist/esm/index.js +7 -0
  50. package/dist/esm/product/activityfeed/activityfeed.js +32 -0
  51. package/dist/esm/product/activityfeed/activityfeed.recipe.js +32 -0
  52. package/dist/esm/product/activityfeed/index.js +2 -0
  53. package/dist/esm/product/formdialog/formdialog.js +134 -0
  54. package/dist/esm/product/formdialog/formdialog.recipe.js +23 -0
  55. package/dist/esm/product/formdialog/index.js +2 -0
  56. package/dist/esm/product/importdialog/importdialog.js +97 -0
  57. package/dist/esm/product/importdialog/importdialog.recipe.js +89 -0
  58. package/dist/esm/product/importdialog/index.js +2 -0
  59. package/dist/esm/product/richtext/richtext.js +43 -0
  60. package/dist/esm/product/savedviews/index.js +2 -0
  61. package/dist/esm/product/savedviews/savedviews.js +171 -0
  62. package/dist/esm/product/savedviews/savedviews.recipe.js +100 -0
  63. package/dist/esm/product/taskstable/index.js +2 -0
  64. package/dist/esm/product/taskstable/taskstable.js +24 -0
  65. package/dist/esm/product/taskstable/taskstable.recipe.js +44 -0
  66. package/dist/esm/product/themepicker/index.js +1 -0
  67. package/dist/esm/product/themepicker/themepicker.js +29 -0
  68. package/dist/esm/product/themepicker/themepicker.recipe.js +95 -0
  69. package/dist/esm/tokens/palette.js +31 -0
  70. package/dist/esm/tokens/semantic.js +11 -0
  71. package/dist/formdialog.css +6 -0
  72. package/dist/formdialog.d.ts +7 -0
  73. package/dist/formdialog.layered.css +8 -0
  74. package/dist/importdialog.css +38 -0
  75. package/dist/importdialog.d.ts +7 -0
  76. package/dist/importdialog.layered.css +40 -0
  77. package/dist/mentionchip.css +3 -0
  78. package/dist/mentionchip.d.ts +7 -0
  79. package/dist/mentionchip.layered.css +5 -0
  80. package/dist/native/tokens.d.ts +1 -1
  81. package/dist/native/tokens.js +24 -4
  82. package/dist/savedviews.css +78 -0
  83. package/dist/savedviews.d.ts +7 -0
  84. package/dist/savedviews.layered.css +80 -0
  85. package/dist/styles.css +242 -27
  86. package/dist/styles.layered.css +242 -27
  87. package/dist/table.css +15 -6
  88. package/dist/table.layered.css +15 -6
  89. package/dist/taskstable.css +23 -0
  90. package/dist/taskstable.d.ts +7 -0
  91. package/dist/taskstable.layered.css +25 -0
  92. package/dist/themepicker.css +27 -0
  93. package/dist/themepicker.d.ts +7 -0
  94. package/dist/themepicker.layered.css +29 -0
  95. package/dist/tokens.css +10 -0
  96. package/dist/tokens.json +24 -4
  97. package/dist/types/components/badge/badge.d.ts +2 -0
  98. package/dist/types/components/badge/badge.recipe.d.ts +8 -0
  99. package/dist/types/components/datatable/datatable.d.ts +12 -1
  100. package/dist/types/components/mentionchip/index.d.ts +2 -0
  101. package/dist/types/components/mentionchip/mentionchip.d.ts +20 -0
  102. package/dist/types/components/mentionchip/mentionchip.recipe.d.ts +18 -0
  103. package/dist/types/core/floating-stack.d.ts +14 -0
  104. package/dist/types/core/index.d.ts +1 -1
  105. package/dist/types/index.d.ts +7 -0
  106. package/dist/types/product/activityfeed/activityfeed.d.ts +57 -0
  107. package/dist/types/product/activityfeed/activityfeed.recipe.d.ts +3 -0
  108. package/dist/types/product/activityfeed/index.d.ts +2 -0
  109. package/dist/types/product/formdialog/formdialog.d.ts +57 -0
  110. package/dist/types/product/formdialog/formdialog.recipe.d.ts +3 -0
  111. package/dist/types/product/formdialog/index.d.ts +2 -0
  112. package/dist/types/product/importdialog/importdialog.d.ts +86 -0
  113. package/dist/types/product/importdialog/importdialog.recipe.d.ts +3 -0
  114. package/dist/types/product/importdialog/index.d.ts +2 -0
  115. package/dist/types/product/savedviews/index.d.ts +2 -0
  116. package/dist/types/product/savedviews/savedviews.d.ts +55 -0
  117. package/dist/types/product/savedviews/savedviews.recipe.d.ts +3 -0
  118. package/dist/types/product/taskstable/index.d.ts +2 -0
  119. package/dist/types/product/taskstable/taskstable.d.ts +54 -0
  120. package/dist/types/product/taskstable/taskstable.recipe.d.ts +3 -0
  121. package/dist/types/product/themepicker/index.d.ts +1 -0
  122. package/dist/types/product/themepicker/themepicker.d.ts +21 -0
  123. package/dist/types/product/themepicker/themepicker.recipe.d.ts +3 -0
  124. package/dist/types/tokens/contract.d.ts +5 -0
  125. package/dist/types/tokens/palette.d.ts +20 -0
  126. package/dist/types/tokens/semantic.d.ts +11 -0
  127. package/package.json +36 -1
@@ -0,0 +1,29 @@
1
+ @layer crisp-components {
2
+ .crisp-themepicker {
3
+ display: flex; gap: var(--crisp-space-2); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
4
+ & .crisp-themepicker-option { box-sizing: border-box; display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); width: 224px; padding: var(--crisp-space-1); border: 1px solid var(--crisp-border-subtle); border-radius: 16px; background: var(--crisp-bg-surface); cursor: pointer; font-family: inherit; }
5
+ & .crisp-themepicker-option[data-selected] { border-color: var(--crisp-bg-brand-solid); }
6
+ & .crisp-themepicker-preview { box-sizing: border-box; display: flex; width: 100%; height: 114px; padding: var(--crisp-space-2); gap: var(--crisp-space-1-5); border-radius: var(--crisp-radius-xl); overflow: hidden; }
7
+ & .crisp-themepicker-preview-side { flex-shrink: 0; width: 28%; display: flex; flex-direction: column; gap: var(--crisp-space-1); }
8
+ & .crisp-themepicker-preview-bar { height: 4px; border-radius: var(--crisp-radius-full); }
9
+ & .crisp-themepicker-preview-bar:nth-child(1) { width: 70%; background: var(--crisp-bg-brand-solid); }
10
+ & .crisp-themepicker-preview-bar:nth-child(2) { width: 90%; }
11
+ & .crisp-themepicker-preview-bar:nth-child(3) { width: 60%; }
12
+ & .crisp-themepicker-preview-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1-5); border-radius: var(--crisp-radius-md); }
13
+ /* Light / System (default) swatch colours. */
14
+ & .crisp-themepicker-preview[data-swatch="light"], & .crisp-themepicker-preview[data-swatch="system"] { border: 1px solid #eeeff1; background: #fbfbfb; }
15
+ & [data-swatch="light"] .crisp-themepicker-preview-bar:not(:nth-child(1)), & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #eeeff1; }
16
+ & [data-swatch="light"] .crisp-themepicker-preview-main, & [data-swatch="system"] .crisp-themepicker-preview-main { background: #ffffff; }
17
+ & [data-swatch="light"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar, & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #eeeff1; }
18
+ /* Dark swatch colours -- always for "dark", and for "system" only when the OS itself reports dark. */
19
+ & .crisp-themepicker-preview[data-swatch="dark"] { border: 1px solid #1c1d1f; background: #0e0f10; }
20
+ & [data-swatch="dark"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
21
+ & [data-swatch="dark"] .crisp-themepicker-preview-main { background: #0a0a0a; }
22
+ & [data-swatch="dark"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #1c1d1f; }
23
+ @media (prefers-color-scheme: dark) { & .crisp-themepicker-preview[data-swatch="system"] { border: 1px solid #1c1d1f; background: #0e0f10; } & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; } & [data-swatch="system"] .crisp-themepicker-preview-main { background: #0a0a0a; } & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #1c1d1f; } }
24
+ & .crisp-themepicker-label { display: flex; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
25
+ & .crisp-themepicker-option[data-selected] .crisp-themepicker-label { color: var(--crisp-fg-primary); }
26
+ & .crisp-themepicker-radio { flex-shrink: 0; width: 14px; height: 14px; border-radius: var(--crisp-radius-full); border: 1px solid var(--crisp-border-default); box-sizing: border-box; }
27
+ & .crisp-themepicker-option[data-selected] .crisp-themepicker-radio { border: 4px solid var(--crisp-bg-brand-solid); }
28
+ }
29
+ }
package/dist/tokens.css CHANGED
@@ -7,6 +7,7 @@
7
7
  --crisp-bg-raised: #f4f4f5;
8
8
  --crisp-border-default: #e4e4e7;
9
9
  --crisp-border-subtle: #eeeff1;
10
+ --crisp-border-dropzone: #e6e7ea;
10
11
  --crisp-ring-neutral: transparent;
11
12
  --crisp-ring-field: rgba(0,0,0,0.06);
12
13
  --crisp-ring-switch: #d9dade;
@@ -25,6 +26,7 @@
25
26
  --crisp-fg-muted: #71717a;
26
27
  --crisp-bg-danger: #e5484d;
27
28
  --crisp-bg-danger-solid: #ba2525;
29
+ --crisp-fg-danger: #eb3b3b;
28
30
  --crisp-stroke-field-focus: #1a1c20;
29
31
  --crisp-fg-disabled: #d1d3d8;
30
32
  --crisp-bg-neutral-weak: #f3f4f5;
@@ -45,6 +47,9 @@
45
47
  --crisp-fg-warning-soft: #80520d;
46
48
  --crisp-fg-danger-soft: #a33539;
47
49
  --crisp-fg-neutral-soft: #686870;
50
+ --crisp-bg-purple-soft: #f5f0ff;
51
+ --crisp-fg-purple-soft: #6238b5;
52
+ --crisp-ring-purple-soft: #e8ddfe;
48
53
  }
49
54
 
50
55
  [data-theme="dark"] {
@@ -56,6 +61,7 @@
56
61
  --crisp-bg-raised: #101112;
57
62
  --crisp-border-default: #212224;
58
63
  --crisp-border-subtle: #1c1d1f;
64
+ --crisp-border-dropzone: #212224;
59
65
  --crisp-ring-neutral: #212224;
60
66
  --crisp-ring-field: #212224;
61
67
  --crisp-ring-switch: #212224;
@@ -74,6 +80,7 @@
74
80
  --crisp-fg-muted: #9a9aa2;
75
81
  --crisp-bg-danger: #ff5a5f;
76
82
  --crisp-bg-danger-solid: #ba2525;
83
+ --crisp-fg-danger: #ff5a5f;
77
84
  --crisp-stroke-field-focus: #f3f4f5;
78
85
  --crisp-fg-disabled: #5b606a;
79
86
  --crisp-bg-neutral-weak: #1d2025;
@@ -94,6 +101,9 @@
94
101
  --crisp-fg-warning-soft: #e0982a;
95
102
  --crisp-fg-danger-soft: #ff5a5f;
96
103
  --crisp-fg-neutral-soft: #9a9aa2;
104
+ --crisp-bg-purple-soft: #2f1e5a;
105
+ --crisp-fg-purple-soft: #d8c4ff;
106
+ --crisp-ring-purple-soft: #45297d;
97
107
  }
98
108
 
99
109
  :root {
package/dist/tokens.json CHANGED
@@ -9,6 +9,7 @@
9
9
  "bgRaised": "#f4f4f5",
10
10
  "borderDefault": "#e4e4e7",
11
11
  "borderSubtle": "#eeeff1",
12
+ "borderDropzone": "#e6e7ea",
12
13
  "ringNeutral": "transparent",
13
14
  "ringField": "rgba(0,0,0,0.06)",
14
15
  "ringSwitch": "#d9dade",
@@ -27,6 +28,7 @@
27
28
  "fgMuted": "#71717a",
28
29
  "bgDanger": "#e5484d",
29
30
  "bgDangerSolid": "#ba2525",
31
+ "fgDanger": "#eb3b3b",
30
32
  "strokeFieldFocus": "#1a1c20",
31
33
  "fgDisabled": "#d1d3d8",
32
34
  "bgNeutralWeak": "#f3f4f5",
@@ -46,7 +48,10 @@
46
48
  "fgSuccessSoft": "#186b3d",
47
49
  "fgWarningSoft": "#80520d",
48
50
  "fgDangerSoft": "#a33539",
49
- "fgNeutralSoft": "#686870"
51
+ "fgNeutralSoft": "#686870",
52
+ "bgPurpleSoft": "#f5f0ff",
53
+ "fgPurpleSoft": "#6238b5",
54
+ "ringPurpleSoft": "#e8ddfe"
50
55
  },
51
56
  "dark": {
52
57
  "bgBrandSolid": "#266df0",
@@ -57,6 +62,7 @@
57
62
  "bgRaised": "#101112",
58
63
  "borderDefault": "#212224",
59
64
  "borderSubtle": "#1c1d1f",
65
+ "borderDropzone": "#212224",
60
66
  "ringNeutral": "#212224",
61
67
  "ringField": "#212224",
62
68
  "ringSwitch": "#212224",
@@ -75,6 +81,7 @@
75
81
  "fgMuted": "#9a9aa2",
76
82
  "bgDanger": "#ff5a5f",
77
83
  "bgDangerSolid": "#ba2525",
84
+ "fgDanger": "#ff5a5f",
78
85
  "strokeFieldFocus": "#f3f4f5",
79
86
  "fgDisabled": "#5b606a",
80
87
  "bgNeutralWeak": "#1d2025",
@@ -94,7 +101,10 @@
94
101
  "fgSuccessSoft": "#2ea968",
95
102
  "fgWarningSoft": "#e0982a",
96
103
  "fgDangerSoft": "#ff5a5f",
97
- "fgNeutralSoft": "#9a9aa2"
104
+ "fgNeutralSoft": "#9a9aa2",
105
+ "bgPurpleSoft": "#2f1e5a",
106
+ "fgPurpleSoft": "#d8c4ff",
107
+ "ringPurpleSoft": "#45297d"
98
108
  }
99
109
  },
100
110
  "palette": {
@@ -106,6 +116,7 @@
106
116
  "gray900": "#101112",
107
117
  "line200": "#e4e4e7",
108
118
  "line100": "#eeeff1",
119
+ "line150": "#e6e7ea",
109
120
  "ringNeutral": "transparent",
110
121
  "ringField": "rgba(0,0,0,0.06)",
111
122
  "ringSwitch": "#d9dade",
@@ -125,6 +136,7 @@
125
136
  "brand700": "#1f5fd6",
126
137
  "red600": "#e5484d",
127
138
  "red700": "#ba2525",
139
+ "red500": "#eb3b3b",
128
140
  "fieldFocus": "#1a1c20",
129
141
  "disabledFg": "#d1d3d8",
130
142
  "neutralWeak": "#f3f4f5",
@@ -143,7 +155,10 @@
143
155
  "softSuccessText": "#186b3d",
144
156
  "softWarningText": "#80520d",
145
157
  "softDangerText": "#a33539",
146
- "softNeutralText": "#686870"
158
+ "softNeutralText": "#686870",
159
+ "purpleTint": "#f5f0ff",
160
+ "softPurpleText": "#6238b5",
161
+ "purpleRing": "#e8ddfe"
147
162
  },
148
163
  "dark": {
149
164
  "gray00": "#0a0a0a",
@@ -153,6 +168,7 @@
153
168
  "gray900": "#f5f5f5",
154
169
  "line200": "#212224",
155
170
  "line100": "#1c1d1f",
171
+ "line150": "#212224",
156
172
  "ringNeutral": "#212224",
157
173
  "ringField": "#212224",
158
174
  "ringSwitch": "#212224",
@@ -172,6 +188,7 @@
172
188
  "brand700": "#1f5fd6",
173
189
  "red600": "#ff5a5f",
174
190
  "red700": "#ba2525",
191
+ "red500": "#ff5a5f",
175
192
  "fieldFocus": "#f3f4f5",
176
193
  "disabledFg": "#5b606a",
177
194
  "neutralWeak": "#1d2025",
@@ -190,7 +207,10 @@
190
207
  "softSuccessText": "#2ea968",
191
208
  "softWarningText": "#e0982a",
192
209
  "softDangerText": "#ff5a5f",
193
- "softNeutralText": "#9a9aa2"
210
+ "softNeutralText": "#9a9aa2",
211
+ "purpleTint": "#2f1e5a",
212
+ "softPurpleText": "#d8c4ff",
213
+ "purpleRing": "#45297d"
194
214
  }
195
215
  },
196
216
  "space": {
@@ -13,6 +13,7 @@ export declare const Badge: React.ForwardRefExoticComponent<Omit<React.DetailedH
13
13
  readonly success: string;
14
14
  readonly warning: string;
15
15
  readonly danger: string;
16
+ readonly purple: string;
16
17
  };
17
18
  readonly size: {
18
19
  readonly small: string;
@@ -31,6 +32,7 @@ export declare const Badge: React.ForwardRefExoticComponent<Omit<React.DetailedH
31
32
  readonly success: string;
32
33
  readonly warning: string;
33
34
  readonly danger: string;
35
+ readonly purple: string;
34
36
  };
35
37
  readonly size: {
36
38
  readonly small: string;
@@ -48,6 +48,11 @@ declare const spec: {
48
48
  color: `var(--${string})`;
49
49
  boxShadow: string;
50
50
  };
51
+ readonly purple: {
52
+ readonly background: `var(--${string})`;
53
+ readonly color: `var(--${string})`;
54
+ readonly boxShadow: `inset 0 0 0 1px var(--${string})`;
55
+ };
51
56
  };
52
57
  readonly size: {
53
58
  readonly small: {
@@ -128,6 +133,7 @@ declare const config: import("../..").RecipeConfig<{
128
133
  readonly success: string;
129
134
  readonly warning: string;
130
135
  readonly danger: string;
136
+ readonly purple: string;
131
137
  };
132
138
  readonly size: {
133
139
  readonly small: string;
@@ -146,6 +152,7 @@ export declare const badgeRecipe: import("../..").RecipeFn<{
146
152
  readonly success: string;
147
153
  readonly warning: string;
148
154
  readonly danger: string;
155
+ readonly purple: string;
149
156
  };
150
157
  readonly size: {
151
158
  readonly small: string;
@@ -164,6 +171,7 @@ export declare const badgeRecipe: import("../..").RecipeFn<{
164
171
  readonly success: string;
165
172
  readonly warning: string;
166
173
  readonly danger: string;
174
+ readonly purple: string;
167
175
  };
168
176
  readonly size: {
169
177
  readonly small: string;
@@ -220,6 +220,17 @@ export type DataTableProps<T extends {
220
220
  * direction like `stickyFirst` does: it pins to the trailing edge, which is
221
221
  * the left edge under `dir="rtl"` (#288). */
222
222
  stickyLast?: boolean;
223
+ /** Props on the scroll element itself (`style`/`className`/other div
224
+ * attributes) -- for bounding the grid's height so its sticky header and
225
+ * calc footer (#554) pin the way Attio's own grid does, the same
226
+ * `scrollProps` shape `Table` already takes directly (its own doc comment
227
+ * on #554 assumes this -- `DataTable` didn't actually expose it, #569).
228
+ * e.g. `scrollProps={{ style: { maxHeight: "calc(100vh - 220px)" } }}`.
229
+ * `ref` and `onScroll` are owned internally (this component tracks its own
230
+ * sticky-column scroll shadows) and are dropped if passed. `className`
231
+ * merges with the internal `crisp-table-scroll` class the same way
232
+ * `Table`'s own `scrollProps` does. */
233
+ scrollProps?: Omit<React.ComponentPropsWithoutRef<"div">, "ref" | "onScroll">;
223
234
  /** BCP 47 locale for the built-in `date`/`number`/`currency` renderers
224
235
  * (default "en-US"). Formats the date and groups the number the way that
225
236
  * locale's readers expect — e.g. "mn-MN" renders a date as "2026.09.12"
@@ -254,7 +265,7 @@ export type DataTableProps<T extends {
254
265
  };
255
266
  export declare function DataTable<T extends {
256
267
  id: string;
257
- }>({ columns: columnsProp, data, selectable, selectedIds, onSelectionChange, selectAllLabel: selectAllLabelProp, selectRowLabel, selectionAnnouncement, columnMenu, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable, searchPlaceholder: searchPlaceholderProp, searchLabel: searchLabelProp, onEdit, stickyFirst, stickyLast, locale: localeProp, avatarTone, surface, interactive, onRowClick, onAddRow, addRowLabel: addRowLabelProp, empty: emptyProp, showCount, countLabel, toolbar, className, reorderRowLabel: reorderRowLabelProp, sortAscendingLabel: sortAscendingLabelProp, sortDescendingLabel: sortDescendingLabelProp, moveColumnLeftLabel: moveColumnLeftLabelProp, moveColumnRightLabel: moveColumnRightLabelProp, editColumnLabel: editColumnLabelProp, hideColumnLabel: hideColumnLabelProp, renameColumnLabel: renameColumnLabelProp, viewSettingsLabel: viewSettingsLabelProp, columnsGroupLabel: columnsGroupLabelProp, ...rest }: DataTableProps<T>): React.JSX.Element;
268
+ }>({ columns: columnsProp, data, selectable, selectedIds, onSelectionChange, selectAllLabel: selectAllLabelProp, selectRowLabel, selectionAnnouncement, columnMenu, onColumnsChange, groupBy, onRowsReorder, error, sort: sortProp, defaultSort, onSortChange, filterable, searchPlaceholder: searchPlaceholderProp, searchLabel: searchLabelProp, onEdit, stickyFirst, stickyLast, scrollProps, locale: localeProp, avatarTone, surface, interactive, onRowClick, onAddRow, addRowLabel: addRowLabelProp, empty: emptyProp, showCount, countLabel, toolbar, className, reorderRowLabel: reorderRowLabelProp, sortAscendingLabel: sortAscendingLabelProp, sortDescendingLabel: sortDescendingLabelProp, moveColumnLeftLabel: moveColumnLeftLabelProp, moveColumnRightLabel: moveColumnRightLabelProp, editColumnLabel: editColumnLabelProp, hideColumnLabel: hideColumnLabelProp, renameColumnLabel: renameColumnLabelProp, viewSettingsLabel: viewSettingsLabelProp, columnsGroupLabel: columnsGroupLabelProp, ...rest }: DataTableProps<T>): React.JSX.Element;
258
269
  export declare namespace DataTable {
259
270
  var displayName: string;
260
271
  }
@@ -0,0 +1,2 @@
1
+ export { MentionChip, type MentionChipProps } from "./mentionchip";
2
+ export { mentionChipRecipe } from "./mentionchip.recipe";
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ export type MentionChipProps = React.ComponentPropsWithoutRef<"span"> & {
3
+ asChild?: boolean;
4
+ };
5
+ /**
6
+ * A standalone "@mention" chip — the same look `RichTextEditor` draws
7
+ * inline while an editor is live (`.crisp-rte-mention`), exported on its
8
+ * own for a consumer rendering a mention OUTSIDE a mounted editor: a
9
+ * comment thread, a note's collapsed preview, anywhere a stored
10
+ * `@[Name](actor:id)`-shaped token needs to read as a person, not literal
11
+ * markup. Renders whatever `children` is given (the trigger character
12
+ * included, if the caller wants one, matching how `RichTextEditor`'s own
13
+ * chip includes it) rather than assuming an `@` prefix itself — plain text,
14
+ * no built-in click/remove behaviour (none was asked for; add one once a
15
+ * real interaction is measured, the same reasoning `Chip`'s own doc gives
16
+ * for not guessing a remove affordance).
17
+ */
18
+ export declare const MentionChip: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
19
+ asChild?: boolean;
20
+ } & React.RefAttributes<HTMLElement>>;
@@ -0,0 +1,18 @@
1
+ declare const spec: {
2
+ readonly name: "mention-chip";
3
+ readonly base: {
4
+ readonly display: "inline";
5
+ readonly borderRadius: `var(--${string})`;
6
+ readonly paddingInline: `var(--${string})`;
7
+ readonly background: `color-mix(in srgb, var(--${string}) 14%, transparent)`;
8
+ readonly color: `color-mix(in srgb, var(--${string}) 82%, var(--${string}))`;
9
+ readonly fontWeight: `var(--${string})`;
10
+ readonly cursor: "default";
11
+ };
12
+ };
13
+ declare const config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
14
+ export declare const mentionChipRecipe: import("../..").RecipeFn<Record<string, Record<string, string>>> & {
15
+ config: import("../..").RecipeConfig<Record<string, Record<string, string>>>;
16
+ };
17
+ export { spec };
18
+ export default config;
@@ -11,6 +11,20 @@ export declare function registerFloatingLayer(el: HTMLElement): () => void;
11
11
  * right query for "was this click inside some floating child I opened".
12
12
  */
13
13
  export declare function isInsideLaterFloatingLayer(target: Node, self: HTMLElement | null): boolean;
14
+ /**
15
+ * True when a layer is registered strictly after `self` — i.e. `self` has
16
+ * spawned a still-open nested layer of its own (a row's kebab `Menu` inside
17
+ * `SavedViews`' own panel, e.g.).
18
+ *
19
+ * This is `hasOpenFloatingLayer`'s sibling for a caller that DOES register
20
+ * itself on this stack: `hasOpenFloatingLayer` reads "is the stack
21
+ * non-empty", which is always true for such a caller once its own layer is
22
+ * open — checking that before closing on Escape would defer to itself
23
+ * forever and Escape would never close it. `self`'s own position on the
24
+ * stack has to be excluded from the count, which `hasOpenFloatingLayer`
25
+ * cannot do since it takes no argument.
26
+ */
27
+ export declare function hasNestedFloatingLayer(self: HTMLElement | null): boolean;
14
28
  /**
15
29
  * True when at least one `Select`/`MultiSelect`/`Menu`/`Popover`/
16
30
  * `ContextMenu` is currently open, anywhere (#361).
@@ -5,7 +5,7 @@ export { defineRecipe } from "./define";
5
5
  export { withDescribedBy } from "./dialog-description";
6
6
  export { isRtlElement } from "./direction";
7
7
  export { FloatingPortal } from "./floating-portal";
8
- export { hasOpenFloatingLayer, isInsideLaterFloatingLayer, registerFloatingLayer, } from "./floating-stack";
8
+ export { hasNestedFloatingLayer, hasOpenFloatingLayer, isInsideLaterFloatingLayer, registerFloatingLayer, } from "./floating-stack";
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";
@@ -29,6 +29,7 @@ export * from "./components/heatmapchart";
29
29
  export * from "./components/input";
30
30
  export * from "./components/kbd";
31
31
  export * from "./components/linechart";
32
+ export * from "./components/mentionchip";
32
33
  export * from "./components/menu";
33
34
  export * from "./components/middletruncate";
34
35
  export * from "./components/multiselect";
@@ -57,13 +58,16 @@ export * from "./components/tooltip";
57
58
  export * from "./components/visuallyhidden";
58
59
  export * from "./components/wheelpicker";
59
60
  export * from "./core";
61
+ export * from "./product/activityfeed";
60
62
  export * from "./product/appshell";
61
63
  export * from "./product/authshell";
62
64
  export * from "./product/board";
63
65
  export * from "./product/command";
64
66
  export * from "./product/entitycard";
65
67
  export * from "./product/flowcanvas";
68
+ export * from "./product/formdialog";
66
69
  export * from "./product/headerbar";
70
+ export * from "./product/importdialog";
67
71
  export * from "./product/inbox";
68
72
  export * from "./product/listpage";
69
73
  export * from "./product/navitem";
@@ -72,11 +76,14 @@ export * from "./product/recordpage";
72
76
  export * from "./product/recordpanel";
73
77
  export * from "./product/recordstable";
74
78
  export * from "./product/richtext";
79
+ export * from "./product/savedviews";
75
80
  export * from "./product/settingssection";
76
81
  export * from "./product/settingsshell";
77
82
  export * from "./product/sidebar";
78
83
  export * from "./product/statlist";
79
84
  export * from "./product/tasklist";
85
+ export * from "./product/taskstable";
86
+ export * from "./product/themepicker";
80
87
  export * from "./product/trialbanner";
81
88
  export * from "./product/viewtoggle";
82
89
  export * from "./tokens";
@@ -0,0 +1,57 @@
1
+ import type * as React from "react";
2
+ export type ActivityFeedProps = React.ComponentPropsWithoutRef<"div"> & {
3
+ className?: string;
4
+ };
5
+ /**
6
+ * A record's own event timeline — a vertically stacked, bordered list of
7
+ * `ActivityFeedRow`s, capped at a readable content width. Built for
8
+ * internal/grc's per-record "Activity" tab (crisp#462 SHELL/forms gap): it
9
+ * replaces a hand-rolled `<div className="mx-auto max-w-3xl space-y-4
10
+ * p-6">`. No live Attio re-measurement behind its own chrome this pass (the
11
+ * CDP bridge was unreachable when this was built) — see the recipe's own
12
+ * doc comment for which already-measured crisp values it reuses instead of
13
+ * a new guess.
14
+ */
15
+ export declare function ActivityFeed({ className, children, ...rest }: ActivityFeedProps): React.JSX.Element;
16
+ export declare namespace ActivityFeed {
17
+ var displayName: string;
18
+ }
19
+ export type ActivityFeedRowProps = {
20
+ /** Who did it — a chip, an avatar+name, whatever the consumer's identity
21
+ * treatment is. crisp renders no actor chip of its own. */
22
+ actor: React.ReactNode;
23
+ /** What happened — a tag/badge naming the action. */
24
+ action: React.ReactNode;
25
+ /** When — already formatted for display. */
26
+ when: React.ReactNode;
27
+ /** An optional field-level diff list under the row (see
28
+ * `ActivityFeedDiffItem`). */
29
+ children?: React.ReactNode;
30
+ };
31
+ /** One event row: actor + action + timestamp, with an optional diff list
32
+ * underneath. The last row in an `ActivityFeed` draws no divider. */
33
+ export declare function ActivityFeedRow({ actor, action, when, children, }: ActivityFeedRowProps): React.JSX.Element;
34
+ export declare namespace ActivityFeedRow {
35
+ var displayName: string;
36
+ }
37
+ export type ActivityFeedDiffItemProps = {
38
+ /** The changed field's label. */
39
+ field: React.ReactNode;
40
+ /** The prior value, already formatted — omit for a "set to" (no known
41
+ * prior value) row. */
42
+ before?: React.ReactNode;
43
+ /** The new value, already formatted. */
44
+ after: React.ReactNode;
45
+ };
46
+ /** One changed-field line under an `ActivityFeedRow` — "Field: before →
47
+ * after", or "Field: set to after" when there is no known prior value. */
48
+ export declare function ActivityFeedDiffItem({ field, before, after, }: ActivityFeedDiffItemProps): React.JSX.Element;
49
+ export declare namespace ActivityFeedDiffItem {
50
+ var displayName: string;
51
+ }
52
+ export declare function ActivityFeedDiffList({ children, }: {
53
+ children: React.ReactNode;
54
+ }): React.JSX.Element;
55
+ export declare namespace ActivityFeedDiffList {
56
+ var displayName: string;
57
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const activityfeedRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { ActivityFeed, ActivityFeedDiffItem, type ActivityFeedDiffItemProps, ActivityFeedDiffList, type ActivityFeedProps, ActivityFeedRow, type ActivityFeedRowProps, } from "./activityfeed";
2
+ export { activityfeedRecipe } from "./activityfeed.recipe";
@@ -0,0 +1,57 @@
1
+ import * as React from "react";
2
+ /** See `OptionalLabelsContext`. Call from a field wrapper as
3
+ * `optional={useFormDialogOptional(required)}`. */
4
+ export declare function useFormDialogOptional(required: boolean): boolean;
5
+ export type FormDialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title" | "children" | "onSubmit" | "onClose"> & {
6
+ title: React.ReactNode;
7
+ /** The primary button's label on an edit dialog ("Save"). Ignored when
8
+ * `createMode` is set — Attio's own button always reads "Create record",
9
+ * never the object's name (measured live: "New Company"'s dialog still
10
+ * says "Create record", not "Create company"). */
11
+ submitLabel: React.ReactNode;
12
+ /** Called on submit — click, Enter in a field, or (in `createMode`)
13
+ * Cmd/Ctrl+Enter — with whether the "Create more" switch was on at that
14
+ * moment. An edit dialog (no switch, always `false`) can ignore it. */
15
+ onSubmit: (createMore: boolean) => void;
16
+ onClose: () => void;
17
+ busy?: boolean;
18
+ /** Anything the server rejected that belongs to no one field. */
19
+ error?: React.ReactNode;
20
+ children: React.ReactNode;
21
+ /** Widens the dialog for a form with more columns to hold. */
22
+ wide?: boolean;
23
+ /** Dialog content width in px, overrides `wide`. */
24
+ size?: number;
25
+ /** Bundles Attio's whole "New Company" create-dialog chrome (crisp#548,
26
+ * measured live): "(optional)" on every non-required field (via
27
+ * `useFormDialogOptional`); a footer of a "Create more" switch and a
28
+ * single "Create record ⌘↵" button with NO Cancel — Attio's dialog
29
+ * closes only from the header's ×; and Cmd/Ctrl+Enter submitting from
30
+ * anywhere inside the dialog, including a portaled Select/DatePicker
31
+ * popover. Only ever set by a create dialog — an edit dialog keeps
32
+ * Cancel + `submitLabel`, unmeasured territory the audit never touched. */
33
+ createMode?: boolean;
34
+ createMoreLabel?: string;
35
+ cancelLabel?: string;
36
+ discardTitle?: string;
37
+ discardConfirmLabel?: string;
38
+ discardCancelLabel?: string;
39
+ };
40
+ /**
41
+ * A modal for a create or edit form — crisp's own `Dialog`/`DialogBody`/
42
+ * `DialogFooter`, plus everything a record-creating form needs beyond plain
43
+ * chrome (crisp#548, moved out of internal/grc's own `forms.tsx`, called
44
+ * from nine places there): dirty tracking with a discard-changes confirm
45
+ * (any click/change/input inside the form marks it dirty; Escape/backdrop/
46
+ * header-×/Cancel all route through one `requestClose`, which only asks
47
+ * when something actually changed — a stacked crisp `Dialog`), a
48
+ * `beforeunload` guard for a reload or external navigation, and
49
+ * scroll-to-first-invalid-field once a submit attempt finishes (crisp's own
50
+ * `FormField` already marks every control `aria-invalid`, so this needs no
51
+ * per-field wiring). A record needs several fields at once to be valid,
52
+ * which is why records are not created by inline editing.
53
+ */
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 namespace FormDialog {
56
+ var displayName: string;
57
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const formdialogRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { FormDialog, type FormDialogProps, useFormDialogOptional, } from "./formdialog";
2
+ export { formdialogRecipe } from "./formdialog.recipe";
@@ -0,0 +1,86 @@
1
+ import type { FileRejection, UseFileUploadProps } from "@seed-design/react-file-upload";
2
+ import * as React from "react";
3
+ export type { FileRejection };
4
+ export type ImportDialogStep = {
5
+ /** Stable id, compared against `activeStep`. */
6
+ id: string;
7
+ label: React.ReactNode;
8
+ };
9
+ /**
10
+ * Root props land on the DIALOG SURFACE — same convention as `Dialog`/
11
+ * `Drawer` (#223): the element a consumer actually wants to reach (for
12
+ * `aria-describedby`, a `data-testid`, a `style`) is the panel, not the
13
+ * portal wrapper.
14
+ */
15
+ export type ImportDialogProps = Omit<React.ComponentPropsWithoutRef<"div">, "title" | "children"> & {
16
+ open: boolean;
17
+ onOpenChange: (open: boolean) => void;
18
+ /** Header title (default "Import"). */
19
+ title?: React.ReactNode;
20
+ /** The fixed step header — id + label pairs, in order. */
21
+ steps: ImportDialogStep[];
22
+ /** Which step's id is current — drives both the header pill and, when a
23
+ * consumer wires `onStepClick`, which row gets `aria-current`. */
24
+ activeStep: string;
25
+ /** Fired when an earlier step's pill is clicked. Omit to make the header
26
+ * display-only (Attio's own back-navigation between steps wasn't part of
27
+ * this measurement pass). */
28
+ onStepClick?: (id: string) => void;
29
+ /** The active step's body. */
30
+ children?: React.ReactNode;
31
+ /** Primary action label (e.g. "Next", "Import 40 rows"). Default "Next". */
32
+ primaryLabel?: React.ReactNode;
33
+ onPrimary?: () => void;
34
+ primaryDisabled?: boolean;
35
+ "aria-label"?: string;
36
+ /** aria-label on the close button (default "Close"). */
37
+ closeLabel?: string;
38
+ };
39
+ /**
40
+ * A full-viewport step wizard — Attio's own CSV import flow (measured live:
41
+ * `1584x871` filling a ~1600x900 viewport, `border-radius: 0`, no shadow,
42
+ * opaque white). Composes Zag's dialog machine for focus-trap/scroll-lock/
43
+ * Escape exactly like `Dialog`/`Drawer`, with its own recipe for the
44
+ * full-bleed chrome neither of those two share (see importdialog.recipe.ts).
45
+ *
46
+ * The step header and footer are generic — the wizard doesn't know about
47
+ * CSV. Step 1's body is typically `ImportDialogDropzone`; steps 2-4
48
+ * (map columns / review values / preview import) are consumer-supplied
49
+ * `children`, since Attio's own column-mapping UI wasn't part of this
50
+ * measurement pass.
51
+ */
52
+ export declare function ImportDialog({ open, onOpenChange, title, steps, activeStep, onStepClick, children, primaryLabel, onPrimary, primaryDisabled, "aria-label": ariaLabel, closeLabel: closeLabelProp, className, style, "aria-describedby": describedBy, ...rest }: ImportDialogProps): React.JSX.Element | null;
53
+ export declare namespace ImportDialog {
54
+ var displayName: string;
55
+ }
56
+ export type ImportDialogDropzoneProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "onDrop"> & {
57
+ /** Accepted file type(s), e.g. ".csv" (the default) or "text/csv". */
58
+ accept?: UseFileUploadProps["accept"];
59
+ disabled?: boolean;
60
+ maxFileSize?: number;
61
+ /** Fired with the accepted file. One file per drop/pick — a CSV import
62
+ * has exactly one source file, unlike the generic `FileUpload` list. */
63
+ onFileAccept?: (file: File) => void;
64
+ onFileReject?: (rejections: FileRejection[]) => void;
65
+ dropLabel?: React.ReactNode;
66
+ orLabel?: React.ReactNode;
67
+ chooseLabel?: React.ReactNode;
68
+ learnMoreHref?: string;
69
+ learnMoreLabel?: React.ReactNode;
70
+ };
71
+ /**
72
+ * The step-1 drop target — measured chrome (`border: 1px dashed
73
+ * rgb(230,231,234)`, `border-radius: 20px`, `background: rgb(251,251,251)`)
74
+ * over the SAME headless drag/drop + file-picker engine `FileUpload` uses
75
+ * (`@seed-design/react-file-upload`'s `useFileUpload`), rather than a fork
76
+ * of it. `FileUpload`'s own rendered markup (a single button carrying one
77
+ * title + one hint) can't host this dropzone's four separate pieces of copy
78
+ * — a title, an "or" divider, a "Choose a .CSV file" trigger, and a "Learn
79
+ * more" link that needs its own `<a href>` — so this composes the hook
80
+ * directly instead of wrapping `<FileUpload>`, and the engine (not this
81
+ * file) still owns every bit of drag-state/accept/reject behaviour.
82
+ */
83
+ export declare function ImportDialogDropzone({ accept, disabled, maxFileSize, onFileAccept, onFileReject, dropLabel, orLabel, chooseLabel, learnMoreHref, learnMoreLabel, className, id, ...rest }: ImportDialogDropzoneProps): React.JSX.Element;
84
+ export declare namespace ImportDialogDropzone {
85
+ var displayName: string;
86
+ }
@@ -0,0 +1,3 @@
1
+ declare const config: import("../..").RecipeConfig<{}>;
2
+ export declare const importdialogRecipe: import("../..").RecipeFn<{}>;
3
+ export default config;
@@ -0,0 +1,2 @@
1
+ export * from "./importdialog";
2
+ export * from "./importdialog.recipe";
@@ -0,0 +1,2 @@
1
+ export { type SavedView, SavedViews, type SavedViewsProps, } from "./savedviews";
2
+ export { savedviewsRecipe } from "./savedviews.recipe";