@crisp-ui-kit/crisp 0.54.1 → 0.54.3

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 (171) hide show
  1. package/dist/chip.css +7 -1
  2. package/dist/chip.d.ts +2 -1
  3. package/dist/chip.layered.css +7 -1
  4. package/dist/cjs/components/chip/chip.js +3 -2
  5. package/dist/cjs/components/chip/chip.recipe.js +37 -1
  6. package/dist/cjs/components/datatable/datatable.js +490 -111
  7. package/dist/cjs/components/datatable/datatable.recipe.js +4 -0
  8. package/dist/cjs/components/emptystate/emptystate.js +3 -2
  9. package/dist/cjs/components/emptystate/emptystate.recipe.js +26 -1
  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/personchip/index.js +17 -0
  14. package/dist/cjs/components/personchip/personchip.js +50 -0
  15. package/dist/cjs/components/table/table.js +2 -2
  16. package/dist/cjs/components/table/table.recipe.js +15 -3
  17. package/dist/cjs/components/tabs/tabs.js +2 -2
  18. package/dist/cjs/components/tabs/tabs.recipe.js +30 -3
  19. package/dist/cjs/components/text/index.js +7 -0
  20. package/dist/cjs/components/text/text.js +55 -0
  21. package/dist/cjs/components/text/text.recipe.js +34 -0
  22. package/dist/cjs/core/floating-stack.js +18 -0
  23. package/dist/cjs/core/index.js +2 -1
  24. package/dist/cjs/index.js +8 -0
  25. package/dist/cjs/product/formdialog/formdialog.js +171 -0
  26. package/dist/cjs/product/formdialog/formdialog.recipe.js +26 -0
  27. package/dist/cjs/product/formdialog/index.js +8 -0
  28. package/dist/cjs/product/headerbar/headerbar.recipe.js +9 -1
  29. package/dist/cjs/product/importdialog/importdialog.js +134 -0
  30. package/dist/cjs/product/importdialog/importdialog.recipe.js +92 -0
  31. package/dist/cjs/product/importdialog/index.js +18 -0
  32. package/dist/cjs/product/recordpage/recordpage.recipe.js +10 -1
  33. package/dist/cjs/product/recordstable/recordstable.js +89 -6
  34. package/dist/cjs/product/richtext/richtext.recipe.js +26 -1
  35. package/dist/cjs/product/savedviews/index.js +7 -0
  36. package/dist/cjs/product/savedviews/savedviews.js +207 -0
  37. package/dist/cjs/product/savedviews/savedviews.recipe.js +103 -0
  38. package/dist/cjs/product/taskstable/index.js +7 -0
  39. package/dist/cjs/product/taskstable/taskstable.js +27 -0
  40. package/dist/cjs/product/taskstable/taskstable.recipe.js +47 -0
  41. package/dist/cjs/product/themepicker/index.js +17 -0
  42. package/dist/cjs/product/themepicker/themepicker.js +32 -0
  43. package/dist/cjs/product/themepicker/themepicker.recipe.js +98 -0
  44. package/dist/cjs/tokens/palette.js +30 -13
  45. package/dist/cjs/tokens/semantic.js +6 -0
  46. package/dist/datatable.css +20 -21
  47. package/dist/datatable.layered.css +20 -21
  48. package/dist/emptystate.css +15 -1
  49. package/dist/emptystate.d.ts +2 -2
  50. package/dist/emptystate.layered.css +15 -1
  51. package/dist/esm/components/chip/chip.js +3 -2
  52. package/dist/esm/components/chip/chip.recipe.js +37 -1
  53. package/dist/esm/components/datatable/datatable.js +489 -111
  54. package/dist/esm/components/datatable/datatable.recipe.js +4 -0
  55. package/dist/esm/components/emptystate/emptystate.js +4 -3
  56. package/dist/esm/components/emptystate/emptystate.recipe.js +26 -1
  57. package/dist/esm/components/emptystate/index.js +1 -1
  58. package/dist/esm/components/mentionchip/index.js +2 -0
  59. package/dist/esm/components/mentionchip/mentionchip.js +21 -0
  60. package/dist/esm/components/mentionchip/mentionchip.recipe.js +35 -0
  61. package/dist/esm/components/personchip/index.js +1 -0
  62. package/dist/esm/components/personchip/personchip.js +47 -0
  63. package/dist/esm/components/table/table.js +2 -2
  64. package/dist/esm/components/table/table.recipe.js +15 -3
  65. package/dist/esm/components/tabs/tabs.js +2 -2
  66. package/dist/esm/components/tabs/tabs.recipe.js +30 -3
  67. package/dist/esm/components/text/index.js +2 -0
  68. package/dist/esm/components/text/text.js +19 -0
  69. package/dist/esm/components/text/text.recipe.js +31 -0
  70. package/dist/esm/core/floating-stack.js +17 -0
  71. package/dist/esm/core/index.js +1 -1
  72. package/dist/esm/index.js +8 -0
  73. package/dist/esm/product/formdialog/formdialog.js +134 -0
  74. package/dist/esm/product/formdialog/formdialog.recipe.js +23 -0
  75. package/dist/esm/product/formdialog/index.js +2 -0
  76. package/dist/esm/product/headerbar/headerbar.recipe.js +9 -1
  77. package/dist/esm/product/importdialog/importdialog.js +97 -0
  78. package/dist/esm/product/importdialog/importdialog.recipe.js +89 -0
  79. package/dist/esm/product/importdialog/index.js +2 -0
  80. package/dist/esm/product/recordpage/recordpage.recipe.js +10 -1
  81. package/dist/esm/product/recordstable/recordstable.js +90 -8
  82. package/dist/esm/product/richtext/richtext.recipe.js +26 -1
  83. package/dist/esm/product/savedviews/index.js +2 -0
  84. package/dist/esm/product/savedviews/savedviews.js +171 -0
  85. package/dist/esm/product/savedviews/savedviews.recipe.js +100 -0
  86. package/dist/esm/product/taskstable/index.js +2 -0
  87. package/dist/esm/product/taskstable/taskstable.js +24 -0
  88. package/dist/esm/product/taskstable/taskstable.recipe.js +44 -0
  89. package/dist/esm/product/themepicker/index.js +1 -0
  90. package/dist/esm/product/themepicker/themepicker.js +29 -0
  91. package/dist/esm/product/themepicker/themepicker.recipe.js +95 -0
  92. package/dist/esm/tokens/palette.js +30 -13
  93. package/dist/esm/tokens/semantic.js +6 -0
  94. package/dist/formdialog.css +6 -0
  95. package/dist/formdialog.d.ts +7 -0
  96. package/dist/formdialog.layered.css +8 -0
  97. package/dist/headerbar.css +1 -1
  98. package/dist/headerbar.layered.css +1 -1
  99. package/dist/importdialog.css +38 -0
  100. package/dist/importdialog.d.ts +7 -0
  101. package/dist/importdialog.layered.css +40 -0
  102. package/dist/mentionchip.css +3 -0
  103. package/dist/mentionchip.d.ts +7 -0
  104. package/dist/mentionchip.layered.css +5 -0
  105. package/dist/native/tokens.d.ts +1 -1
  106. package/dist/native/tokens.js +14 -6
  107. package/dist/recordpage.css +13 -2
  108. package/dist/recordpage.layered.css +13 -2
  109. package/dist/richtext.css +11 -1
  110. package/dist/richtext.layered.css +11 -1
  111. package/dist/savedviews.css +78 -0
  112. package/dist/savedviews.d.ts +7 -0
  113. package/dist/savedviews.layered.css +80 -0
  114. package/dist/styles.css +287 -37
  115. package/dist/styles.layered.css +287 -37
  116. package/dist/table.css +15 -6
  117. package/dist/table.layered.css +15 -6
  118. package/dist/tabs.css +7 -1
  119. package/dist/tabs.d.ts +2 -2
  120. package/dist/tabs.layered.css +7 -1
  121. package/dist/taskstable.css +23 -0
  122. package/dist/taskstable.d.ts +7 -0
  123. package/dist/taskstable.layered.css +25 -0
  124. package/dist/text.css +9 -0
  125. package/dist/text.d.ts +7 -0
  126. package/dist/text.layered.css +11 -0
  127. package/dist/themepicker.css +27 -0
  128. package/dist/themepicker.d.ts +7 -0
  129. package/dist/themepicker.layered.css +29 -0
  130. package/dist/tokens.css +7 -3
  131. package/dist/tokens.json +14 -6
  132. package/dist/types/components/chip/chip.d.ts +32 -0
  133. package/dist/types/components/chip/chip.recipe.d.ts +31 -0
  134. package/dist/types/components/datatable/datatable.d.ts +39 -4
  135. package/dist/types/components/emptystate/emptystate.d.ts +29 -4
  136. package/dist/types/components/emptystate/emptystate.recipe.d.ts +2 -0
  137. package/dist/types/components/emptystate/index.d.ts +1 -1
  138. package/dist/types/components/mentionchip/index.d.ts +2 -0
  139. package/dist/types/components/mentionchip/mentionchip.d.ts +20 -0
  140. package/dist/types/components/mentionchip/mentionchip.recipe.d.ts +18 -0
  141. package/dist/types/components/personchip/index.d.ts +1 -0
  142. package/dist/types/components/personchip/personchip.d.ts +37 -0
  143. package/dist/types/components/table/table.d.ts +36 -0
  144. package/dist/types/components/tabs/tabs.d.ts +4 -2
  145. package/dist/types/components/tabs/tabs.recipe.d.ts +18 -3
  146. package/dist/types/components/text/index.d.ts +2 -0
  147. package/dist/types/components/text/text.d.ts +32 -0
  148. package/dist/types/components/text/text.recipe.d.ts +40 -0
  149. package/dist/types/core/floating-stack.d.ts +14 -0
  150. package/dist/types/core/index.d.ts +1 -1
  151. package/dist/types/index.d.ts +8 -0
  152. package/dist/types/product/formdialog/formdialog.d.ts +57 -0
  153. package/dist/types/product/formdialog/formdialog.recipe.d.ts +3 -0
  154. package/dist/types/product/formdialog/index.d.ts +2 -0
  155. package/dist/types/product/importdialog/importdialog.d.ts +86 -0
  156. package/dist/types/product/importdialog/importdialog.recipe.d.ts +3 -0
  157. package/dist/types/product/importdialog/index.d.ts +2 -0
  158. package/dist/types/product/recordstable/recordstable.d.ts +24 -2
  159. package/dist/types/product/savedviews/index.d.ts +2 -0
  160. package/dist/types/product/savedviews/savedviews.d.ts +55 -0
  161. package/dist/types/product/savedviews/savedviews.recipe.d.ts +3 -0
  162. package/dist/types/product/taskstable/index.d.ts +2 -0
  163. package/dist/types/product/taskstable/taskstable.d.ts +54 -0
  164. package/dist/types/product/taskstable/taskstable.recipe.d.ts +3 -0
  165. package/dist/types/product/themepicker/index.d.ts +1 -0
  166. package/dist/types/product/themepicker/themepicker.d.ts +21 -0
  167. package/dist/types/product/themepicker/themepicker.recipe.d.ts +3 -0
  168. package/dist/types/tokens/contract.d.ts +2 -0
  169. package/dist/types/tokens/palette.d.ts +11 -3
  170. package/dist/types/tokens/semantic.d.ts +6 -0
  171. package/package.json +41 -1
@@ -3,6 +3,7 @@ declare const config: import("../..").RecipeConfig<{
3
3
  default: string;
4
4
  illustrated: string;
5
5
  page: string;
6
+ records: string;
6
7
  };
7
8
  }>;
8
9
  export declare const emptystateRecipe: import("../..").RecipeFn<{
@@ -10,6 +11,7 @@ export declare const emptystateRecipe: import("../..").RecipeFn<{
10
11
  default: string;
11
12
  illustrated: string;
12
13
  page: string;
14
+ records: string;
13
15
  };
14
16
  }>;
15
17
  export default config;
@@ -1,2 +1,2 @@
1
- export { EmptyState, type EmptyStateProps } from "./emptystate";
1
+ export { EmptyState, type EmptyStateLearnMore, type EmptyStateProps, } from "./emptystate";
2
2
  export { emptystateRecipe } from "./emptystate.recipe";
@@ -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;
@@ -0,0 +1 @@
1
+ export * from "./personchip";
@@ -0,0 +1,37 @@
1
+ import type * as React from "react";
2
+ export type PersonChipProps = Omit<React.ComponentPropsWithoutRef<"span">, "children"> & {
3
+ /** The person's display name — also the avatar's initials fallback. */
4
+ name: string;
5
+ /** A photo URL. Omitted (no populated photo field was reachable to
6
+ * measure this round), the avatar falls back to a per-name hashed-colour
7
+ * initials tile. */
8
+ avatar?: string;
9
+ /** De-emphasises the name (e.g. a departed person, a system actor) —
10
+ * `fgNeutralMuted`, the same token `Text`'s own `tone="muted"` uses.
11
+ * Applied to the name only; the avatar keeps its full-strength tone so
12
+ * the chip still reads as a distinct person, not a disabled control. */
13
+ muted?: boolean;
14
+ className?: string;
15
+ };
16
+ /**
17
+ * A person, as a chip: a small avatar (a photo, or hashed-colour initials)
18
+ * plus their name, truncating with an ellipsis when it doesn't fit — Attio's
19
+ * own actor chip (measured live on `techpartners`, Tasks page, "Assigned to"
20
+ * column): a 16px circular avatar in a neutral `Chip`, `gap: 3px` between
21
+ * avatar and name (now `Chip`'s own base — every multi-child `Chip` gets
22
+ * it). Every other value — the pill's height, padding, radius, ring and text
23
+ * — is already `Chip`'s, unchanged; `PersonChip` adds no recipe of its own.
24
+ *
25
+ * Ellipsis only, no `Tooltip` on hover (#623 — no Attio reference for one;
26
+ * a truncated cell there is revealed by its own click-to-expand, #579, a
27
+ * different, DataTable-specific interaction).
28
+ *
29
+ * Composes `Chip`'s `truncate` CSS directly rather than its string-only
30
+ * auto-wrap (children here is an avatar plus a name, not a single string),
31
+ * so the name gets its own `.crisp-chip-label` span while the avatar stays
32
+ * fixed-size.
33
+ */
34
+ export declare function PersonChip({ name, avatar, muted, className, ...props }: PersonChipProps): React.JSX.Element;
35
+ export declare namespace PersonChip {
36
+ var displayName: string;
37
+ }
@@ -8,6 +8,24 @@ export type TableProps = React.ComponentPropsWithoutRef<"table"> & VariantProps<
8
8
  scrollProps?: React.ComponentPropsWithoutRef<"div"> & {
9
9
  ref?: React.Ref<HTMLDivElement>;
10
10
  };
11
+ /**
12
+ * Style applied to the `<table>` element itself, as opposed to `style`
13
+ * (below), which sizes the OUTER bordered wrapper -- crisp/#581.
14
+ * `DataTable` uses this for its `min-width: <sum of column widths>`,
15
+ * which forces `<table>` to its true content width and lets
16
+ * `.crisp-table-scroll`'s existing `overflow-x: auto` scroll it
17
+ * internally. Putting that same min-width on the outer wrapper
18
+ * (`style`) instead, as this component used to require, forces the
19
+ * WRAPPER itself that wide -- a plain block box's width is normally set
20
+ * by its own container regardless of a child's min-width, so the only
21
+ * element that should ever be forced wider than its container is the
22
+ * scrollable one, never an ancestor of it. Getting this backwards is
23
+ * exactly what made a `DataTable` widen its own page instead of
24
+ * scrolling in place (internal/grc#117), forcing GRC to hand-build its
25
+ * own `overflow: hidden` clipping wrapper around it -- which the
26
+ * crisp-only rule forbids and which this makes unnecessary.
27
+ */
28
+ tableStyle?: React.CSSProperties;
11
29
  };
12
30
  /**
13
31
  * A composable data table. Wraps `<table>` in a horizontally scrollable
@@ -32,6 +50,24 @@ export declare const Table: React.ForwardRefExoticComponent<Omit<React.DetailedH
32
50
  scrollProps?: React.ComponentPropsWithoutRef<"div"> & {
33
51
  ref?: React.Ref<HTMLDivElement>;
34
52
  };
53
+ /**
54
+ * Style applied to the `<table>` element itself, as opposed to `style`
55
+ * (below), which sizes the OUTER bordered wrapper -- crisp/#581.
56
+ * `DataTable` uses this for its `min-width: <sum of column widths>`,
57
+ * which forces `<table>` to its true content width and lets
58
+ * `.crisp-table-scroll`'s existing `overflow-x: auto` scroll it
59
+ * internally. Putting that same min-width on the outer wrapper
60
+ * (`style`) instead, as this component used to require, forces the
61
+ * WRAPPER itself that wide -- a plain block box's width is normally set
62
+ * by its own container regardless of a child's min-width, so the only
63
+ * element that should ever be forced wider than its container is the
64
+ * scrollable one, never an ancestor of it. Getting this backwards is
65
+ * exactly what made a `DataTable` widen its own page instead of
66
+ * scrolling in place (internal/grc#117), forcing GRC to hand-build its
67
+ * own `overflow: hidden` clipping wrapper around it -- which the
68
+ * crisp-only rule forbids and which this makes unnecessary.
69
+ */
70
+ tableStyle?: React.CSSProperties;
35
71
  } & React.RefAttributes<HTMLTableElement>>;
36
72
  export declare const TableHeader: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & React.RefAttributes<HTMLTableSectionElement>>;
37
73
  export declare const TableBody: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>, "ref"> & React.RefAttributes<HTMLTableSectionElement>>;
@@ -1,4 +1,6 @@
1
1
  import * as React from "react";
2
+ import type { VariantProps } from "../../core";
3
+ import { tabsRecipe } from "./tabs.recipe";
2
4
  export type TabItem = {
3
5
  value: string;
4
6
  label: React.ReactNode;
@@ -8,7 +10,7 @@ export type TabItem = {
8
10
  badge?: React.ReactNode;
9
11
  disabled?: boolean;
10
12
  };
11
- export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "defaultValue" | "children"> & {
13
+ export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "defaultValue" | "children"> & VariantProps<typeof tabsRecipe> & {
12
14
  tabs: TabItem[];
13
15
  /** Controlled active value. Omit to let Tabs manage it (see defaultValue). */
14
16
  value?: string;
@@ -27,7 +29,7 @@ export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" | "d
27
29
  * Home/End jump); activation follows focus. Controlled via
28
30
  * `value`/`onValueChange`, or uncontrolled from `defaultValue`.
29
31
  */
30
- export declare function Tabs({ tabs, value, defaultValue, onValueChange, leading, children, className, "aria-label": ariaLabel, ...rest }: TabsProps): React.JSX.Element;
32
+ export declare function Tabs({ tabs, value, defaultValue, onValueChange, leading, children, className, fill, "aria-label": ariaLabel, ...rest }: TabsProps): React.JSX.Element;
31
33
  export declare namespace Tabs {
32
34
  var displayName: string;
33
35
  }
@@ -1,5 +1,20 @@
1
- declare const config: import("../..").RecipeConfig<{}>;
2
- export declare const tabsRecipe: import("../..").RecipeFn<{}> & {
3
- config: import("../..").RecipeConfig<{}>;
1
+ declare const config: import("../..").RecipeConfig<{
2
+ fill: {
3
+ true: string;
4
+ false: string;
5
+ };
6
+ }>;
7
+ export declare const tabsRecipe: import("../..").RecipeFn<{
8
+ fill: {
9
+ true: string;
10
+ false: string;
11
+ };
12
+ }> & {
13
+ config: import("../..").RecipeConfig<{
14
+ fill: {
15
+ true: string;
16
+ false: string;
17
+ };
18
+ }>;
4
19
  };
5
20
  export default config;
@@ -0,0 +1,2 @@
1
+ export { Text, type TextProps } from "./text";
2
+ export { textRecipe } from "./text.recipe";
@@ -0,0 +1,32 @@
1
+ import * as React from "react";
2
+ import type { VariantProps } from "../../core";
3
+ import { textRecipe } from "./text.recipe";
4
+ export type TextProps = React.ComponentPropsWithoutRef<"span"> & VariantProps<typeof textRecipe> & {
5
+ asChild?: boolean;
6
+ };
7
+ /**
8
+ * Plain coloured text — `tone="default"` (the app's primary text colour) or
9
+ * `"muted"` — for the runs of text that aren't a Badge, a Chip, a link, or
10
+ * any of crisp's other typed things: a cell's own yes/no, an empty-state
11
+ * caption, a secondary line under a heading. One component so every such
12
+ * spot reaches for crisp's own tokens instead of each hand-writing its own
13
+ * colour utility for the same two values.
14
+ *
15
+ * Renders a `<span>` (inherits its size/weight/line-height from context —
16
+ * see `text.recipe.ts`'s doc for why `Text` sets none of those itself).
17
+ */
18
+ export declare const Text: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & VariantProps<import("../..").RecipeFn<{
19
+ readonly tone: {
20
+ readonly default: string;
21
+ readonly muted: string;
22
+ };
23
+ }> & {
24
+ config: import("../..").RecipeConfig<{
25
+ readonly tone: {
26
+ readonly default: string;
27
+ readonly muted: string;
28
+ };
29
+ }>;
30
+ }> & {
31
+ asChild?: boolean;
32
+ } & React.RefAttributes<HTMLSpanElement>>;
@@ -0,0 +1,40 @@
1
+ declare const spec: {
2
+ readonly name: "text";
3
+ readonly base: {
4
+ readonly display: "inline";
5
+ };
6
+ readonly variants: {
7
+ tone: {
8
+ default: {
9
+ color: `var(--${string})`;
10
+ };
11
+ muted: {
12
+ color: `var(--${string})`;
13
+ };
14
+ };
15
+ };
16
+ readonly defaultVariants: {
17
+ readonly tone: "default";
18
+ };
19
+ };
20
+ declare const config: import("../..").RecipeConfig<{
21
+ readonly tone: {
22
+ readonly default: string;
23
+ readonly muted: string;
24
+ };
25
+ }>;
26
+ export declare const textRecipe: import("../..").RecipeFn<{
27
+ readonly tone: {
28
+ readonly default: string;
29
+ readonly muted: string;
30
+ };
31
+ }> & {
32
+ config: import("../..").RecipeConfig<{
33
+ readonly tone: {
34
+ readonly default: string;
35
+ readonly muted: string;
36
+ };
37
+ }>;
38
+ };
39
+ export { spec };
40
+ 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,9 +29,11 @@ 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";
36
+ export * from "./components/personchip";
35
37
  export * from "./components/popover";
36
38
  export * from "./components/progress";
37
39
  export * from "./components/quantitypicker";
@@ -49,6 +51,7 @@ export * from "./components/switch";
49
51
  export * from "./components/table";
50
52
  export * from "./components/tabletoolbar";
51
53
  export * from "./components/tabs";
54
+ export * from "./components/text";
52
55
  export * from "./components/textarea";
53
56
  export * from "./components/textlink";
54
57
  export * from "./components/timepicker";
@@ -64,7 +67,9 @@ export * from "./product/board";
64
67
  export * from "./product/command";
65
68
  export * from "./product/entitycard";
66
69
  export * from "./product/flowcanvas";
70
+ export * from "./product/formdialog";
67
71
  export * from "./product/headerbar";
72
+ export * from "./product/importdialog";
68
73
  export * from "./product/inbox";
69
74
  export * from "./product/listpage";
70
75
  export * from "./product/navitem";
@@ -73,11 +78,14 @@ export * from "./product/recordpage";
73
78
  export * from "./product/recordpanel";
74
79
  export * from "./product/recordstable";
75
80
  export * from "./product/richtext";
81
+ export * from "./product/savedviews";
76
82
  export * from "./product/settingssection";
77
83
  export * from "./product/settingsshell";
78
84
  export * from "./product/sidebar";
79
85
  export * from "./product/statlist";
80
86
  export * from "./product/tasklist";
87
+ export * from "./product/taskstable";
88
+ export * from "./product/themepicker";
81
89
  export * from "./product/trialbanner";
82
90
  export * from "./product/viewtoggle";
83
91
  export * from "./tokens";
@@ -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";
@@ -1,9 +1,14 @@
1
1
  import * as React from "react";
2
+ import { type EmptyStateLearnMore } from "../../components/emptystate";
2
3
  import type { EditableOption } from "./editable-field";
3
4
  type IconType = React.ComponentType<{
4
5
  size?: number;
5
6
  strokeWidth?: number;
6
7
  }>;
8
+ export declare function isLabelTruncated(el: {
9
+ scrollWidth: number;
10
+ clientWidth: number;
11
+ }): boolean;
7
12
  export type ColumnType = "entity" | "text" | "tags" | "number" | "url" | "date" | "currency" | "status" | "reference";
8
13
  export type StatusOption = {
9
14
  value: string;
@@ -123,6 +128,20 @@ export type RecordsTableProps = Omit<React.ComponentPropsWithoutRef<"div">, "chi
123
128
  * stable colour per name, matching what `DataTable`'s `avatarTone` offers).
124
129
  * Entity avatars only — `TAG_TONES`/tag/status tone logic is untouched. */
125
130
  avatarTone?: "brand" | "hashed";
131
+ /**
132
+ * #603: Attio's zero-*records* state (nothing imported yet, no active
133
+ * filter) adds an "Import CSV" / "Connect data source" pair and a
134
+ * "Learn more" card next to the usual "New record" action -- measured
135
+ * on Users/Workspaces, which show nothing else. Omit any of these and
136
+ * that piece is left out; omit the whole prop and the empty state is
137
+ * unchanged (just "New record"), since this hasn't been confirmed for
138
+ * every object type.
139
+ */
140
+ emptyStateExtra?: {
141
+ onImportCsv?: () => void;
142
+ onConnectDataSource?: () => void;
143
+ learnMore?: EmptyStateLearnMore;
144
+ };
126
145
  className?: string;
127
146
  };
128
147
  export declare function tagTone(t: string): string;
@@ -204,6 +223,9 @@ export type RecordsTableLabels = {
204
223
  setRecordPlaceholder: string;
205
224
  noRecords: string;
206
225
  untitled: string;
226
+ /** #603: the zero-records state's optional extra CTAs. */
227
+ importCsv: string;
228
+ connectDataSource: string;
207
229
  /** Aggregation names, keyed by the aggregation. */
208
230
  agg: Record<Agg, string>;
209
231
  /** Filter operator names, keyed by the operator. */
@@ -229,7 +251,7 @@ export type RecordsTableLabelsInput = Partial<Omit<RecordsTableLabels, "agg" | "
229
251
  agg?: Partial<Record<Agg, string>>;
230
252
  op?: Partial<Record<FilterOp, string>>;
231
253
  };
232
- type FilterOp = "contains" | "is" | "isnot" | "empty" | "notempty";
254
+ type FilterOp = "contains" | "doesnotcontain" | "startswith" | "endswith" | "is" | "isnot" | "empty" | "notempty";
233
255
  /**
234
256
  * A date-only cell is a CALENDAR DATE, not an instant. ECMA-262 parses the
235
257
  * date-only ISO forms — `1998`, `1998-09`, `1998-09-04` — as UTC midnight, and
@@ -251,6 +273,6 @@ export { formatCellDate, parseCellDate };
251
273
  * and a floating bulk-action bar (delete / deselect) when rows are selected.
252
274
  * Selection can be controlled via `selectedIds`/`onSelectionChange`.
253
275
  */
254
- export declare function RecordsTable({ labels, columns: columnsProp, rows: rowsProp, selectedIds, onSelectionChange, showNew, allowAddColumn, onOpenRecord, onOpenRecordPage, avatarTone, className, ...rest }: RecordsTableProps): React.JSX.Element;
276
+ export declare function RecordsTable({ labels, columns: columnsProp, rows: rowsProp, selectedIds, onSelectionChange, showNew, allowAddColumn, onOpenRecord, onOpenRecordPage, avatarTone, emptyStateExtra, className, ...rest }: RecordsTableProps): React.JSX.Element;
255
277
  export declare const defaultColumns: Column[];
256
278
  export declare const defaultRows: Row[];
@@ -0,0 +1,2 @@
1
+ export { type SavedView, SavedViews, type SavedViewsProps, } from "./savedviews";
2
+ export { savedviewsRecipe } from "./savedviews.recipe";