@ciridae/ui 1.0.2 → 1.0.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 (209) hide show
  1. package/dist/app/auth.d.ts +10 -0
  2. package/dist/app/auth.js +60 -0
  3. package/dist/app/error-boundary.d.ts +18 -0
  4. package/dist/app/error-boundary.js +45 -0
  5. package/dist/app/feedback.d.ts +12 -0
  6. package/dist/app/feedback.js +128 -0
  7. package/dist/app/index.d.ts +8 -0
  8. package/dist/app/index.js +8 -0
  9. package/dist/app/request-errors.d.ts +63 -0
  10. package/dist/app/request-errors.js +172 -0
  11. package/dist/app/sentry.d.ts +18 -0
  12. package/dist/app/sentry.js +52 -0
  13. package/dist/app/telemetry.d.ts +7 -0
  14. package/dist/app/telemetry.js +28 -0
  15. package/dist/app/trail.d.ts +9 -0
  16. package/dist/app/trail.js +18 -0
  17. package/dist/chat/chat-query-keys.d.ts +3 -3
  18. package/dist/chat/contract.d.ts +15 -15
  19. package/dist/chat/conversation-items-query-options.d.ts +114 -114
  20. package/dist/chat/conversation-source.d.ts +89 -0
  21. package/dist/chat/conversation-source.js +1 -0
  22. package/dist/chat/describe-tool-call.d.ts +3 -3
  23. package/dist/chat/describe-tool-call.js +3 -3
  24. package/dist/chat/message-text.d.ts +1 -1
  25. package/dist/chat/message-text.js +116 -48
  26. package/dist/chat/use-conversation-list.d.ts +6 -6
  27. package/dist/ciridae.css +16 -4
  28. package/dist/components/activity-feed.d.ts +3 -2
  29. package/dist/components/activity-feed.js +1 -0
  30. package/dist/components/agent-work.d.ts +3 -3
  31. package/dist/components/app-frame.d.ts +91 -0
  32. package/dist/components/app-frame.js +134 -0
  33. package/dist/components/app-navigation.d.ts +30 -3
  34. package/dist/components/app-navigation.js +105 -14
  35. package/dist/components/badge.d.ts +30 -5
  36. package/dist/components/badge.js +134 -15
  37. package/dist/components/brand-icons.d.ts +3 -3
  38. package/dist/components/bulk-action-bar.d.ts +1 -1
  39. package/dist/components/bulk-action-bar.js +3 -3
  40. package/dist/components/button.d.ts +12 -5
  41. package/dist/components/button.js +77 -44
  42. package/dist/components/calendar.d.ts +1 -1
  43. package/dist/components/calendar.js +44 -17
  44. package/dist/components/centered-page.d.ts +1 -1
  45. package/dist/components/centered-page.js +2 -2
  46. package/dist/components/chart.d.ts +22 -2
  47. package/dist/components/chart.js +251 -51
  48. package/dist/components/chat-client-source.d.ts +16 -0
  49. package/dist/components/chat-client-source.js +297 -0
  50. package/dist/components/chat-page.d.ts +9 -8
  51. package/dist/components/chat-page.js +7 -11
  52. package/dist/components/chat-sheet-controller.d.ts +11 -14
  53. package/dist/components/chat-sheet-controller.js +3 -3
  54. package/dist/components/chat-sheet.d.ts +18 -11
  55. package/dist/components/chat-sheet.js +188 -289
  56. package/dist/components/chat.d.ts +109 -19
  57. package/dist/components/chat.js +520 -124
  58. package/dist/components/checkbox-item.d.ts +6 -3
  59. package/dist/components/checkbox-item.js +9 -5
  60. package/dist/components/checkbox-list.d.ts +1 -1
  61. package/dist/components/chip.d.ts +6 -1
  62. package/dist/components/chip.js +27 -1
  63. package/dist/components/collapsible.d.ts +1 -1
  64. package/dist/components/color-theme.d.ts +1 -1
  65. package/dist/components/column-settings.d.ts +1 -1
  66. package/dist/components/column-settings.js +1 -1
  67. package/dist/components/command-menu.d.ts +5 -1
  68. package/dist/components/command-menu.js +98 -32
  69. package/dist/components/command-palette.d.ts +7 -3
  70. package/dist/components/command-palette.js +20 -11
  71. package/dist/components/copyable-id.d.ts +22 -5
  72. package/dist/components/copyable-id.js +46 -6
  73. package/dist/components/data-display.d.ts +39 -8
  74. package/dist/components/data-display.js +138 -19
  75. package/dist/components/data-grid.d.ts +23 -11
  76. package/dist/components/data-grid.js +61 -26
  77. package/dist/components/date-range-picker.d.ts +1 -1
  78. package/dist/components/date-range-picker.js +9 -20
  79. package/dist/components/date-time.d.ts +1 -1
  80. package/dist/components/dialog-height-context.d.ts +1 -1
  81. package/dist/components/document-viewer.d.ts +2 -2
  82. package/dist/components/drawer.d.ts +11 -6
  83. package/dist/components/drawer.js +91 -54
  84. package/dist/components/dropzone.d.ts +4 -4
  85. package/dist/components/editable-field.d.ts +12 -3
  86. package/dist/components/editable-field.js +57 -27
  87. package/dist/components/email-input.d.ts +1 -1
  88. package/dist/components/email-input.js +6 -5
  89. package/dist/components/environment-frame.d.ts +2 -2
  90. package/dist/components/environment-frame.js +37 -6
  91. package/dist/components/expandable-text.d.ts +1 -1
  92. package/dist/components/feedback-screenshot.d.ts +1 -1
  93. package/dist/components/feedback-sheet.d.ts +18 -3
  94. package/dist/components/feedback-sheet.js +216 -55
  95. package/dist/components/field-context.d.ts +1 -1
  96. package/dist/components/filter-bar.d.ts +3 -3
  97. package/dist/components/filter-bar.js +43 -29
  98. package/dist/components/form-controls.d.ts +12 -3
  99. package/dist/components/form-controls.js +46 -22
  100. package/dist/components/form-layout.d.ts +14 -10
  101. package/dist/components/form-layout.js +68 -23
  102. package/dist/components/glass-menu.d.ts +3 -0
  103. package/dist/components/glass-menu.js +63 -0
  104. package/dist/components/gradient-edge.d.ts +9 -0
  105. package/dist/components/gradient-edge.js +31 -0
  106. package/dist/components/hotkeys.d.ts +2 -2
  107. package/dist/components/icon.d.ts +1 -1
  108. package/dist/components/input.d.ts +7 -5
  109. package/dist/components/input.js +29 -17
  110. package/dist/components/keyboard-shortcuts.d.ts +2 -2
  111. package/dist/components/keycap.d.ts +10 -6
  112. package/dist/components/keycap.js +57 -19
  113. package/dist/components/layout.d.ts +13 -13
  114. package/dist/components/lightbox.d.ts +9 -3
  115. package/dist/components/lightbox.js +13 -9
  116. package/dist/components/link.d.ts +1 -1
  117. package/dist/components/locale.d.ts +42 -2
  118. package/dist/components/locale.js +43 -3
  119. package/dist/components/log-entry.d.ts +40 -0
  120. package/dist/components/log-entry.js +146 -0
  121. package/dist/components/log-list.d.ts +3 -3
  122. package/dist/components/mention-input.d.ts +2 -2
  123. package/dist/components/mention-input.js +4 -3
  124. package/dist/components/menu.d.ts +7 -3
  125. package/dist/components/menu.js +34 -37
  126. package/dist/components/meter.d.ts +10 -2
  127. package/dist/components/meter.js +64 -6
  128. package/dist/components/navigation.d.ts +21 -4
  129. package/dist/components/navigation.js +84 -19
  130. package/dist/components/notification-tray.d.ts +1 -1
  131. package/dist/components/notification-tray.js +5 -4
  132. package/dist/components/overlays.d.ts +6 -4
  133. package/dist/components/overlays.js +69 -40
  134. package/dist/components/page-frame.d.ts +4 -4
  135. package/dist/components/page-frame.js +1 -1
  136. package/dist/components/panel.d.ts +4 -4
  137. package/dist/components/panel.js +18 -12
  138. package/dist/components/profile-header.d.ts +1 -1
  139. package/dist/components/progress.d.ts +1 -1
  140. package/dist/components/project-avatar.d.ts +1 -1
  141. package/dist/components/radio-card.d.ts +2 -2
  142. package/dist/components/radio-card.js +10 -9
  143. package/dist/components/record.d.ts +29 -5
  144. package/dist/components/record.js +147 -18
  145. package/dist/components/resolved-file-url.d.ts +19 -0
  146. package/dist/components/resolved-file-url.js +49 -0
  147. package/dist/components/scroll-area.d.ts +1 -1
  148. package/dist/components/secret-dialog.d.ts +1 -1
  149. package/dist/components/segmented-bar.d.ts +4 -2
  150. package/dist/components/segmented-bar.js +16 -6
  151. package/dist/components/select.d.ts +9 -6
  152. package/dist/components/select.js +103 -127
  153. package/dist/components/settings.d.ts +4 -4
  154. package/dist/components/shell-skeleton.d.ts +1 -1
  155. package/dist/components/shell-skeleton.js +1 -1
  156. package/dist/components/shell.d.ts +21 -21
  157. package/dist/components/shell.js +43 -43
  158. package/dist/components/side-panel.d.ts +3 -3
  159. package/dist/components/sidebar.d.ts +13 -8
  160. package/dist/components/sidebar.js +55 -27
  161. package/dist/components/single-line-text.d.ts +2 -0
  162. package/dist/components/single-line-text.js +16 -0
  163. package/dist/components/site-banner.d.ts +5 -2
  164. package/dist/components/site-banner.js +17 -6
  165. package/dist/components/skeleton.d.ts +8 -7
  166. package/dist/components/skeleton.js +28 -16
  167. package/dist/components/skeletons.d.ts +17 -5
  168. package/dist/components/skeletons.js +71 -8
  169. package/dist/components/stages.d.ts +83 -11
  170. package/dist/components/stages.js +512 -156
  171. package/dist/components/stat-card.d.ts +12 -4
  172. package/dist/components/stat-card.js +92 -37
  173. package/dist/components/status-banner.d.ts +1 -1
  174. package/dist/components/status-banner.js +1 -1
  175. package/dist/components/status.d.ts +2 -2
  176. package/dist/components/steps.d.ts +1 -1
  177. package/dist/components/switch.d.ts +1 -1
  178. package/dist/components/tabs.d.ts +8 -8
  179. package/dist/components/tabs.js +26 -13
  180. package/dist/components/theme-customizer.d.ts +2 -2
  181. package/dist/components/theme-toggle.d.ts +4 -0
  182. package/dist/components/theme-toggle.js +67 -0
  183. package/dist/components/toast.d.ts +10 -3
  184. package/dist/components/toast.js +78 -29
  185. package/dist/components/use-new-version-available.d.ts +6 -0
  186. package/dist/components/use-new-version-available.js +29 -0
  187. package/dist/components/user-chip.d.ts +3 -3
  188. package/dist/components/wizard.d.ts +2 -2
  189. package/dist/feedback/contract.d.ts +136 -136
  190. package/dist/feedback/feedback-controller.d.ts +6 -6
  191. package/dist/feedback/generated/zod.gen.d.ts +28 -28
  192. package/dist/feedback/operator-contract.d.ts +11 -11
  193. package/dist/feedback/operator-controller.d.ts +32 -13
  194. package/dist/feedback/operator-controller.js +44 -11
  195. package/dist/preset.js +289 -33
  196. package/dist/styled-system/styles.css +3294 -1079
  197. package/dist/styled-system/tokens/index.mjs +598 -22
  198. package/dist/styled-system/tokens/tokens.d.ts +11 -11
  199. package/dist/styled-system/types/prop-type.d.ts +2 -2
  200. package/dist/styles.css +16 -4
  201. package/dist/theme/color.d.ts +3 -0
  202. package/dist/theme/color.js +5 -0
  203. package/dist/theme/derive.d.ts +9 -2
  204. package/dist/theme/derive.js +72 -12
  205. package/dist/theme/palettes.d.ts +49 -6
  206. package/dist/theme/palettes.js +84 -15
  207. package/dist/theme/tokens.d.ts +3 -3
  208. package/dist/theme/tokens.js +107 -32
  209. package/package.json +40 -3
@@ -4,8 +4,11 @@ export type CheckboxItemProps = Omit<ComponentProps<typeof BaseCheckbox.Root>, "
4
4
  children: ReactNode;
5
5
  /** Shown muted at the row's end, such as where the item comes from. */
6
6
  meta?: ReactNode;
7
- /** Shows a drag handle on hover, for a row that can be reordered. */
8
- grip?: boolean;
7
+ /**
8
+ * Shows a drag handle on hover, for a row that can be reordered; `locked` keeps the handle's
9
+ * room empty, for a row that stays put among ones that move.
10
+ */
11
+ grip?: boolean | "locked";
9
12
  className?: string;
10
13
  };
11
- export declare function CheckboxItem({ children, meta, grip: showGrip, className, ...props }: CheckboxItemProps): import("@types/react").JSX.Element;
14
+ export declare function CheckboxItem({ children, meta, grip: showGrip, className, ...props }: CheckboxItemProps): import("react").JSX.Element;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
3
- import { CheckIcon, DotsSixVerticalIcon, MinusIcon } from "@phosphor-icons/react";
3
+ import { DotsSixVerticalIcon } from "@phosphor-icons/react";
4
4
  import { css, cx } from "#primitives/css";
5
- import { checkIndicator, checkMark } from "./form-controls.js";
5
+ import { CheckGlyph, checkIndicator, checkMark, checkMarkEdge } from "./form-controls.js";
6
6
  import { icon } from "./icon.js";
7
7
  /*
8
8
  * A checkbox as a whole row: the mark, its label, and what else the row has to say, with the hover
@@ -23,8 +23,10 @@ const row = css({
23
23
  cursor: "pointer",
24
24
  transitionProperty: "background",
25
25
  transitionDuration: "fast",
26
- _hover: { background: "bg.glass" },
27
- "&:has(:focus-visible)": { focusRing: "outer" },
26
+ // The selected tint in dark and the row wash in light, as a menu row hovers; focus rings the row
27
+ // inside its own edge.
28
+ _hover: { background: "token(gradients.selected)", _light: { background: "bg.rowHover" } },
29
+ "&:has(:focus-visible)": { focusRing: "inset" },
28
30
  "&:has([data-disabled])": { opacity: "disabled", cursor: "not-allowed" },
29
31
  });
30
32
  // The grip only shows once the row is pointed at, so a list of rows is not a column of grips.
@@ -37,9 +39,11 @@ const grip = css({
37
39
  transitionProperty: "opacity",
38
40
  transitionDuration: "fast",
39
41
  "label:hover > &, label:focus-within > &": { opacity: "1" },
42
+ // A locked row keeps the grip's room, so its label lines up with the rows that move.
43
+ "&[data-locked]": { visibility: "hidden" },
40
44
  });
41
45
  const labelText = css({ flex: "1", minWidth: "0" });
42
46
  const metaText = css({ flexShrink: "0", color: "fg.subtle", fontSize: "code" });
43
47
  export function CheckboxItem({ children, meta, grip: showGrip, className, ...props }) {
44
- return (_jsxs("label", { className: cx(row, className), "data-ciridae-ui": "", children: [showGrip && (_jsx("span", { className: grip, "aria-hidden": "true", children: _jsx(DotsSixVerticalIcon, { className: icon({ size: "small" }) }) })), _jsx(BaseCheckbox.Root, { ...props, className: checkMark({ focus: "row" }), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children: props.indeterminate ? _jsx(MinusIcon, { weight: "bold" }) : _jsx(CheckIcon, { weight: "bold" }) }) }), _jsx("span", { className: labelText, children: children }), meta !== undefined && _jsx("span", { className: metaText, children: meta })] }));
48
+ return (_jsxs("label", { className: cx(row, className), "data-ciridae-ui": "", children: [showGrip && (_jsx("span", { className: grip, "aria-hidden": "true", "data-locked": showGrip === "locked" || undefined, children: _jsx(DotsSixVerticalIcon, { className: icon({ size: "small" }) }) })), _jsx(BaseCheckbox.Root, { ...props, ...checkMarkEdge, className: checkMark({ focus: "row" }), children: _jsx(BaseCheckbox.Indicator, { className: checkIndicator, children: _jsx(CheckGlyph, { mixed: props.indeterminate }) }) }), _jsx("span", { className: labelText, children: children }), meta !== undefined && _jsx("span", { className: metaText, children: meta })] }));
45
49
  }
@@ -48,4 +48,4 @@ export type CheckboxListProps = {
48
48
  * group. A long list can take a search, and bulk actions that touch only the items it leaves shown,
49
49
  * so nothing is ticked or cleared out of sight.
50
50
  */
51
- export declare function CheckboxList(props: CheckboxListProps): import("@types/react").JSX.Element;
51
+ export declare function CheckboxList(props: CheckboxListProps): import("react").JSX.Element;
@@ -1,5 +1,10 @@
1
1
  import type { Tone } from "./badge.js";
2
2
  import type { ComponentProps, ReactNode } from "react";
3
+ /** A small neutral label naming a category, such as "Prefilled". A status takes a `Badge`. */
4
+ export declare function Tag({ icon, children, className, ...props }: Omit<ComponentProps<"span">, "children"> & {
5
+ children: ReactNode;
6
+ icon?: ReactNode;
7
+ }): import("react").JSX.Element;
3
8
  export type ChipProps = Omit<ComponentProps<"span">, "children"> & {
4
9
  children: ReactNode;
5
10
  /** A mark before the label. */
@@ -14,4 +19,4 @@ export type ChipProps = Omit<ComponentProps<"span">, "children"> & {
14
19
  /** Compact recipients and inline tags; regular preserves the standalone chip. */
15
20
  size?: "regular" | "compact";
16
21
  };
17
- export declare function Chip({ children, icon, tone, onRemove, removeLabel, disabled, invalid, size, className, ...props }: ChipProps): import("@types/react").JSX.Element;
22
+ export declare function Chip({ children, icon, tone, onRemove, removeLabel, disabled, invalid, size, className, ...props }: ChipProps): import("react").JSX.Element;
@@ -1,7 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { XIcon } from "@phosphor-icons/react";
3
3
  import { css, cx } from "#primitives/css";
4
4
  import { IconButton } from "./button.js";
5
+ import { faceEdge } from "./gradient-edge.js";
5
6
  import { icon as iconStyle } from "./icon.js";
6
7
  import { useCiridaeLocale } from "./locale.js";
7
8
  const chip = css({
@@ -36,6 +37,31 @@ const chip = css({
36
37
  "&[data-tone=warning]": { background: "bg.warningSubtle", color: "accent.yellow" },
37
38
  "&[data-tone=danger], &[data-invalid]": { borderColor: "accent.red", color: "accent.red" },
38
39
  });
40
+ /* An 18px label on the raised face: 12px text over a 2px inset and the edge's 1px. */
41
+ const tag = css({
42
+ display: "inline-flex",
43
+ alignItems: "center",
44
+ gap: "layout.tightGap",
45
+ paddingBlock: "control.trackInset",
46
+ paddingInlineStart: "control.iconGap",
47
+ paddingInlineEnd: "layout.controlGap",
48
+ border: "1px solid transparent",
49
+ borderRadius: "round",
50
+ background: "token(gradients.raised)",
51
+ color: "fg.label",
52
+ fontFamily: "sans",
53
+ fontSize: "code",
54
+ fontWeight: "medium",
55
+ lineHeight: "tight",
56
+ letterSpacing: "compact",
57
+ whiteSpace: "nowrap",
58
+ "& > svg": { flexShrink: "0", fontSize: "icon.small" },
59
+ });
60
+ /** A small neutral label naming a category, such as "Prefilled". A status takes a `Badge`. */
61
+ export function Tag({ icon, children, className, ...props }) {
62
+ const edge = faceEdge("raised");
63
+ return (_jsxs("span", { ...props, className: cx(tag, edge.className, className), "data-ciridae-ui": "", "data-edge": edge["data-edge"], children: [icon, children] }));
64
+ }
39
65
  export function Chip({ children, icon, tone = "neutral", onRemove, removeLabel, disabled = false, invalid = false, size = "regular", className, ...props }) {
40
66
  const { labels } = useCiridaeLocale();
41
67
  const name = removeLabel ?? (typeof children === "string" ? children : "");
@@ -5,4 +5,4 @@ export type CollapsibleProps = Omit<ComponentProps<typeof BaseCollapsible.Root>,
5
5
  label: ReactNode;
6
6
  children: ReactNode;
7
7
  };
8
- export declare function Collapsible({ label, children, ...rootProps }: CollapsibleProps): import("@types/react").JSX.Element;
8
+ export declare function Collapsible({ label, children, ...rootProps }: CollapsibleProps): import("react").JSX.Element;
@@ -33,7 +33,7 @@ export type ThemeProviderProps = {
33
33
  * `_light` values resolve through, so every component follows without
34
34
  * threading a prop.
35
35
  */
36
- export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand, palette, fonts, }: ThemeProviderProps): import("@types/react").JSX.Element;
36
+ export declare function ThemeProvider({ children, defaultColorTheme, storageKey, brand, palette, fonts, }: ThemeProviderProps): import("react").JSX.Element;
37
37
  /** Throws outside a `ThemeProvider`, where there is no theme to report or change. */
38
38
  export declare function useColorTheme(): ColorThemeContextValue;
39
39
  /** Throws outside a `ThemeProvider` given a `brand`, where there is no name to show. */
@@ -19,4 +19,4 @@ export declare function ColumnSettings<Row extends RowData>({ columns, columnVis
19
19
  open?: boolean;
20
20
  onOpenChange?: (open: boolean) => void;
21
21
  labels?: Partial<CiridaeLabels["table"]>;
22
- }): import("@types/react").JSX.Element;
22
+ }): import("react").JSX.Element;
@@ -102,7 +102,7 @@ export function ColumnSettings({ columns, columnVisibility, onColumnVisibilityCh
102
102
  };
103
103
  const setShown = (id, visible) => onColumnVisibilityChange({ ...columnVisibility, [id]: visible });
104
104
  const dropMarker = (_jsx("span", { className: dropSlot, "aria-hidden": "true", children: _jsx("span", {}) }));
105
- return (_jsx(Popover, { open: open, onOpenChange: onOpenChange, density: "compact", trigger: trigger ?? (_jsx(Button, { variant: "secondary", size: "medium", icon: _jsx(ColumnsIcon, { className: icon({ size: "small" }) }), children: labels.columns })), children: _jsxs("div", { className: panel, children: [_jsxs("div", { className: heading, children: [labels.columns, onReset && (_jsx(Button, { variant: "ghost", onClick: onReset, children: labels.reset }))] }), _jsxs("div", { className: list, onDragEnd: finishDrag, children: [locked.map((column) => (_jsx(CheckboxItem, { checked: true, disabled: true, meta: labels.alwaysShown, children: column.label }, column.id))), shown.map((column, index) => (_jsxs("span", { className: css({ display: "contents" }), children: [dropIndex === index && dragging !== column.id && dropMarker, _jsx("span", { className: draggable, draggable: reorderable, "data-dragging": dragging === column.id || undefined, onDragStart: (event) => {
105
+ return (_jsx(Popover, { open: open, onOpenChange: onOpenChange, density: "compact", trigger: trigger ?? (_jsx(Button, { variant: "secondary", size: "medium", icon: _jsx(ColumnsIcon, { className: icon({ size: "small" }) }), children: labels.columns })), children: _jsxs("div", { className: panel, children: [_jsxs("div", { className: heading, children: [labels.columns, onReset && (_jsx(Button, { variant: "ghost", onClick: onReset, children: labels.reset }))] }), _jsxs("div", { className: list, onDragEnd: finishDrag, children: [locked.map((column) => (_jsx(CheckboxItem, { checked: true, disabled: true, grip: reorderable && "locked", meta: labels.alwaysShown, children: column.label }, column.id))), shown.map((column, index) => (_jsxs("span", { className: css({ display: "contents" }), children: [dropIndex === index && dragging !== column.id && dropMarker, _jsx("span", { className: draggable, draggable: reorderable, "data-dragging": dragging === column.id || undefined, onDragStart: (event) => {
106
106
  event.dataTransfer.effectAllowed = "move";
107
107
  setDragging(column.id);
108
108
  }, onDragOver: (event) => dragOver(event, index), onDrop: (event) => {
@@ -6,6 +6,8 @@ export type CommandMenuItem = {
6
6
  icon?: ReactNode;
7
7
  /** Muted text after the label, such as a record's title. */
8
8
  detail?: string;
9
+ /** What the row is, at its end, such as "Invoice" or "Job". */
10
+ kind?: string;
9
11
  /** The hotkey that runs it while the menu is open, such as "Mod+J", shown at the row's end. */
10
12
  shortcut?: HotkeyChord;
11
13
  /** More text the query matches, such as a job's customer. */
@@ -39,5 +41,7 @@ export type CommandMenuProps = {
39
41
  placeholder?: string;
40
42
  /** Shown when no row matches, above any `unfiltered` row; the locale's "No results" by default. */
41
43
  empty?: ReactNode;
44
+ /** What the menu searches, at the end of its footer, such as "Records, people and actions". */
45
+ searchScope?: ReactNode;
42
46
  };
43
- export declare function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, }: CommandMenuProps): import("@types/react").JSX.Element;
47
+ export declare function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, searchScope, }: CommandMenuProps): import("react").JSX.Element;
@@ -12,9 +12,9 @@ import { Command } from "cmdk";
12
12
  import { useLayoutEffect, useRef, useState, } from "react";
13
13
  import { css } from "#primitives/css";
14
14
  import { scoreCommandMatch } from "./command-match.js";
15
- import { HotkeyLayer, useHotkeys } from "./hotkeys.js";
15
+ import { formatForDisplay, HotkeyLayer, useHotkeys } from "./hotkeys.js";
16
16
  import { icon } from "./icon.js";
17
- import { ShortcutHint } from "./keycap.js";
17
+ import { Keycap, ShortcutHint } from "./keycap.js";
18
18
  import { useCiridaeLocale } from "./locale.js";
19
19
  const backdrop = css({
20
20
  position: "fixed",
@@ -26,22 +26,23 @@ const backdrop = css({
26
26
  "&[data-starting-style], &[data-ending-style]": { opacity: "0" },
27
27
  _motionReduce: { transition: "none" },
28
28
  });
29
+ // The palette is a sheet in a glass shell, as a modal is: the shell blurs the page in dark, the
30
+ // sheet blurs it in light.
29
31
  const popup = css({
30
32
  zIndex: "dialog",
31
33
  position: "fixed",
32
- top: "15dvh",
34
+ top: "18dvh",
33
35
  left: "50%",
34
36
  display: "flex",
35
- flexDirection: "column",
36
37
  width: "calc(100vw - token(spacing.layout.pageGap) * 2)",
37
- maxWidth: "overlay.dialog",
38
- overflow: "hidden",
39
- border: "1px solid token(colors.border.control)",
40
- borderRadius: "action",
41
- background: "bg.card",
38
+ maxWidth: "calc(token(sizes.overlay.palette) + token(spacing.menu.inset) * 2 + 2px)",
39
+ padding: "menu.inset",
40
+ border: "1px solid token(colors.border.divider)",
41
+ borderRadius: "shell",
42
+ background: "bg.modalShell",
43
+ backdropFilter: "blur(token(blurs.modalShell))",
42
44
  color: "fg.primary",
43
45
  textStyle: "body",
44
- boxShadow: "card",
45
46
  outline: "none",
46
47
  transform: "translateX(-50%)",
47
48
  transitionProperty: "opacity",
@@ -49,6 +50,18 @@ const popup = css({
49
50
  "&[data-starting-style], &[data-ending-style]": { opacity: "0" },
50
51
  _motionReduce: { transition: "none" },
51
52
  _phone: { top: "layout.pageGap" },
53
+ "& > [cmdk-root]": {
54
+ display: "flex",
55
+ flexDirection: "column",
56
+ flex: "1",
57
+ minWidth: "0",
58
+ overflow: "hidden",
59
+ border: "1px solid token(colors.border.divider)",
60
+ borderRadius: "inset",
61
+ background: "bg.modalSheet",
62
+ backdropFilter: "blur(token(blurs.modalSheet))",
63
+ boxShadow: "soft",
64
+ },
52
65
  });
53
66
  const visuallyHidden = css({
54
67
  position: "absolute",
@@ -65,9 +78,9 @@ const field = css({
65
78
  display: "flex",
66
79
  alignItems: "center",
67
80
  gap: "layout.controlGap",
68
- height: "control.search",
69
- paddingInline: "control.compactInline",
70
- borderBottom: "1px solid token(colors.border.control)",
81
+ height: "commandPalette.query",
82
+ flexShrink: "0",
83
+ paddingInline: "control.inline",
71
84
  color: "fg.muted",
72
85
  "& > input": {
73
86
  flex: "1",
@@ -78,35 +91,52 @@ const field = css({
78
91
  background: "transparent",
79
92
  color: "fg.primary",
80
93
  font: "inherit",
94
+ fontWeight: "medium",
95
+ letterSpacing: "compact",
81
96
  _placeholder: { color: "fg.muted" },
82
97
  },
83
98
  });
99
+ // The rules between the query, the results and the footer stop short of the sheet's edges.
100
+ const divider = css({
101
+ flexShrink: "0",
102
+ height: "border.hairline",
103
+ marginInline: "panel.compact",
104
+ background: "border.divider",
105
+ });
84
106
  const list = css({
85
107
  maxHeight: "min(60dvh, 420px)",
86
108
  overflowY: "auto",
87
109
  overscrollBehavior: "contain",
88
- "& [cmdk-group] + [cmdk-group]": { borderTop: "1px solid token(colors.border.subtle)" },
110
+ padding: "panel.compact",
111
+ "& [cmdk-group-items]": { display: "grid", gap: "control.trackInset" },
89
112
  "& [cmdk-group-heading]": {
90
113
  paddingInline: "control.compactInline",
91
114
  paddingTop: "control.block",
92
- paddingBottom: "layout.tightGap",
93
- color: "fg.muted",
115
+ paddingBottom: "control.compactBlock",
116
+ color: "fg.subtle",
94
117
  fontSize: "code",
95
118
  fontWeight: "medium",
119
+ letterSpacing: "compact",
120
+ lineHeight: "tight",
96
121
  },
97
- // The last group's rows run to the popup's foot, with the field's inset under them.
98
- "& [cmdk-group]:last-child": { paddingBottom: "layout.tightGap" },
122
+ "& [cmdk-group] + [cmdk-group]": { marginTop: "control.trackInset" },
99
123
  });
100
124
  const row = css({
101
125
  display: "flex",
102
126
  alignItems: "center",
103
- gap: "layout.controlGap",
104
- minHeight: "menu.item",
127
+ gap: "layout.contentGap",
128
+ minHeight: "commandPalette.row",
105
129
  paddingInline: "control.compactInline",
106
- fontSize: "caption",
107
- lineHeight: "body",
130
+ borderRadius: "control",
131
+ fontSize: "body",
132
+ fontWeight: "medium",
133
+ letterSpacing: "compact",
134
+ lineHeight: "tight",
108
135
  cursor: "pointer",
109
- "&[data-selected=true]": { background: "bg.rowHover" },
136
+ "&[data-selected=true]": {
137
+ background: "token(gradients.selected)",
138
+ boxShadow: "inset 0 0 0 1px token(colors.border.divider)",
139
+ },
110
140
  "& > svg": { flexShrink: "0", color: "fg.muted" },
111
141
  "& > [data-label]": {
112
142
  flexShrink: "0",
@@ -121,7 +151,14 @@ const row = css({
121
151
  overflow: "hidden",
122
152
  textOverflow: "ellipsis",
123
153
  whiteSpace: "nowrap",
124
- color: "fg.muted",
154
+ color: "fg.subtle",
155
+ fontSize: "code",
156
+ },
157
+ "& > [data-kind]": {
158
+ flexShrink: "0",
159
+ marginInlineStart: "auto",
160
+ color: "fg.subtle",
161
+ fontSize: "code",
125
162
  },
126
163
  "& > [data-shortcut]": { marginInlineStart: "auto" },
127
164
  // A link row's anchor fills the row, so its content lays out as a plain row's does. Choosing
@@ -150,7 +187,14 @@ const row = css({
150
187
  overflow: "hidden",
151
188
  textOverflow: "ellipsis",
152
189
  whiteSpace: "nowrap",
153
- color: "fg.muted",
190
+ color: "fg.subtle",
191
+ fontSize: "code",
192
+ },
193
+ "& > [data-kind]": {
194
+ flexShrink: "0",
195
+ marginInlineStart: "auto",
196
+ color: "fg.subtle",
197
+ fontSize: "code",
154
198
  },
155
199
  },
156
200
  });
@@ -160,6 +204,24 @@ const emptyRow = css({
160
204
  color: "fg.muted",
161
205
  fontSize: "caption",
162
206
  });
207
+ // How to drive the palette from the keyboard, and what it searches.
208
+ const footer = css({
209
+ display: "flex",
210
+ alignItems: "center",
211
+ justifyContent: "space-between",
212
+ gap: "layout.clusterGap",
213
+ minHeight: "commandPalette.footer",
214
+ flexShrink: "0",
215
+ paddingInline: "control.inline",
216
+ color: "fg.subtle",
217
+ fontSize: "code",
218
+ fontWeight: "medium",
219
+ letterSpacing: "compact",
220
+ _phone: { display: "none" },
221
+ });
222
+ const footerHints = css({ display: "flex", alignItems: "center", gap: "layout.clusterGap" });
223
+ const footerHint = css({ display: "flex", alignItems: "center", gap: "control.iconGap" });
224
+ const footerKeys = css({ display: "flex", alignItems: "center", gap: "layout.tightGap" });
163
225
  /**
164
226
  * The shown rows' hotkeys, in the menu's layer: it is the newest scope, so a row's hotkey wins over
165
227
  * the page's own binding for the same keys, such as Cmd+J opening the chat empty.
@@ -176,10 +238,14 @@ function CommandMenuShortcuts({ items, run, }) {
176
238
  : []));
177
239
  return null;
178
240
  }
241
+ /** The keys the palette's footer names, as its keycaps write them. */
242
+ const escapeKey = formatForDisplay("Escape");
243
+ const moveKeys = [formatForDisplay("ArrowUp"), formatForDisplay("ArrowDown")];
244
+ const openKey = formatForDisplay("Enter");
179
245
  /** Past this many rows the menu draws only those near the view. */
180
246
  const virtualizeRowsPast = 50;
181
- /** A row's height before it is measured: the menu's item height. */
182
- const menuRowHeight = 30;
247
+ /** A row's height before it is measured: the palette's row height, `sizes.commandPalette.row`. */
248
+ const menuRowHeight = 40;
183
249
  // The rows lie over a box as tall as all of them, each moved down to its place.
184
250
  const virtualLines = css({
185
251
  position: "relative",
@@ -189,7 +255,7 @@ const virtualLines = css({
189
255
  function matchesQuery(item, query) {
190
256
  return item.unfiltered === true || scoreCommandMatch(item, query) > 0;
191
257
  }
192
- export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, }) {
258
+ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups, title: ownTitle, placeholder: ownPlaceholder, empty: ownEmpty, searchScope, }) {
193
259
  const { labels } = useCiridaeLocale();
194
260
  const title = ownTitle ?? labels.commandMenu.title;
195
261
  const placeholder = ownPlaceholder ?? labels.common.search;
@@ -306,8 +372,8 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
306
372
  links.current.set(item.id, element);
307
373
  else
308
374
  links.current.delete(item.id);
309
- } })) : (_jsx(CommandMenuRowContent, { item: item })), item.shortcut && _jsx(ShortcutHint, { "data-shortcut": "", hotkey: item.shortcut })] }, item.id));
310
- return (_jsx(BaseDialog.Root, { open: open, onOpenChange: setOpen, children: _jsx(BaseDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(CommandMenuShortcuts, { items: shownGroups.flatMap((group) => group.items), run: run }), _jsx(BaseDialog.Backdrop, { className: backdrop, "data-ciridae-ui": "" }), _jsxs(BaseDialog.Popup, { className: popup, "data-ciridae-ui": "", ref: popupRef, finalFocus: restoreFocus, children: [_jsx(BaseDialog.Title, { className: visuallyHidden, children: title }), _jsxs(Command, { label: title, shouldFilter: false, loop: true, ...(virtualized ? { value: selectedId, onValueChange: setChosenId } : {}), onKeyDown: moveSelection, children: [_jsxs("div", { className: field, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(Command.Input, { autoFocus: true, placeholder: placeholder, value: query, onValueChange: onQueryChange })] }), _jsxs(Command.List, { ref: setListElement, className: list, children: [!matched && (_jsx("div", { className: emptyRow, role: "presentation", children: empty })), virtualized ? (_jsx("div", { className: virtualLines, style: { height: virtualizer.getTotalSize() }, children: virtualizer.getVirtualItems().map((virtualItem) => {
375
+ } })) : (_jsx(CommandMenuRowContent, { item: item })), item.shortcut && _jsx(ShortcutHint, { boxed: true, "data-shortcut": "", hotkey: item.shortcut })] }, item.id));
376
+ return (_jsx(BaseDialog.Root, { open: open, onOpenChange: setOpen, children: _jsx(BaseDialog.Portal, { children: _jsxs(HotkeyLayer, { children: [_jsx(CommandMenuShortcuts, { items: shownGroups.flatMap((group) => group.items), run: run }), _jsx(BaseDialog.Backdrop, { className: backdrop, "data-ciridae-ui": "" }), _jsxs(BaseDialog.Popup, { className: popup, "data-ciridae-ui": "", ref: popupRef, finalFocus: restoreFocus, children: [_jsx(BaseDialog.Title, { className: visuallyHidden, children: title }), _jsxs(Command, { label: title, shouldFilter: false, loop: true, ...(virtualized ? { value: selectedId, onValueChange: setChosenId } : {}), onKeyDown: moveSelection, children: [_jsxs("div", { className: field, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), _jsx(Command.Input, { autoFocus: true, placeholder: placeholder, value: query, onValueChange: onQueryChange }), _jsx(Keycap, { "aria-hidden": "true", children: escapeKey })] }), _jsx("div", { className: divider }), _jsxs(Command.List, { ref: setListElement, className: list, children: [!matched && (_jsx("div", { className: emptyRow, role: "presentation", children: empty })), virtualized ? (_jsx("div", { className: virtualLines, style: { height: virtualizer.getTotalSize() }, children: virtualizer.getVirtualItems().map((virtualItem) => {
311
377
  const line = lines[virtualItem.index];
312
378
  if (!line)
313
379
  return null;
@@ -317,10 +383,10 @@ export function CommandMenu({ open, onOpenChange, query, onQueryChange, groups,
317
383
  style: { transform: `translateY(${virtualItem.start}px)` },
318
384
  };
319
385
  return line.kind === "heading" ? (_jsx("div", { ref: measured.ref, "data-index": measured.index, style: measured.style, "cmdk-group-heading": "", role: "presentation", children: line.heading }, line.key)) : (drawItem(line.item, measured));
320
- }) })) : (shownGroups.map((group, groupIndex) => (_jsx(Command.Group, { heading: group.heading, children: group.items.map((item) => drawItem(item)) }, group.id ?? group.heading ?? groupIndex))))] })] })] })] }) }) }));
386
+ }) })) : (shownGroups.map((group, groupIndex) => (_jsx(Command.Group, { heading: group.heading, children: group.items.map((item) => drawItem(item)) }, group.id ?? group.heading ?? groupIndex))))] }), _jsx("div", { className: divider }), _jsxs("div", { className: footer, children: [_jsxs("div", { className: footerHints, children: [_jsxs("span", { className: footerHint, children: [_jsx("span", { className: footerKeys, children: moveKeys.map((key) => (_jsx(Keycap, { "aria-hidden": "true", children: key }, key))) }), labels.commandMenu.move] }), _jsxs("span", { className: footerHint, children: [_jsx(Keycap, { "aria-hidden": "true", children: openKey }), labels.commandMenu.open] }), _jsxs("span", { className: footerHint, children: [_jsx(Keycap, { "aria-hidden": "true", children: escapeKey }), labels.common.close] })] }), searchScope] })] })] })] }) }) }));
321
387
  }
322
388
  function CommandMenuRowContent({ item }) {
323
- return (_jsxs(_Fragment, { children: [item.icon, _jsx("span", { "data-label": "", children: item.label }), item.detail && _jsx("span", { "data-detail": "", children: item.detail })] }));
389
+ return (_jsxs(_Fragment, { children: [item.icon, _jsx("span", { "data-label": "", children: item.label }), item.detail && _jsx("span", { "data-detail": "", children: item.detail }), item.kind && _jsx("span", { "data-kind": "", children: item.kind })] }));
324
390
  }
325
391
  /** A link row's anchor; the row's own selection clicks it, so it never takes focus itself. */
326
392
  function CommandMenuLink({ item, register, }) {
@@ -18,19 +18,23 @@ export type CommandPaletteProps = {
18
18
  title?: string;
19
19
  placeholder?: string;
20
20
  empty?: ReactNode;
21
+ /** What the palette searches, at the end of its footer, such as "Records, people and actions". */
22
+ searchScope?: ReactNode;
21
23
  };
22
24
  /** Whether the palette is open; `hotkey` (Cmd/Ctrl+K by default) toggles it from anywhere. */
23
25
  export declare function useCommandPalette({ hotkey }?: {
24
26
  hotkey?: HotkeyChord;
25
27
  }): {
26
28
  open: boolean;
27
- setOpen: import("@types/react").Dispatch<import("@types/react").SetStateAction<boolean>>;
29
+ setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
28
30
  toggle: () => void;
29
31
  };
30
- export declare function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, }: CommandPaletteProps): import("@types/react").JSX.Element;
32
+ export declare function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, searchScope, }: CommandPaletteProps): import("react").JSX.Element;
31
33
  export type CommandPaletteTriggerProps = ComponentProps<"button"> & {
32
34
  /** The hotkey `useCommandPalette` opens it with, shown at the end; Cmd/Ctrl+K by default. */
33
35
  hotkey?: HotkeyChord;
36
+ /** The icon alone, round, for the rail; it is named "Search" unless given an `aria-label`. */
37
+ compact?: boolean;
34
38
  };
35
39
  /** A search field's face, as a button that opens the palette; reads "Search" unless given text. */
36
- export declare function CommandPaletteTrigger({ hotkey, className, children, ...props }: CommandPaletteTriggerProps): import("@types/react").JSX.Element;
40
+ export declare function CommandPaletteTrigger({ hotkey, compact, className, children, ...props }: CommandPaletteTriggerProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /*
3
3
  * The app's Cmd+K palette on `CommandMenu`: groups of pages, records, people and actions the app
4
4
  * supplies, matched loosely on label, detail and keywords and ranked closest first within each
@@ -25,7 +25,7 @@ export function useCommandPalette({ hotkey = "Mod+K" } = {}) {
25
25
  const toggle = useCallback(() => setOpen((current) => !current), []);
26
26
  return { open, setOpen, toggle };
27
27
  }
28
- export function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, }) {
28
+ export function CommandPalette({ open, onOpenChange, groups, onQueryChange, footerItem, title, placeholder, empty, searchScope, }) {
29
29
  const [query, setQuery] = useState("");
30
30
  const changeQuery = (next) => {
31
31
  setQuery(next);
@@ -47,31 +47,40 @@ export function CommandPalette({ open, onOpenChange, groups, onQueryChange, foot
47
47
  const footer = typed && footerItem ? footerItem(typed) : null;
48
48
  return (_jsx(CommandMenu, { open: open, onOpenChange: onOpenChange, query: query, onQueryChange: changeQuery, groups: footer
49
49
  ? [...rankedGroups, { id: "footer", items: [{ ...footer, unfiltered: true }] }]
50
- : rankedGroups, title: title, placeholder: placeholder, empty: empty }));
50
+ : rankedGroups, title: title, placeholder: placeholder, empty: empty, searchScope: searchScope }));
51
51
  }
52
+ // A form field's well on the canvas, as the sidebar draws it; in the rail, a round icon.
52
53
  const trigger = css({
53
54
  display: "flex",
54
55
  alignItems: "center",
55
56
  gap: "control.iconGap",
56
57
  width: "100%",
57
- // The sidebar row's height, so it sits in the column as one of its items.
58
- height: "control.small",
58
+ height: "control.sidebarSearch",
59
59
  paddingInlineStart: "control.compactInline",
60
- paddingInlineEnd: "control.iconGap",
61
- border: "1px solid token(colors.border.control)",
62
- borderRadius: "action",
63
- background: "bg.field",
60
+ paddingInlineEnd: "control.block",
61
+ border: "1px solid token(colors.border.canvas)",
62
+ borderRadius: "control",
63
+ background: "bg.formField",
64
64
  color: "fg.muted",
65
+ _light: { color: "fg.primary" },
65
66
  font: "inherit",
66
67
  fontWeight: "medium",
67
68
  letterSpacing: "compact",
69
+ lineHeight: "tight",
68
70
  cursor: "pointer",
69
71
  _hover: { color: "fg.primary" },
70
72
  _focusVisible: { focusRing: "outer" },
71
73
  "& > [data-shortcut]": { marginInlineStart: "auto", _phone: { display: "none" } },
74
+ "&[data-compact]": {
75
+ justifyContent: "center",
76
+ width: "control.compact",
77
+ height: "control.compact",
78
+ padding: "none",
79
+ borderRadius: "round",
80
+ },
72
81
  });
73
82
  /** A search field's face, as a button that opens the palette; reads "Search" unless given text. */
74
- export function CommandPaletteTrigger({ hotkey = "Mod+K", className, children, ...props }) {
83
+ export function CommandPaletteTrigger({ hotkey = "Mod+K", compact = false, className, children, ...props }) {
75
84
  const { labels } = useCiridaeLocale();
76
- return (_jsxs("button", { type: "button", "aria-haspopup": "dialog", ...props, className: cx(trigger, className), "data-ciridae-ui": "", children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), children ?? labels.common.search, _jsx(ShortcutHint, { "data-shortcut": "", hotkey: hotkey })] }));
85
+ return (_jsxs("button", { type: "button", "aria-haspopup": "dialog", "aria-label": compact ? labels.common.search : undefined, ...props, className: cx(trigger, className), "data-ciridae-ui": "", "data-compact": compact || undefined, children: [_jsx(MagnifyingGlassIcon, { className: icon({ size: "small" }) }), !compact && (_jsxs(_Fragment, { children: [children ?? labels.common.search, _jsx(ShortcutHint, { boxed: true, "data-shortcut": "", hotkey: hotkey })] }))] }));
77
86
  }
@@ -1,9 +1,11 @@
1
1
  import { type IconButtonProps } from "./button.js";
2
2
  /**
3
3
  * Copies `value` (or what it returns, read at the moment of copying) and reports `copied` for a
4
- * moment afterwards, for a check-mark confirmation.
4
+ * moment afterwards, for a check-mark confirmation. A copy the browser refuses, such as a denied
5
+ * permission or an insecure origin with no clipboard, goes to `onError`, or without one raises the
6
+ * kit's error toast, so a reader never pastes a stale clipboard thinking it holds the value.
5
7
  */
6
- export declare function useCopy(value: string | (() => string), onCopied?: () => void): {
8
+ export declare function useCopy(value: string | (() => string), onCopied?: () => void, onError?: (error: unknown) => void): {
7
9
  copied: boolean;
8
10
  copy: () => undefined;
9
11
  };
@@ -16,10 +18,12 @@ export type CopyButtonProps = {
16
18
  variant?: "raised" | "ghost" | "inline";
17
19
  size?: IconButtonProps["size"];
18
20
  onCopied?: () => void;
21
+ /** A refused copy; the kit's error toast without it. */
22
+ onError?: (error: unknown) => void;
19
23
  className?: string;
20
24
  };
21
25
  /** A button that copies `value`, its icon turning into a check once copied. */
22
- export declare function CopyButton({ value, label, variant, size, onCopied, className, }: CopyButtonProps): import("@types/react").JSX.Element;
26
+ export declare function CopyButton({ value, label, variant, size, onCopied, onError, className, }: CopyButtonProps): import("react").JSX.Element;
23
27
  /**
24
28
  * A long identifier, such as an error's trace ID, shown short and copied whole on click so a
25
29
  * reader can hand it to support.
@@ -28,10 +32,23 @@ export declare function CopyableId({ value, label, className, }: {
28
32
  value: string;
29
33
  label?: string;
30
34
  className?: string;
31
- }): import("@types/react").JSX.Element;
35
+ }): import("react").JSX.Element;
32
36
  /** Text shown in full with a copy control; `label` names what gets copied, such as a key's name. */
33
37
  export declare function CopyableText({ text, label, className, }: {
34
38
  text: string;
35
39
  label: string;
36
40
  className?: string;
37
- }): import("@types/react").JSX.Element;
41
+ }): import("react").JSX.Element;
42
+ /**
43
+ * A value to paste elsewhere, such as a command or a connection code, as a labelled read-only
44
+ * field with a copy button: it selects on focus and reads like the field it is pasted into. The
45
+ * row stays while there is no value yet, showing `placeholder`. The value is masked from session
46
+ * recorders, since such values are often credentials.
47
+ */
48
+ export declare function CopyField({ label, value, placeholder, className, }: {
49
+ label: string;
50
+ value: string | undefined;
51
+ /** What an absent value means, such as that it is not generated yet. */
52
+ placeholder?: string;
53
+ className?: string;
54
+ }): import("react").JSX.Element;