@crisp-ui-kit/crisp 0.49.0 → 0.51.0
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.
- package/dist/cjs/components/composewindow/composewindow.js +144 -0
- package/dist/cjs/components/composewindow/composewindow.recipe.js +45 -0
- package/dist/cjs/components/composewindow/index.js +8 -0
- package/dist/cjs/components/datatable/datatable.js +224 -43
- package/dist/cjs/components/datatable/datatable.recipe.js +38 -4
- package/dist/cjs/components/datatable/index.js +6 -0
- package/dist/cjs/components/datepickerfield/datepickerfield.js +25 -15
- package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +25 -8
- package/dist/cjs/components/dialog/dialog.recipe.js +9 -1
- package/dist/cjs/components/menu/menu.js +4 -2
- package/dist/cjs/components/multiselect/multiselect.recipe.js +14 -8
- package/dist/cjs/components/select/select.js +2 -1
- package/dist/cjs/components/table/table.recipe.js +12 -3
- package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +2 -1
- package/dist/cjs/components/tabletoolbar/tabletoolbar.js +39 -8
- package/dist/cjs/core/cell-date.js +11 -0
- package/dist/cjs/core/index.js +2 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/product/recordpage/recordpage.js +88 -10
- package/dist/cjs/product/recordpage/recordpage.recipe.js +30 -0
- package/dist/cjs/product/recordpanel/recordpanel.js +54 -4
- package/dist/cjs/product/recordpanel/recordpanel.recipe.js +29 -0
- package/dist/cjs/product/recordstable/editable-field.js +110 -0
- package/dist/cjs/product/recordstable/index.js +4 -1
- package/dist/cjs/product/recordstable/recordstable.js +67 -11
- package/dist/cjs/product/recordstable/recordstable.recipe.js +9 -1
- package/dist/cjs/product/settingsshell/settingsshell.recipe.js +13 -4
- package/dist/cjs/product/sidebar/sidebar.js +15 -3
- package/dist/cjs/product/sidebar/sidebar.recipe.js +21 -2
- package/dist/composewindow.css +24 -0
- package/dist/composewindow.d.ts +7 -0
- package/dist/composewindow.layered.css +26 -0
- package/dist/datatable.css +34 -15
- package/dist/datatable.layered.css +34 -15
- package/dist/datepickerfield.css +9 -4
- package/dist/datepickerfield.layered.css +9 -4
- package/dist/dialog.css +2 -1
- package/dist/dialog.layered.css +2 -1
- package/dist/esm/components/composewindow/composewindow.js +107 -0
- package/dist/esm/components/composewindow/composewindow.recipe.js +42 -0
- package/dist/esm/components/composewindow/index.js +2 -0
- package/dist/esm/components/datatable/datatable.js +226 -45
- package/dist/esm/components/datatable/datatable.recipe.js +38 -4
- package/dist/esm/components/datatable/index.js +6 -0
- package/dist/esm/components/datepickerfield/datepickerfield.js +26 -16
- package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +25 -8
- package/dist/esm/components/dialog/dialog.recipe.js +9 -1
- package/dist/esm/components/menu/menu.js +4 -2
- package/dist/esm/components/multiselect/multiselect.recipe.js +14 -8
- package/dist/esm/components/select/select.js +2 -1
- package/dist/esm/components/table/table.recipe.js +12 -3
- package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +2 -1
- package/dist/esm/components/tabletoolbar/tabletoolbar.js +38 -8
- package/dist/esm/core/cell-date.js +10 -0
- package/dist/esm/core/index.js +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/product/recordpage/recordpage.js +89 -11
- package/dist/esm/product/recordpage/recordpage.recipe.js +30 -0
- package/dist/esm/product/recordpanel/recordpanel.js +55 -5
- package/dist/esm/product/recordpanel/recordpanel.recipe.js +29 -0
- package/dist/esm/product/recordstable/editable-field.js +73 -0
- package/dist/esm/product/recordstable/index.js +1 -0
- package/dist/esm/product/recordstable/recordstable.js +69 -13
- package/dist/esm/product/recordstable/recordstable.recipe.js +9 -1
- package/dist/esm/product/settingsshell/settingsshell.recipe.js +13 -4
- package/dist/esm/product/sidebar/sidebar.js +15 -3
- package/dist/esm/product/sidebar/sidebar.recipe.js +21 -2
- package/dist/multiselect.css +8 -8
- package/dist/multiselect.layered.css +8 -8
- package/dist/recordpage.css +25 -13
- package/dist/recordpage.layered.css +25 -13
- package/dist/recordpanel.css +22 -5
- package/dist/recordpanel.layered.css +22 -5
- package/dist/recordstable.css +10 -2
- package/dist/recordstable.layered.css +10 -2
- package/dist/settingsshell.css +2 -2
- package/dist/settingsshell.layered.css +2 -2
- package/dist/sidebar.css +7 -2
- package/dist/sidebar.layered.css +7 -2
- package/dist/styles.css +150 -55
- package/dist/styles.layered.css +150 -55
- package/dist/table.css +4 -2
- package/dist/table.layered.css +4 -2
- package/dist/tabletoolbar.css +2 -1
- package/dist/tabletoolbar.layered.css +2 -1
- package/dist/types/components/composewindow/composewindow.d.ts +80 -0
- package/dist/types/components/composewindow/composewindow.recipe.d.ts +3 -0
- package/dist/types/components/composewindow/index.d.ts +2 -0
- package/dist/types/components/datatable/datatable.d.ts +58 -4
- package/dist/types/components/datatable/index.d.ts +1 -1
- package/dist/types/components/datepickerfield/datepickerfield.d.ts +18 -4
- package/dist/types/components/menu/menu.d.ts +10 -1
- package/dist/types/components/select/select.d.ts +6 -1
- package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +62 -5
- package/dist/types/core/cell-date.d.ts +17 -0
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/product/recordpage/recordpage.d.ts +59 -1
- package/dist/types/product/recordpanel/recordpanel.d.ts +11 -1
- package/dist/types/product/recordstable/editable-field.d.ts +45 -0
- package/dist/types/product/recordstable/index.d.ts +1 -0
- package/dist/types/product/recordstable/recordstable.d.ts +29 -0
- package/dist/types/product/sidebar/sidebar.d.ts +60 -4
- package/package.json +6 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type ComposeWindowProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
|
|
3
|
+
/** Controlled open state — `ComposeWindow` never manages this itself, the
|
|
4
|
+
* same controlled-only shape as `Dialog`/`Drawer`/`Command`. This is
|
|
5
|
+
* deliberate: crisp has no router dependency, so making the window fully
|
|
6
|
+
* controlled (this, and `minimized`/`pinned` below) is what lets a
|
|
7
|
+
* consumer sync it to a URL itself — the way Attio's own note window is
|
|
8
|
+
* addressable via `?id=…&modal=note` — without crisp owning any routing. */
|
|
9
|
+
open: boolean;
|
|
10
|
+
onOpenChange: (open: boolean) => void;
|
|
11
|
+
/** The header's leading area — typically a link to whatever record this
|
|
12
|
+
* window is attached to. Rendered as-is; crisp does not style its
|
|
13
|
+
* contents beyond spacing, since the exact breadcrumb chip inside it
|
|
14
|
+
* wasn't independently re-measured (see the component's own doc comment). */
|
|
15
|
+
breadcrumb?: React.ReactNode;
|
|
16
|
+
/** Minimized state. Omit for uncontrolled (see `defaultMinimized`). */
|
|
17
|
+
minimized?: boolean;
|
|
18
|
+
defaultMinimized?: boolean;
|
|
19
|
+
onMinimizedChange?: (minimized: boolean) => void;
|
|
20
|
+
/** Pinned state. While pinned, clicking outside the window does not close
|
|
21
|
+
* it. Omit for uncontrolled (see `defaultPinned`). */
|
|
22
|
+
pinned?: boolean;
|
|
23
|
+
defaultPinned?: boolean;
|
|
24
|
+
onPinnedChange?: (pinned: boolean) => void;
|
|
25
|
+
/** Content width in px (clamped to 90vw), matching `Dialog`'s own knob.
|
|
26
|
+
* Default 968 — Attio's own measured note window width. */
|
|
27
|
+
width?: number;
|
|
28
|
+
"aria-label"?: string;
|
|
29
|
+
minimizeLabel?: string;
|
|
30
|
+
pinLabel?: string;
|
|
31
|
+
closeLabel?: string;
|
|
32
|
+
children?: React.ReactNode;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* A floating, minimizable, pinnable window — Attio's own note "compose
|
|
36
|
+
* window" chrome (measured live, read-only, 2026-09-24; see HANDOFF), not a
|
|
37
|
+
* new visual recipe: it reuses `Dialog`'s exact measured frosted-glass panel
|
|
38
|
+
* (`bgOverlayFrost` 60% + `blur(15px)`, `elevation.modal`'s 3-layer shadow,
|
|
39
|
+
* 16px outer radius) — those numbers matched Attio's compose window exactly
|
|
40
|
+
* when re-checked against it, panel-for-panel. What's actually different
|
|
41
|
+
* from `Dialog` is the header (a breadcrumb plus minimize/pin/close, not a
|
|
42
|
+
* title plus close) and two extra pieces of state Dialog has no concept of.
|
|
43
|
+
*
|
|
44
|
+
* `minimized` is measured, not guessed — the FIRST version of this file built
|
|
45
|
+
* an invented "minimized bar" (a Gmail-style dock, since a bar was never
|
|
46
|
+
* actually exercised against Attio). Re-measured properly: minimizing an
|
|
47
|
+
* existing note does not produce any bar, tray, dock, or badge anywhere on
|
|
48
|
+
* screen. Confirmed four independent ways, both with synthetic and real
|
|
49
|
+
* CDP-dispatched trusted clicks — the element count under the note's own
|
|
50
|
+
* subtree drops by ~110 nodes, `[role="dialog"]` stops matching it, its
|
|
51
|
+
* `data-hidden="true"` ancestor computes `visibility: hidden; opacity: 0`,
|
|
52
|
+
* and the URL drops the `?id=…&modal=note` query exactly like Close does —
|
|
53
|
+
* but the subtree is NOT removed: `document.querySelectorAll('[aria-label=
|
|
54
|
+
* "Minimize"]')` still finds it afterward, `visibility: hidden` (not
|
|
55
|
+
* `display: none`) preserves layout, and nothing in localStorage or the DOM
|
|
56
|
+
* suggests state was discarded. So: minimized hides the panel — mounted,
|
|
57
|
+
* `visibility: hidden; opacity: 0` — rather than unmounting or closing it,
|
|
58
|
+
* and crisp renders no restore affordance of its own (Attio has none
|
|
59
|
+
* either); reopening is the consumer's own UI, driven by `minimized`/
|
|
60
|
+
* `onMinimizedChange` the same way `open` already works.
|
|
61
|
+
*
|
|
62
|
+
* "Pinned" is implemented as the one directly-supported behavior that
|
|
63
|
+
* matches its name (Zag's `closeOnInteractOutside`, off while pinned) —
|
|
64
|
+
* Attio's own multi-instance stacking/docking when pinned was not exercised,
|
|
65
|
+
* so nothing here repositions the window when pinned.
|
|
66
|
+
*
|
|
67
|
+
* Not modal: Attio's own compose window dims nothing behind it (`Dialog`'s
|
|
68
|
+
* backdrop is `background: transparent` too — the blur alone does the
|
|
69
|
+
* separation), and the page behind stays visibly interactive in the
|
|
70
|
+
* measured screenshot. `trapFocus` follows the same call — a picture-in-
|
|
71
|
+
* picture window, not a modal, so Tab is not caught inside it.
|
|
72
|
+
*/
|
|
73
|
+
export declare function ComposeWindow({ open, onOpenChange, breadcrumb, minimized: minimizedProp, defaultMinimized, onMinimizedChange, pinned: pinnedProp, defaultPinned, onPinnedChange, width, "aria-label": ariaLabel, minimizeLabel, pinLabel, closeLabel, children, className, style, "aria-describedby": describedBy, ...rest }: ComposeWindowProps): React.JSX.Element | null;
|
|
74
|
+
export declare namespace ComposeWindow {
|
|
75
|
+
var displayName: string;
|
|
76
|
+
}
|
|
77
|
+
export declare function ComposeWindowBody({ children, className, }: {
|
|
78
|
+
children?: React.ReactNode;
|
|
79
|
+
className?: string;
|
|
80
|
+
}): React.JSX.Element;
|
|
@@ -7,7 +7,18 @@ export type EntityValue = {
|
|
|
7
7
|
name: string;
|
|
8
8
|
avatar?: string;
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
/** An `editor: "select"` column's choices. Same shape as RecordsTable's
|
|
11
|
+
* `StatusOption`. */
|
|
12
|
+
export type DataEditableOption = {
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
color?: string;
|
|
16
|
+
/** `editor: "reference"` only (#449) — a photo URL for the option's
|
|
17
|
+
* leading avatar; a generic icon renders when omitted. Unused by
|
|
18
|
+
* `editor: "select"`. */
|
|
19
|
+
avatar?: string;
|
|
20
|
+
};
|
|
21
|
+
export type DataCellType = "text" | "entity" | "tags" | "status" | "date" | "datetime" | "number" | "currency";
|
|
11
22
|
export type DataTableColumn<T> = {
|
|
12
23
|
key: string;
|
|
13
24
|
/** Truncates with an ellipsis when it's wider than the
|
|
@@ -29,8 +40,44 @@ export type DataTableColumn<T> = {
|
|
|
29
40
|
sortable?: boolean;
|
|
30
41
|
/** Exclude this column from the search filter (default: included). */
|
|
31
42
|
filterable?: boolean;
|
|
32
|
-
/** Allow inline editing
|
|
43
|
+
/** Allow inline editing. A plain `editable` column opens a text/number/
|
|
44
|
+
* date/datetime field on double-click (Enter/blur/choosing a value
|
|
45
|
+
* commits) — see `editor` for `select`/`switch`/`reference`. */
|
|
33
46
|
editable?: boolean;
|
|
47
|
+
/** The inline editor an `editable` column opens. Omitted: a plain field
|
|
48
|
+
* inferred from `type` (number/date/datetime/text), gated behind the
|
|
49
|
+
* double-click `editable` opens today. `"select"`/`"switch"`/`"reference"`
|
|
50
|
+
* instead render crisp's own `Select`/`Switch` as the cell's live content,
|
|
51
|
+
* ALWAYS interactive — no double-click gate, no separate edit/view mode —
|
|
52
|
+
* the same convention RecordsTable's `status`/`reference` pickers already
|
|
53
|
+
* use, since choosing an option or flipping a toggle IS the commit
|
|
54
|
+
* gesture; there is nothing for a second click to open. `select` reads
|
|
55
|
+
* `options`; `reference` reads `refOptions` and is search-enabled, the
|
|
56
|
+
* same searchable-`Select` shape as `RecordsTable`'s own
|
|
57
|
+
* `ReferenceCell`. */
|
|
58
|
+
editor?: "select" | "switch" | "reference";
|
|
59
|
+
/** Options for `editor: "select"` (value/label, an optional `color` a
|
|
60
|
+
* caller's own `render` can read) — same shape as RecordsTable's
|
|
61
|
+
* `Column.options` for its `status` picker. */
|
|
62
|
+
options?: DataEditableOption[];
|
|
63
|
+
/** Options for `editor: "reference"` — same shape as `options`, plus
|
|
64
|
+
* `avatar` (#449): a 16px avatar renders before each option's label, a
|
|
65
|
+
* photo when given, a generic fallback icon otherwise — matching
|
|
66
|
+
* RecordsTable's own `ReferenceCell`, which this picker mirrors. */
|
|
67
|
+
refOptions?: DataEditableOption[];
|
|
68
|
+
/** Placeholder for `editor: "reference"`'s search input. Defaults to
|
|
69
|
+
* `Select`'s own generic "Search…" — a generic primitive doesn't hardcode
|
|
70
|
+
* Attio's own copy ("Search records..."), which is workspace/object
|
|
71
|
+
* text, not a crisp-measured value. */
|
|
72
|
+
refSearchPlaceholder?: string;
|
|
73
|
+
/** Adds a trailing "Create {createLabel}" row to `editor: "reference"`'s
|
|
74
|
+
* picker (Attio's own always has one, #449) — rendered only when this is
|
|
75
|
+
* provided. Picking it hands back the picker's current search text, e.g.
|
|
76
|
+
* to open a create flow pre-seeded with it. */
|
|
77
|
+
onCreateReference?: (query: string) => void;
|
|
78
|
+
/** The object noun in "Create {createLabel}" (Attio: "Create Person").
|
|
79
|
+
* Only used with `onCreateReference`; defaults to "record". */
|
|
80
|
+
createLabel?: string;
|
|
34
81
|
align?: "left" | "right" | "center";
|
|
35
82
|
width?: number;
|
|
36
83
|
/** Custom cell renderer. */
|
|
@@ -125,8 +172,15 @@ export type DataTableProps<T extends {
|
|
|
125
172
|
* of `searchPlaceholder`, which is visible text — this is the
|
|
126
173
|
* screen-reader-only label. */
|
|
127
174
|
searchLabel?: string;
|
|
128
|
-
/** Commit handler for inline edits.
|
|
129
|
-
|
|
175
|
+
/** Commit handler for inline edits. Returning (or resolving) nothing
|
|
176
|
+
* commits synchronously, same as before -- `Promise<void>` is additive.
|
|
177
|
+
* Returning a `Promise` that rejects shows a pending state on the cell
|
|
178
|
+
* while it's in flight, then reverts the cell to its last-known-good value
|
|
179
|
+
* (the cell only ever shows `data`, which this never mutates itself) and
|
|
180
|
+
* renders the rejection's message in an error slot beside the cell,
|
|
181
|
+
* outside `render`'s own output so a hover-only wrapper (a `Tooltip`, say)
|
|
182
|
+
* can't swallow it. */
|
|
183
|
+
onEdit?: (id: string, key: string, value: string) => Promise<void> | void;
|
|
130
184
|
/** Sticky the first column(s) with a horizontal scroll shadow (default true). */
|
|
131
185
|
stickyFirst?: boolean;
|
|
132
186
|
/** Sticky the LAST column with a horizontal scroll shadow, mirroring
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { DataTable, type DataTableColumn, type DataTableProps, type SortState, } from "./datatable";
|
|
1
|
+
export { type DataCellType, type DataEditableOption, DataTable, type DataTableColumn, type DataTableProps, type SortState, } from "./datatable";
|
|
2
2
|
export { datatableRecipe } from "./datatable.recipe";
|
|
@@ -11,20 +11,34 @@ export type DatePickerFieldProps = Omit<React.ComponentPropsWithoutRef<"div">, "
|
|
|
11
11
|
/** Controlled value. Omit to let the field manage it (see defaultValue). */
|
|
12
12
|
value?: Date | null;
|
|
13
13
|
defaultValue?: Date | null;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Fires with the picked date, controlled or not — or `null`, when the
|
|
16
|
+
* field's own Clear button is pressed (#394). A field whose value is
|
|
17
|
+
* meaningfully optional (a range's From/To, e.g. — blank legitimately
|
|
18
|
+
* means "unconstrained") needs a way back to that blank state without
|
|
19
|
+
* leaving the field; there was none before this.
|
|
20
|
+
*/
|
|
21
|
+
onValueChange?: (date: Date | null) => void;
|
|
16
22
|
/**
|
|
17
23
|
* The original name for `onValueChange`, kept working so no consumer breaks.
|
|
18
24
|
* Prefer `onValueChange`: it is what every other crisp component calls this,
|
|
19
25
|
* and passing the house name to a component that only knew `onChange` was
|
|
20
26
|
* not a type error — the handler simply never fired (#202).
|
|
21
27
|
*/
|
|
22
|
-
onChange?: (date: Date) => void;
|
|
28
|
+
onChange?: (date: Date | null) => void;
|
|
23
29
|
placeholder?: string;
|
|
24
30
|
/** `default` = outlined trigger; `ghost` = transparent (for table cells). */
|
|
25
31
|
variant?: "default" | "ghost";
|
|
26
32
|
/** Formats the trigger label (default: e.g. "Jun 3, 2026"). */
|
|
27
33
|
format?: (date: Date) => string;
|
|
34
|
+
/**
|
|
35
|
+
* Shows a Clear (×) button next to the trigger once a value is set
|
|
36
|
+
* (default `true`). Set `false` for a field whose value is never
|
|
37
|
+
* meaningfully optional.
|
|
38
|
+
*/
|
|
39
|
+
clearable?: boolean;
|
|
40
|
+
/** aria-label on the Clear button (default "Clear date"). */
|
|
41
|
+
clearLabel?: string;
|
|
28
42
|
/** Quick-pick chips under the calendar. */
|
|
29
43
|
presets?: DatePreset[];
|
|
30
44
|
/** Forwarded to the calendar — constraints, locale, ariaLabels and the rest. */
|
|
@@ -37,7 +51,7 @@ export type DatePickerFieldProps = Omit<React.ComponentPropsWithoutRef<"div">, "
|
|
|
37
51
|
* popover. This is what `DatePicker` used to be; `DatePicker` is now
|
|
38
52
|
* seed-design's bare calendar, and this composes it.
|
|
39
53
|
*/
|
|
40
|
-
export declare function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder, variant, format, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }: DatePickerFieldProps): React.JSX.Element;
|
|
54
|
+
export declare function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder, variant, format, clearable, clearLabel, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }: DatePickerFieldProps): React.JSX.Element;
|
|
41
55
|
export declare namespace DatePickerField {
|
|
42
56
|
var displayName: string;
|
|
43
57
|
}
|
|
@@ -13,6 +13,15 @@ export type MenuProps = {
|
|
|
13
13
|
/** Fires with the next open state, controlled or not. */
|
|
14
14
|
onOpenChange?: (open: boolean) => void;
|
|
15
15
|
className?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Extra class(es) for the popover surface itself (`.crisp-menu-content`).
|
|
18
|
+
* `className` alone can't reach it: the surface is portaled to
|
|
19
|
+
* `document.body` (#339) so it's no longer a DOM descendant of the root
|
|
20
|
+
* `className` lands on, and a descendant selector scoped to the root
|
|
21
|
+
* silently matches nothing there — found wiring the workspace switcher's
|
|
22
|
+
* wider, Attio-measured popover (#415).
|
|
23
|
+
*/
|
|
24
|
+
contentClassName?: string;
|
|
16
25
|
"aria-label"?: string;
|
|
17
26
|
};
|
|
18
27
|
/**
|
|
@@ -22,7 +31,7 @@ export type MenuProps = {
|
|
|
22
31
|
* typeahead, Enter/Space select, Esc closes and returns focus to the trigger);
|
|
23
32
|
* closes on outside click. Flips up / right-aligns when space is tight.
|
|
24
33
|
*/
|
|
25
|
-
export declare function Menu({ trigger, children, align, open: openProp, defaultOpen, onOpenChange, className, "aria-label": ariaLabel, }: MenuProps): React.JSX.Element;
|
|
34
|
+
export declare function Menu({ trigger, children, align, open: openProp, defaultOpen, onOpenChange, className, contentClassName, "aria-label": ariaLabel, }: MenuProps): React.JSX.Element;
|
|
26
35
|
export declare namespace Menu {
|
|
27
36
|
var displayName: string;
|
|
28
37
|
}
|
|
@@ -47,6 +47,11 @@ export type SelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" |
|
|
|
47
47
|
/** Show a search field at the top of the list that filters options (Linear/cmdk style). */
|
|
48
48
|
searchable?: boolean;
|
|
49
49
|
searchPlaceholder?: string;
|
|
50
|
+
/** Fires on every keystroke in the search field. `Select` filters `options`
|
|
51
|
+
* itself, so this exists for a consumer who needs the raw text too — a
|
|
52
|
+
* trailing "create" row seeded with it, a server-side search, and so on.
|
|
53
|
+
* Only meaningful with `searchable`. */
|
|
54
|
+
onSearchChange?: (query: string) => void;
|
|
50
55
|
/** Shown when the search matches nothing. */
|
|
51
56
|
emptyLabel?: string;
|
|
52
57
|
disabled?: boolean;
|
|
@@ -64,7 +69,7 @@ export type SelectProps = Omit<React.ComponentPropsWithoutRef<"div">, "value" |
|
|
|
64
69
|
* "No results" empty state). Full keyboard model — ↑/↓ move, Enter/Space pick,
|
|
65
70
|
* Esc close, Home/End jump, opens upward when tight. Controlled or uncontrolled.
|
|
66
71
|
*/
|
|
67
|
-
export declare function Select({ options, value, defaultValue, onValueChange, name, required, placeholder, variant, width, searchable, searchPlaceholder, emptyLabel, disabled, invalid, className, "aria-label": ariaLabel, id, ...rest }: SelectProps): React.JSX.Element;
|
|
72
|
+
export declare function Select({ options, value, defaultValue, onValueChange, name, required, placeholder, variant, width, searchable, searchPlaceholder, onSearchChange, emptyLabel, disabled, invalid, className, "aria-label": ariaLabel, id, ...rest }: SelectProps): React.JSX.Element;
|
|
68
73
|
export declare namespace Select {
|
|
69
74
|
var displayName: string;
|
|
70
75
|
}
|
|
@@ -31,8 +31,25 @@ export type TableToolbarColumn = {
|
|
|
31
31
|
values?: string[];
|
|
32
32
|
};
|
|
33
33
|
export type TableToolbarProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
|
|
34
|
-
/**
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The fields Sort and Filter both offer, when neither overrides it below.
|
|
36
|
+
* Optional only when `sortColumns` AND `filterColumns` are both supplied —
|
|
37
|
+
* TableToolbar has nothing left to fall back to otherwise, and a side left
|
|
38
|
+
* with neither offers no fields at all (its trigger still renders; its
|
|
39
|
+
* popover is just empty).
|
|
40
|
+
*/
|
|
41
|
+
columns?: TableToolbarColumn[];
|
|
42
|
+
/**
|
|
43
|
+
* The fields Sort offers, when they differ from Filter's — Attio's own
|
|
44
|
+
* Tasks page is the reference (measured live, `app.attio.com/<ws>/tasks`):
|
|
45
|
+
* Sort offers Due date/Assignee/Creation date, Filter offers Assignee/
|
|
46
|
+
* Record/Created by, and neither is the other's full set. Defaults to
|
|
47
|
+
* `columns`.
|
|
48
|
+
*/
|
|
49
|
+
sortColumns?: TableToolbarColumn[];
|
|
50
|
+
/** The fields Filter offers, when they differ from Sort's. Defaults to
|
|
51
|
+
* `columns`. */
|
|
52
|
+
filterColumns?: TableToolbarColumn[];
|
|
36
53
|
/** Controlled sorts. Omit to let the toolbar manage them internally. */
|
|
37
54
|
sorts?: ToolbarSort[];
|
|
38
55
|
defaultSorts?: ToolbarSort[];
|
|
@@ -75,12 +92,22 @@ export type TableToolbarProps = Omit<React.ComponentPropsWithoutRef<"div">, "chi
|
|
|
75
92
|
ascendingLabel?: string;
|
|
76
93
|
/** Label on the "descending" sort-direction option (default "Descending"). */
|
|
77
94
|
descendingLabel?: string;
|
|
78
|
-
/** Text on the sort trigger. Receives the active sorts and the
|
|
79
|
-
*
|
|
95
|
+
/** Text on the sort trigger. Receives the active sorts and the *sort*
|
|
96
|
+
* fields (`sortColumns`, or `columns` when that's not set), so the
|
|
97
|
+
* sorted-by phrase can be built in the caller's own word order —
|
|
80
98
|
* "Sorted by Name +2" does not survive a template with holes. */
|
|
81
99
|
sortTriggerLabel?: (sorts: ToolbarSort[], columns: TableToolbarColumn[]) => React.ReactNode;
|
|
82
100
|
/** Text on the filter trigger. Receives the number of active filters. */
|
|
83
101
|
filterTriggerLabel?: (activeFilters: number) => React.ReactNode;
|
|
102
|
+
/**
|
|
103
|
+
* Set when nesting `TableToolbar` inside a consumer's own toolbar row
|
|
104
|
+
* (`DataTable`'s `toolbar` slot, e.g.) alongside other same-height
|
|
105
|
+
* controls. Drops the row's own bottom padding, which exists for when
|
|
106
|
+
* `TableToolbar` sits directly above a table with nothing else in its
|
|
107
|
+
* row — that gap isn't the row's to add when something else in the same
|
|
108
|
+
* row already centres on the same 28px line (#398).
|
|
109
|
+
*/
|
|
110
|
+
inline?: boolean;
|
|
84
111
|
className?: string;
|
|
85
112
|
};
|
|
86
113
|
/**
|
|
@@ -101,6 +128,36 @@ export declare function applySorts<T>(rows: T[], sorts: ToolbarSort[], get?: (ro
|
|
|
101
128
|
* `RecordsTable` renders this same measured chrome internally; this is the
|
|
102
129
|
* composable version, to put above `DataTable` or any table of your own. Pair
|
|
103
130
|
* it with `applyFilters` / `applySorts` to turn its state into rows.
|
|
131
|
+
*
|
|
132
|
+
* Sort and Filter read the same `columns` list by default, but can be given
|
|
133
|
+
* their own (`sortColumns`/`filterColumns`) when a consumer's two menus
|
|
134
|
+
* genuinely offer different fields — Attio's own Tasks page does exactly
|
|
135
|
+
* this (Sort: Due date/Assignee/Creation date; Filter: Assignee/Record/
|
|
136
|
+
* Created by), which one shared list can't reproduce.
|
|
137
|
+
*/
|
|
138
|
+
export declare function TableToolbar({ columns, sortColumns: sortColumnsProp, filterColumns: filterColumnsProp, sorts: sortsProp, defaultSorts, onSortsChange, filters: filtersProp, defaultFilters, onFiltersChange, count, children, helpHref, className, sortLabel, reorderSortLabel, noSortsLabel, addSortLabel, learnSortingLabel, selectConditionLabel, sortFieldLabel, sortDirectionLabel, removeSortLabel, filterFieldLabel, filterFieldPlaceholder, filterValuePlaceholder, ascendingLabel, descendingLabel, sortTriggerLabel, filterTriggerLabel, inline, ...rest }: TableToolbarProps): React.JSX.Element;
|
|
139
|
+
export type ToolbarToolProps = React.ComponentPropsWithoutRef<"button"> & {
|
|
140
|
+
/** Drawn the way Sort/Filter are once a condition is set (#399). */
|
|
141
|
+
active?: boolean;
|
|
142
|
+
/** The quieter, no-ring variant Sort/Filter never use themselves, for a
|
|
143
|
+
* chip whose "on" state should read as less committed than a real filter. */
|
|
144
|
+
ghost?: boolean;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* The Sort/Filter chip's own chrome (`.crisp-tabletoolbar-tool`), standalone
|
|
148
|
+
* (#399) — for a control drawn like Sort/Filter that isn't Sort or Filter (a
|
|
149
|
+
* screen's own quick filter, e.g.). `.crisp-tabletoolbar-tool` alone renders
|
|
150
|
+
* unstyled: the rule lives nested under `TableToolbar`'s own root class, the
|
|
151
|
+
* same way every other rule in its shared chrome does, so it only paints on
|
|
152
|
+
* a descendant of an actual `TableToolbar`. This wraps one in, `display:
|
|
153
|
+
* contents` so it contributes no box of its own — the same technique
|
|
154
|
+
* `TableToolbar`'s own root already uses to disappear from layout.
|
|
104
155
|
*/
|
|
105
|
-
export declare
|
|
156
|
+
export declare const ToolbarTool: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
|
157
|
+
/** Drawn the way Sort/Filter are once a condition is set (#399). */
|
|
158
|
+
active?: boolean;
|
|
159
|
+
/** The quieter, no-ring variant Sort/Filter never use themselves, for a
|
|
160
|
+
* chip whose "on" state should read as less committed than a real filter. */
|
|
161
|
+
ghost?: boolean;
|
|
162
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
106
163
|
export {};
|
|
@@ -15,3 +15,20 @@
|
|
|
15
15
|
export declare function parseCellDate(raw: string | undefined): Date | null;
|
|
16
16
|
/** The inverse: the picked date's own calendar day, not the UTC one. */
|
|
17
17
|
export declare function formatCellDate(d: Date): string;
|
|
18
|
+
/**
|
|
19
|
+
* How much of a date-only value a raw cell string actually carried.
|
|
20
|
+
*
|
|
21
|
+
* `parseCellDate` fills a missing month/day with January/the 1st so a
|
|
22
|
+
* year-only or year-month value can become a `Date` — right for parsing,
|
|
23
|
+
* which must produce an instant, but wrong for display: a *display*
|
|
24
|
+
* formatter that always prints `month day, year` renders a value that named
|
|
25
|
+
* one field as though it named three (#312 — `"1998"` rendered "Jan 1,
|
|
26
|
+
* 1998"). A caller that formats for display reads this first and only
|
|
27
|
+
* requests the precision the raw string actually had.
|
|
28
|
+
*
|
|
29
|
+
* A value the `DATE_ONLY` forms don't match (it carries a time, or isn't a
|
|
30
|
+
* recognised date at all) names a specific instant rather than a calendar
|
|
31
|
+
* field, so it's always `"day"` — full precision, same as today.
|
|
32
|
+
*/
|
|
33
|
+
export type CellDatePrecision = "year" | "month" | "day";
|
|
34
|
+
export declare function cellDatePrecision(raw: string): CellDatePrecision;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { formatCellDate, parseCellDate } from "./cell-date";
|
|
1
|
+
export { type CellDatePrecision, cellDatePrecision, formatCellDate, parseCellDate, } from "./cell-date";
|
|
2
2
|
export { cx } from "./cx";
|
|
3
3
|
export { defineRecipe } from "./define";
|
|
4
4
|
export { withDescribedBy } from "./dialog-description";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./components/card";
|
|
|
11
11
|
export * from "./components/checkbox";
|
|
12
12
|
export * from "./components/chip";
|
|
13
13
|
export * from "./components/columncalc";
|
|
14
|
+
export * from "./components/composewindow";
|
|
14
15
|
export * from "./components/contextmenu";
|
|
15
16
|
export * from "./components/datatable";
|
|
16
17
|
export * from "./components/datepicker";
|
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type Column, type Row } from "../recordstable";
|
|
3
|
+
export type RecordPageNote = {
|
|
4
|
+
id: string;
|
|
5
|
+
text: string;
|
|
6
|
+
time: string;
|
|
7
|
+
};
|
|
8
|
+
export type RecordPageTask = {
|
|
9
|
+
id: string;
|
|
10
|
+
text: string;
|
|
11
|
+
done: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A consumer-supplied tab, replacing one of the built-in CRM tabs
|
|
15
|
+
* (Overview/Activity/Emails/Calls/Team/Notes/Tasks/Files/Deals). `render`
|
|
16
|
+
* is called only while its tab is active, the same lazy-body contract the
|
|
17
|
+
* built-in tabs already follow.
|
|
18
|
+
*/
|
|
19
|
+
export type RecordPageTab = {
|
|
20
|
+
id: string;
|
|
21
|
+
label: string;
|
|
22
|
+
/** Optional count/badge shown after the label (e.g. "Notes · 3"). */
|
|
23
|
+
count?: number;
|
|
24
|
+
render: () => React.ReactNode;
|
|
25
|
+
};
|
|
3
26
|
export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "children"> & {
|
|
4
27
|
record: Row;
|
|
5
28
|
columns: Column[];
|
|
29
|
+
/**
|
|
30
|
+
* Commit handler for a `column.editable` Details field (#431) — same
|
|
31
|
+
* shape `DataTable`'s own `onEdit` uses (#385/#430): returning (or
|
|
32
|
+
* resolving) nothing commits synchronously; returning a `Promise` that
|
|
33
|
+
* rejects shows a pending state on the field while it's in flight, then
|
|
34
|
+
* reverts to the last-known-good value (this component never mutates
|
|
35
|
+
* `record` itself) and renders the rejection's message beside the field.
|
|
36
|
+
* A field with `editable` but no `onEdit` never opens — there's nothing
|
|
37
|
+
* to commit to.
|
|
38
|
+
*/
|
|
39
|
+
onEdit?: (id: string, key: string, value: string) => Promise<void> | void;
|
|
6
40
|
/** Breadcrumb label + back button target (e.g. "Companies"). */
|
|
7
41
|
collection?: string;
|
|
8
42
|
/** Partial override of the chrome strings; see `recordPageLabels`. */
|
|
@@ -12,6 +46,30 @@ export type RecordPageProps = Omit<React.ComponentPropsWithoutRef<"div">, "child
|
|
|
12
46
|
onToggleFull?: () => void;
|
|
13
47
|
full?: boolean;
|
|
14
48
|
className?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Replaces the built-in CRM tab set. An app with a non-CRM domain (a
|
|
51
|
+
* custom register's own sections, a Related/backlinks tab) supplies its
|
|
52
|
+
* own list instead of rebuilding RecordPage's chrome by hand. Omit to
|
|
53
|
+
* keep the default Overview/Activity/Emails/Calls/Team/Notes/Tasks/
|
|
54
|
+
* Files/Deals set.
|
|
55
|
+
*/
|
|
56
|
+
tabs?: RecordPageTab[];
|
|
57
|
+
/** Active tab id on first render, when `tabs` is supplied. Defaults to the first tab. Ignored for the built-in tab set (Overview is always first there). */
|
|
58
|
+
defaultTab?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Controlled Notes: when supplied (even as `[]`), RecordPage renders
|
|
61
|
+
* this list instead of managing its own, and the composer calls
|
|
62
|
+
* `onAddNote` instead of appending to internal state — the same
|
|
63
|
+
* "caller owns the data, crisp owns the chrome" shape `Board`'s
|
|
64
|
+
* `cards`/`onCardsChange` uses. Omit both to keep the self-contained
|
|
65
|
+
* Notes section (crisp owns the data too, as today).
|
|
66
|
+
*/
|
|
67
|
+
notes?: RecordPageNote[];
|
|
68
|
+
onAddNote?: (text: string) => void;
|
|
69
|
+
/** Controlled Tasks — same shape as `notes`/`onAddNote`. */
|
|
70
|
+
tasks?: RecordPageTask[];
|
|
71
|
+
onAddTask?: (text: string) => void;
|
|
72
|
+
onToggleTask?: (id: string) => void;
|
|
15
73
|
};
|
|
16
74
|
/**
|
|
17
75
|
* Every chrome string RecordPage renders. Supplied as a PARTIAL map, so
|
|
@@ -97,7 +155,7 @@ export type RecordPageLabelsInput = Partial<Omit<RecordPageLabels, "tabs" | "hig
|
|
|
97
155
|
* Emails sections (Notes & Tasks are live — add and check things off). Drop it
|
|
98
156
|
* into the app's main content area.
|
|
99
157
|
*/
|
|
100
|
-
export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, className, ...rest }: RecordPageProps): React.JSX.Element;
|
|
158
|
+
export declare function RecordPage({ record, columns, collection, labels, onBack, onToggleFull, full, className, onEdit, tabs: tabsProp, defaultTab, notes: notesProp, onAddNote, tasks: tasksProp, onAddTask, onToggleTask, ...rest }: RecordPageProps): React.JSX.Element;
|
|
101
159
|
export declare namespace RecordPage {
|
|
102
160
|
var displayName: string;
|
|
103
161
|
}
|
|
@@ -21,6 +21,16 @@ export type RecordPanelProps = Omit<React.ComponentPropsWithoutRef<"div">, "chil
|
|
|
21
21
|
record: Row | null;
|
|
22
22
|
columns: Column[];
|
|
23
23
|
onClose: () => void;
|
|
24
|
+
/**
|
|
25
|
+
* Commit handler for a `column.editable` field (#431) — same shape
|
|
26
|
+
* `DataTable`'s own `onEdit` uses (#385/#430): returning (or resolving)
|
|
27
|
+
* nothing commits synchronously; returning a `Promise` that rejects shows
|
|
28
|
+
* a pending state on the field while it's in flight, then reverts to the
|
|
29
|
+
* last-known-good value (this component never mutates `record` itself)
|
|
30
|
+
* and renders the rejection's message beside the field. A field with
|
|
31
|
+
* `editable` but no `onEdit` never opens — there's nothing to commit to.
|
|
32
|
+
*/
|
|
33
|
+
onEdit?: (id: string, key: string, value: string) => Promise<void> | void;
|
|
24
34
|
className?: string;
|
|
25
35
|
};
|
|
26
36
|
/**
|
|
@@ -29,7 +39,7 @@ export type RecordPanelProps = Omit<React.ComponentPropsWithoutRef<"div">, "chil
|
|
|
29
39
|
* relative` container (e.g. the app main area); it slides in from the right and
|
|
30
40
|
* overlays the content.
|
|
31
41
|
*/
|
|
32
|
-
export declare function RecordPanel({ record, columns, onClose, className, closeLabel, title, detailsLabel, emptyLabel, footer, ...rest }: RecordPanelProps): React.JSX.Element | null;
|
|
42
|
+
export declare function RecordPanel({ record, columns, onClose, className, closeLabel, title, detailsLabel, emptyLabel, footer, onEdit, ...rest }: RecordPanelProps): React.JSX.Element | null;
|
|
33
43
|
export declare namespace RecordPanel {
|
|
34
44
|
var displayName: string;
|
|
35
45
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** A `select`-editor field's choices — same shape DataTable's own
|
|
2
|
+
* `DataEditableOption` uses (#385/#430), kept as its own type (not
|
|
3
|
+
* `Column.options`/`StatusOption`, whose `color` is required for the
|
|
4
|
+
* `status` picker) so this stays purely additive. */
|
|
5
|
+
export type EditableOption = {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
color?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The async-commit state machine behind `RecordPanel`/`RecordPage`'s
|
|
12
|
+
* editable fields (#431) — the same shape `DataTable`'s own `commitEdit`
|
|
13
|
+
* uses (#385/#430): a sync `onEdit` (returns `undefined`) commits and closes
|
|
14
|
+
* immediately; a Promise-returning `onEdit` keeps the field open and pending
|
|
15
|
+
* while it settles, then either closes it (resolve) or closes it AND
|
|
16
|
+
* reverts while showing the rejection's message (reject). The revert needs
|
|
17
|
+
* no extra code here either: neither `RecordPanel` nor `RecordPage` mutates
|
|
18
|
+
* `record` itself, so once `editingKey` clears, the field simply renders
|
|
19
|
+
* `record[key]` again — whatever it still says.
|
|
20
|
+
*
|
|
21
|
+
* One hook shared by both consumers rather than two copies of the same
|
|
22
|
+
* three `useState`s and the same `.then` branching.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useEditableField(onEdit?: (id: string, key: string, value: string) => Promise<void> | void): {
|
|
25
|
+
editingKey: string | null;
|
|
26
|
+
pendingKey: string | null;
|
|
27
|
+
error: {
|
|
28
|
+
key: string;
|
|
29
|
+
message: string;
|
|
30
|
+
} | null;
|
|
31
|
+
openEditing: (key: string) => void;
|
|
32
|
+
closeEditing: () => void;
|
|
33
|
+
commit: (id: string, key: string, value: string) => void;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Which plain editor a column gets when it's `editable` without an
|
|
37
|
+
* `editor: "select" | "switch"` — identical to `DataTable`'s own
|
|
38
|
+
* `editorFor` (#385): number/currency get a numeric field, date a native
|
|
39
|
+
* date field, everything else (text, entity, tags, url, status, reference)
|
|
40
|
+
* a plain text field. Kept as one function so the two never drift apart.
|
|
41
|
+
*/
|
|
42
|
+
export declare function editableInputType(colType: string | undefined): {
|
|
43
|
+
type: string;
|
|
44
|
+
inputMode?: "decimal" | "text";
|
|
45
|
+
};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
+
export { type EditableOption, editableInputType, useEditableField, } from "./editable-field";
|
|
1
2
|
export { type Column, type ColumnType, defaultColumns, defaultRows, type EntityValue, RecordsTable, type RecordsTableProps, type Row, tagTone, } from "./recordstable";
|
|
2
3
|
export { recordstableRecipe } from "./recordstable.recipe";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
+
import type { EditableOption } from "./editable-field";
|
|
2
3
|
type IconType = React.ComponentType<{
|
|
3
4
|
size?: number;
|
|
4
5
|
strokeWidth?: number;
|
|
@@ -29,6 +30,14 @@ export type Column = {
|
|
|
29
30
|
options?: StatusOption[];
|
|
30
31
|
/** Choices for a `reference` column (a searchable record picker). */
|
|
31
32
|
refOptions?: ReferenceOption[];
|
|
33
|
+
/** Adds a trailing "Create {createLabel}" row to the picker (Attio's own
|
|
34
|
+
* always has one) — rendered only when this is provided. Picking it hands
|
|
35
|
+
* back the picker's current search text, e.g. to open a create flow
|
|
36
|
+
* pre-seeded with it. */
|
|
37
|
+
onCreateReference?: (query: string) => void;
|
|
38
|
+
/** The object noun in "Create {createLabel}" (Attio: "Create Person").
|
|
39
|
+
* Only used with `onCreateReference`; defaults to "record". */
|
|
40
|
+
createLabel?: string;
|
|
32
41
|
/**
|
|
33
42
|
* Full custom cell content — an escape hatch for a display crisp can't
|
|
34
43
|
* express via `type` (sign-coloured currency, a maskable amount, a custom
|
|
@@ -65,6 +74,26 @@ export type Column = {
|
|
|
65
74
|
* currency string still sums and sorts numerically.
|
|
66
75
|
*/
|
|
67
76
|
format?: (value: unknown, row: Row) => string;
|
|
77
|
+
/**
|
|
78
|
+
* Opts this column into `RecordPanel`/`RecordPage`'s editable-field API
|
|
79
|
+
* (#431) — click-to-edit there (not this table's own type-driven
|
|
80
|
+
* mechanism, which those two components don't use). Ignored by
|
|
81
|
+
* `RecordsTable` itself. A plain `editable` column, with no `editor`,
|
|
82
|
+
* opens a text/number/date field (inferred from `type`, same inference
|
|
83
|
+
* `DataTable`'s own `editable` columns use — #385); `editor` below picks
|
|
84
|
+
* a `select`/`switch` picker instead. Both consumers require `onEdit` to
|
|
85
|
+
* actually be given for a field to open at all.
|
|
86
|
+
*/
|
|
87
|
+
editable?: boolean;
|
|
88
|
+
/** `select`/`switch` render as the field's own live, always-interactive
|
|
89
|
+
* content instead of opening on click — see `DataTableColumn.editor`
|
|
90
|
+
* (#385) for the identical convention and reasoning. `select` reads
|
|
91
|
+
* `editOptions`. */
|
|
92
|
+
editor?: "select" | "switch";
|
|
93
|
+
/** Options for `editor: "select"` — same shape `DataTable`'s own
|
|
94
|
+
* `DataEditableOption` uses. Not `options` (`StatusOption` requires
|
|
95
|
+
* `color`, for this type's own `status` picker) so this stays additive. */
|
|
96
|
+
editOptions?: EditableOption[];
|
|
68
97
|
};
|
|
69
98
|
export type EntityValue = {
|
|
70
99
|
name: string;
|