@crispy-seed/data-table 0.7.0 → 0.9.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/data-table-recipe.css +7 -2
- package/dist/data-table-recipe.layered.css +3 -1
- package/dist/index.cjs +3490 -409
- package/dist/index.d.ts +246 -62
- package/dist/index.js +3491 -410
- package/dist/record-preview-recipe.css +16 -0
- package/dist/record-preview-recipe.layered.css +19 -0
- package/dist/resizable-panel-recipe.css +90 -22
- package/dist/resizable-panel-recipe.layered.css +88 -22
- package/dist/styles.css +110 -23
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
declare interface DataTableVariant {
|
|
@@ -57,15 +57,18 @@ interface ToolbarFilter {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
60
|
+
* Live-review fix (Attio/GRC parity): the ColumnCalc footer's own aggregation set --
|
|
61
|
+
* three apply to every column, six more to numeric ones, one more to non-numeric ones.
|
|
62
|
+
* Distinct from crisp's own `ColumnCalc` (`countEmpty`/`countFilled`/`percentEmpty`/
|
|
63
|
+
* `percentFilled` + sum/average/min/max + "none") -- crisp's own set was read for the
|
|
64
|
+
* MENU/trigger interaction (`column-calc.tsx`'s own doc comment), not copied op-for-op;
|
|
65
|
+
* this table's contract is the ten named directly in DATATABLE-ATTIO-SPEC.md/the GRC
|
|
66
|
+
* feature contract: count / empty / not-empty everywhere, sum / average / median / min
|
|
67
|
+
* / max / range on a numeric column, count-unique on a non-numeric one. The styled
|
|
68
|
+
* layer picks which extra set to offer off the column's own cell type (`column-calc.tsx`'s
|
|
69
|
+
* `ColumnCalcCell`).
|
|
67
70
|
*/
|
|
68
|
-
type DataTableCalcOp = "count" | "
|
|
71
|
+
type DataTableCalcOp = "count" | "empty" | "notEmpty" | "sum" | "average" | "median" | "min" | "max" | "range" | "countUnique";
|
|
69
72
|
|
|
70
73
|
/** Everything a saved view actually captures -- deliberately the same five controlled
|
|
71
74
|
* props `useDataTableColumns` + the toolbar sort/filter hooks already expose, so
|
|
@@ -135,7 +138,7 @@ interface DataTableColumn<TRow> {
|
|
|
135
138
|
*/
|
|
136
139
|
key: string;
|
|
137
140
|
/** 헤더 셀에 표시할 내용입니다. */
|
|
138
|
-
header:
|
|
141
|
+
header: React.ReactNode;
|
|
139
142
|
/** 이 열을 클릭해 정렬할 수 있는지 여부입니다. */
|
|
140
143
|
sortable?: boolean;
|
|
141
144
|
/**
|
|
@@ -146,7 +149,7 @@ interface DataTableColumn<TRow> {
|
|
|
146
149
|
/** 셀 내용을 직접 그립니다. 지정하면 `type`의 기본 렌더러 대신 이것을 사용합니다.
|
|
147
150
|
* `editable`이어도 편집/always-live 상태에는 영향이 없습니다 -- 이 필드는 REST
|
|
148
151
|
* 상태의 표시만 바꿉니다. */
|
|
149
|
-
render?: (row: TRow) =>
|
|
152
|
+
render?: (row: TRow) => React.ReactNode;
|
|
150
153
|
/** `type: "currency"`의 통화 기호입니다. @default "$" */
|
|
151
154
|
symbol?: string;
|
|
152
155
|
/** `type: "rating"`의 별 개수입니다. @default 5 */
|
|
@@ -269,7 +272,7 @@ interface DataTableColumn<TRow> {
|
|
|
269
272
|
}
|
|
270
273
|
interface DataTableProps<TRow extends {
|
|
271
274
|
id: string;
|
|
272
|
-
}> extends DataTableVariantProps, Omit<PrimitiveProps, "asChild">, Omit<
|
|
275
|
+
}> extends DataTableVariantProps, Omit<PrimitiveProps, "asChild">, Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
273
276
|
columns: DataTableColumn<TRow>[];
|
|
274
277
|
data: TRow[];
|
|
275
278
|
/** `type`이 있는 열의 number/currency/date/datetime 표시에 쓰는 로캘입니다. @default "en-US" */
|
|
@@ -278,17 +281,18 @@ interface DataTableProps<TRow extends {
|
|
|
278
281
|
sort?: DataTableSortState;
|
|
279
282
|
/** 비제어 방식으로 사용할 때의 초기 정렬 상태입니다. */
|
|
280
283
|
defaultSort?: DataTableSortState;
|
|
281
|
-
/** 정렬 가능한 열을 클릭해 정렬 상태가 바뀔
|
|
282
|
-
|
|
284
|
+
/** 정렬 가능한 열을 클릭해 정렬 상태가 바뀔 때, 그리고 열 메뉴의 "Clear sort"로
|
|
285
|
+
* 정렬이 지워질 때 호출됩니다 -- 지워진 상태는 `undefined`로 전달됩니다. */
|
|
286
|
+
onSortChange?: (sort: DataTableSortState | undefined) => void;
|
|
283
287
|
/**
|
|
284
288
|
* 정렬 아이콘입니다. `idle`은 정렬 가능하지만 아직 정렬되지 않은 열의 헤더에
|
|
285
289
|
* (호버 시에만 드러나는) 기본 표시로 쓰이고, `asc`/`desc`는 실제로 정렬된 열에
|
|
286
290
|
* 씁니다. 생략하면 karrot 아이콘 셋의 chevron을 씁니다.
|
|
287
291
|
*/
|
|
288
292
|
sortIcon?: {
|
|
289
|
-
idle?:
|
|
290
|
-
asc?:
|
|
291
|
-
desc?:
|
|
293
|
+
idle?: React.ReactNode;
|
|
294
|
+
asc?: React.ReactNode;
|
|
295
|
+
desc?: React.ReactNode;
|
|
292
296
|
};
|
|
293
297
|
/** 왼쪽에 40px짜리 체크박스 선택 열을 추가합니다. */
|
|
294
298
|
selectable?: boolean;
|
|
@@ -304,10 +308,10 @@ interface DataTableProps<TRow extends {
|
|
|
304
308
|
getRowSelectionLabel?: (row: TRow) => string;
|
|
305
309
|
/** 선택 체크박스가 checked일 때 표시할 아이콘입니다. 생략하면 karrot의 체크 아이콘을
|
|
306
310
|
* 씁니다. */
|
|
307
|
-
selectionCheckedIcon?:
|
|
311
|
+
selectionCheckedIcon?: React.ReactNode;
|
|
308
312
|
/** 전체 선택 체크박스가 일부만 선택됐을 때(indeterminate) 표시할 아이콘입니다.
|
|
309
313
|
* 생략하면 karrot의 minus 아이콘을 씁니다. */
|
|
310
|
-
selectionIndeterminateIcon?:
|
|
314
|
+
selectionIndeterminateIcon?: React.ReactNode;
|
|
311
315
|
/** 제어할 검색어입니다. */
|
|
312
316
|
query?: string;
|
|
313
317
|
/** 비제어 방식으로 사용할 때의 초기 검색어입니다. */
|
|
@@ -344,7 +348,7 @@ interface DataTableProps<TRow extends {
|
|
|
344
348
|
* 행 개수 텍스트를 직접 만듭니다. 생략하면 crisp의 기본 형식을 씁니다: 검색/필터로
|
|
345
349
|
* 줄지 않았으면 "N rows"(단수는 "row"), 줄었으면 "N of M".
|
|
346
350
|
*/
|
|
347
|
-
countLabel?: (shown: number, total: number) =>
|
|
351
|
+
countLabel?: (shown: number, total: number) => React.ReactNode;
|
|
348
352
|
/**
|
|
349
353
|
* 툴바 오른쪽, 행 개수 옆에 렌더링할 커스텀 액션입니다(예: Download/내보내기 버튼).
|
|
350
354
|
* 이전에는 이 자리에 넣을 공식 prop이 없어서 소비자가 `.seed-data-table__toolbar`
|
|
@@ -353,7 +357,7 @@ interface DataTableProps<TRow extends {
|
|
|
353
357
|
* 렌더링됩니다). 검색/정렬/필터보다 뒤, 카운트보다 앞(같은 그룹 안에서 카운트
|
|
354
358
|
* 왼쪽)에 옵니다.
|
|
355
359
|
*/
|
|
356
|
-
toolbarActions?:
|
|
360
|
+
toolbarActions?: React.ReactNode;
|
|
357
361
|
/** 헤더의 열별 메뉴(이름 변경 / 숨기기 / 왼쪽·오른쪽으로 이동)를 켭니다, seed `Menu`. */
|
|
358
362
|
columnMenu?: boolean;
|
|
359
363
|
/** 헤더를 드래그해 열 순서를 바꿀 수 있게 합니다. @default true */
|
|
@@ -427,19 +431,19 @@ interface DataTableProps<TRow extends {
|
|
|
427
431
|
/** 주어지면 맨 아래에 crisp가 측정한 "+ New" 추가 행 버튼을 렌더링합니다. */
|
|
428
432
|
onAddRow?: () => void;
|
|
429
433
|
/** 추가 행 버튼의 라벨입니다. @default "New record" */
|
|
430
|
-
addRowLabel?:
|
|
434
|
+
addRowLabel?: React.ReactNode;
|
|
431
435
|
/** 전체 본문을 이 상태로 대체합니다(로딩 아이콘 + `loadingLabel`) -- 필터/정렬
|
|
432
436
|
* 재조회나 최초 로드처럼 행 전체가 아직 없을 때를 위한 것입니다. `error`/빈 상태
|
|
433
437
|
* 보다 우선합니다. 인라인 스크롤 로딩 표시기(`onLoadMore`)와는 별개입니다. */
|
|
434
438
|
loading?: boolean;
|
|
435
439
|
/** `loading`일 때 스피너 옆에 보이는 텍스트입니다. @default "Loading..." */
|
|
436
|
-
loadingLabel?:
|
|
440
|
+
loadingLabel?: React.ReactNode;
|
|
437
441
|
/** 주어지면 행 대신 이 내용을 본문에 렌더링합니다(crisp의 `.crisp-datatable-empty`
|
|
438
442
|
* 칸 재사용). `loading`보다는 아래, 빈 상태보다는 위 우선순위입니다. */
|
|
439
|
-
error?:
|
|
443
|
+
error?: React.ReactNode;
|
|
440
444
|
/** 검색/필터를 거치고도 행이 하나도 없을 때 본문에 렌더링할 내용입니다.
|
|
441
445
|
* @default "No results." */
|
|
442
|
-
empty?:
|
|
446
|
+
empty?: React.ReactNode;
|
|
443
447
|
/**
|
|
444
448
|
* Attio 스타일 무한 스크롤: 스크롤 컨테이너 바닥 근처의 sentinel 행이 뷰에 들어오면
|
|
445
449
|
* 호출됩니다. `Promise`를 반환하면 그동안 자동으로 `loadingMore`가 켜집니다(직접
|
|
@@ -463,7 +467,7 @@ interface DataTableProps<TRow extends {
|
|
|
463
467
|
* `style={{ height: "100%" }}` 같은 바운드를 주는 것만으로도 "전체 높이" 모드가
|
|
464
468
|
* 됩니다 -- 새 prop 없이 기존 `style` 전달만으로 두 모드 다 지원됩니다.
|
|
465
469
|
*/
|
|
466
|
-
scrollProps?: Omit<
|
|
470
|
+
scrollProps?: Omit<React.ComponentPropsWithoutRef<"div">, "ref" | "onScroll">;
|
|
467
471
|
}
|
|
468
472
|
/**
|
|
469
473
|
* @see https://seed-design.io/react/components/data-table
|
|
@@ -471,8 +475,8 @@ interface DataTableProps<TRow extends {
|
|
|
471
475
|
declare const DataTable: <TRow extends {
|
|
472
476
|
id: string;
|
|
473
477
|
}>(props: DataTableProps<TRow> & {
|
|
474
|
-
ref?:
|
|
475
|
-
}) =>
|
|
478
|
+
ref?: React.ForwardedRef<HTMLDivElement>;
|
|
479
|
+
}) => React.ReactElement;
|
|
476
480
|
|
|
477
481
|
interface DataTableViewsControlProps extends UseDataTableViewsProps {
|
|
478
482
|
/** The trigger's label when no view is active. @default "Views" */
|
|
@@ -482,7 +486,7 @@ interface DataTableViewsControlProps extends UseDataTableViewsProps {
|
|
|
482
486
|
* meaningful "no view" state to switch back to. */
|
|
483
487
|
showClearRow?: boolean;
|
|
484
488
|
/** The clear row's own label, when `showClearRow` is on. @default "label" */
|
|
485
|
-
clearLabel?:
|
|
489
|
+
clearLabel?: React.ReactNode;
|
|
486
490
|
/**
|
|
487
491
|
* Reads the table's CURRENT column order/visibility/widths/pins + toolbar sort/
|
|
488
492
|
* filter conditions -- called when the user picks "Save as new view" or "Update
|
|
@@ -518,7 +522,7 @@ declare namespace DataTableViewsControl {
|
|
|
518
522
|
type ResizablePanelSide = "left" | "right";
|
|
519
523
|
|
|
520
524
|
type ResizablePanelHandleVariant = "panel" | "column";
|
|
521
|
-
type ResizablePanelProps = Omit<
|
|
525
|
+
type ResizablePanelProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "onResize"> & {
|
|
522
526
|
/** Which edge of its container the panel is anchored to. @default "left" */
|
|
523
527
|
side?: ResizablePanelSide;
|
|
524
528
|
/** Controlled width, in px. */
|
|
@@ -538,11 +542,42 @@ type ResizablePanelProps = Omit<react.ComponentPropsWithoutRef<"div">, "children
|
|
|
538
542
|
*/
|
|
539
543
|
max?: number | string;
|
|
540
544
|
/**
|
|
541
|
-
* Layout model
|
|
542
|
-
*
|
|
543
|
-
*
|
|
545
|
+
* Layout model. "docked" (default) is IN-FLOW: `spacer` reserves the
|
|
546
|
+
* panel's real width, shrinking a `flex: 1` sibling beside it (e.g. a
|
|
547
|
+
* table), flush with a hairline border -- unchanged since this
|
|
548
|
+
* primitive's own first version.
|
|
549
|
+
*
|
|
550
|
+
* "floating" is a true OVERLAY, not a bigger gutter on the docked look:
|
|
551
|
+
* this component's own outer element takes itself OUT of flow entirely
|
|
552
|
+
* (`position: absolute; inset: 0`) and renders no `spacer` at all -- it
|
|
553
|
+
* reserves ZERO layout width, so a sibling beside it (a table) never
|
|
554
|
+
* shrinks or reflows when this opens or resizes. The panel itself is
|
|
555
|
+
* pinned to one edge of that `inset: 0` box, spans its full height, and
|
|
556
|
+
* only the corners facing INTO the container are rounded (a left-edge
|
|
557
|
+
* shadow for `side="right"`, mirrored for `side="left"`) -- this is
|
|
558
|
+
* `RecordPreview`'s own peek panel (your-moon/crisp#448 reversed a
|
|
559
|
+
* docked/reflow attempt at this exact spot: "table's action buttons
|
|
560
|
+
* moving" when the panel opened).
|
|
561
|
+
*
|
|
562
|
+
* Because the outer element is now `position: absolute`, the consumer's
|
|
563
|
+
* own immediate parent (wherever this component -- or `RecordPreview` --
|
|
564
|
+
* is rendered) MUST itself be a positioned element (typically
|
|
565
|
+
* `position: relative`) with a real height, e.g. the table region's own
|
|
566
|
+
* wrapper div. No flex-row wrapper is needed or wanted: the table can be
|
|
567
|
+
* an ordinary 100%-width block and this panel a plain sibling.
|
|
544
568
|
*/
|
|
545
569
|
floating?: boolean;
|
|
570
|
+
/**
|
|
571
|
+
* An optional dimming backdrop behind a `floating` panel, covering the
|
|
572
|
+
* same `inset: 0` container -- OFF by default: this is a peek panel, not
|
|
573
|
+
* a modal, and Attio's own peek never dims the table it floats over.
|
|
574
|
+
* Meaningful only together with `floating`; ignored otherwise.
|
|
575
|
+
* @default false
|
|
576
|
+
*/
|
|
577
|
+
backdrop?: boolean;
|
|
578
|
+
/** Fires when the optional `backdrop` is clicked. Typically wired to the
|
|
579
|
+
* same handler as the panel's own close control. */
|
|
580
|
+
onBackdropClick?: () => void;
|
|
546
581
|
/** Resize-handle geometry -- "panel" (default) or "column" (table edges). */
|
|
547
582
|
handleVariant?: ResizablePanelHandleVariant;
|
|
548
583
|
/**
|
|
@@ -559,20 +594,42 @@ type ResizablePanelProps = Omit<react.ComponentPropsWithoutRef<"div">, "children
|
|
|
559
594
|
* `width` is uncontrolled.
|
|
560
595
|
*/
|
|
561
596
|
storageKey?: string;
|
|
597
|
+
/**
|
|
598
|
+
* Drives the floating panel's own enter/exit keyframe animation (only
|
|
599
|
+
* meaningful together with `floating`) -- "open" plays the slide-and-fade
|
|
600
|
+
* in on mount, "closed" plays it in reverse. A consumer that keeps this
|
|
601
|
+
* component mounted through its own close transition (e.g.
|
|
602
|
+
* `@seed-design/react-presence`'s `usePresence`, the same idiom Dialog/
|
|
603
|
+
* Drawer use) flips this once `open` goes false, then unmounts once that
|
|
604
|
+
* hook reports the exit animation finished. Omit for a panel that
|
|
605
|
+
* shouldn't animate at all.
|
|
606
|
+
*/
|
|
607
|
+
animationState?: "open" | "closed";
|
|
608
|
+
/**
|
|
609
|
+
* Ref to the panel element itself (not the outer root/spacer wrapper this
|
|
610
|
+
* component's own `ref` targets) -- lets a consumer's presence hook
|
|
611
|
+
* observe `animationName` changes on the SAME node that carries
|
|
612
|
+
* `data-state`/the keyframe animation above.
|
|
613
|
+
*/
|
|
614
|
+
panelElementRef?: React.Ref<HTMLDivElement>;
|
|
562
615
|
className?: string;
|
|
563
|
-
children?:
|
|
616
|
+
children?: React.ReactNode;
|
|
564
617
|
};
|
|
565
618
|
/**
|
|
566
|
-
* An adjustable-panel primitive
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
619
|
+
* An adjustable-panel primitive with two layout models (`floating`'s own doc
|
|
620
|
+
* comment above has the full contrast). Docked: a `spacer` reserves layout
|
|
621
|
+
* width and the panel overlays exactly that reservation, so a resize drag
|
|
622
|
+
* never causes a reflow glitch on the rest of the layout. Floating: no
|
|
623
|
+
* spacer at all -- this component's own outer element becomes a
|
|
624
|
+
* `position: absolute; inset: 0` overlay reserving zero width, with the
|
|
625
|
+
* panel itself pinned to one edge and spanning the full height of that box.
|
|
626
|
+
* Drag the edge handle to resize; constraints are CSS `min-width`/
|
|
627
|
+
* `max-width`, never re-clamped in JS. Ported from your-moon/crisp's
|
|
628
|
+
* `ResizablePanel` (`components/resizablepanel/`); state/drag behavior
|
|
629
|
+
* lives in `useResizablePanel` (`@seed-design/react-resizable-panel`), this
|
|
630
|
+
* component owns the DOM + recipe classes on top of it.
|
|
574
631
|
*/
|
|
575
|
-
declare const ResizablePanel:
|
|
632
|
+
declare const ResizablePanel: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "onResize"> & {
|
|
576
633
|
/** Which edge of its container the panel is anchored to. @default "left" */
|
|
577
634
|
side?: ResizablePanelSide;
|
|
578
635
|
/** Controlled width, in px. */
|
|
@@ -592,11 +649,42 @@ declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<Omit<react.De
|
|
|
592
649
|
*/
|
|
593
650
|
max?: number | string;
|
|
594
651
|
/**
|
|
595
|
-
* Layout model
|
|
596
|
-
*
|
|
597
|
-
*
|
|
652
|
+
* Layout model. "docked" (default) is IN-FLOW: `spacer` reserves the
|
|
653
|
+
* panel's real width, shrinking a `flex: 1` sibling beside it (e.g. a
|
|
654
|
+
* table), flush with a hairline border -- unchanged since this
|
|
655
|
+
* primitive's own first version.
|
|
656
|
+
*
|
|
657
|
+
* "floating" is a true OVERLAY, not a bigger gutter on the docked look:
|
|
658
|
+
* this component's own outer element takes itself OUT of flow entirely
|
|
659
|
+
* (`position: absolute; inset: 0`) and renders no `spacer` at all -- it
|
|
660
|
+
* reserves ZERO layout width, so a sibling beside it (a table) never
|
|
661
|
+
* shrinks or reflows when this opens or resizes. The panel itself is
|
|
662
|
+
* pinned to one edge of that `inset: 0` box, spans its full height, and
|
|
663
|
+
* only the corners facing INTO the container are rounded (a left-edge
|
|
664
|
+
* shadow for `side="right"`, mirrored for `side="left"`) -- this is
|
|
665
|
+
* `RecordPreview`'s own peek panel (your-moon/crisp#448 reversed a
|
|
666
|
+
* docked/reflow attempt at this exact spot: "table's action buttons
|
|
667
|
+
* moving" when the panel opened).
|
|
668
|
+
*
|
|
669
|
+
* Because the outer element is now `position: absolute`, the consumer's
|
|
670
|
+
* own immediate parent (wherever this component -- or `RecordPreview` --
|
|
671
|
+
* is rendered) MUST itself be a positioned element (typically
|
|
672
|
+
* `position: relative`) with a real height, e.g. the table region's own
|
|
673
|
+
* wrapper div. No flex-row wrapper is needed or wanted: the table can be
|
|
674
|
+
* an ordinary 100%-width block and this panel a plain sibling.
|
|
598
675
|
*/
|
|
599
676
|
floating?: boolean;
|
|
677
|
+
/**
|
|
678
|
+
* An optional dimming backdrop behind a `floating` panel, covering the
|
|
679
|
+
* same `inset: 0` container -- OFF by default: this is a peek panel, not
|
|
680
|
+
* a modal, and Attio's own peek never dims the table it floats over.
|
|
681
|
+
* Meaningful only together with `floating`; ignored otherwise.
|
|
682
|
+
* @default false
|
|
683
|
+
*/
|
|
684
|
+
backdrop?: boolean;
|
|
685
|
+
/** Fires when the optional `backdrop` is clicked. Typically wired to the
|
|
686
|
+
* same handler as the panel's own close control. */
|
|
687
|
+
onBackdropClick?: () => void;
|
|
600
688
|
/** Resize-handle geometry -- "panel" (default) or "column" (table edges). */
|
|
601
689
|
handleVariant?: ResizablePanelHandleVariant;
|
|
602
690
|
/**
|
|
@@ -613,9 +701,27 @@ declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<Omit<react.De
|
|
|
613
701
|
* `width` is uncontrolled.
|
|
614
702
|
*/
|
|
615
703
|
storageKey?: string;
|
|
704
|
+
/**
|
|
705
|
+
* Drives the floating panel's own enter/exit keyframe animation (only
|
|
706
|
+
* meaningful together with `floating`) -- "open" plays the slide-and-fade
|
|
707
|
+
* in on mount, "closed" plays it in reverse. A consumer that keeps this
|
|
708
|
+
* component mounted through its own close transition (e.g.
|
|
709
|
+
* `@seed-design/react-presence`'s `usePresence`, the same idiom Dialog/
|
|
710
|
+
* Drawer use) flips this once `open` goes false, then unmounts once that
|
|
711
|
+
* hook reports the exit animation finished. Omit for a panel that
|
|
712
|
+
* shouldn't animate at all.
|
|
713
|
+
*/
|
|
714
|
+
animationState?: "open" | "closed";
|
|
715
|
+
/**
|
|
716
|
+
* Ref to the panel element itself (not the outer root/spacer wrapper this
|
|
717
|
+
* component's own `ref` targets) -- lets a consumer's presence hook
|
|
718
|
+
* observe `animationName` changes on the SAME node that carries
|
|
719
|
+
* `data-state`/the keyframe animation above.
|
|
720
|
+
*/
|
|
721
|
+
panelElementRef?: React.Ref<HTMLDivElement>;
|
|
616
722
|
className?: string;
|
|
617
|
-
children?:
|
|
618
|
-
} &
|
|
723
|
+
children?: React.ReactNode;
|
|
724
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
619
725
|
|
|
620
726
|
/** One Highlights card -- label, value and an optional icon, laid out the way
|
|
621
727
|
* Attio's own peek panel lays its own out (your-moon/crisp#448, measured
|
|
@@ -624,8 +730,8 @@ declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<Omit<react.De
|
|
|
624
730
|
type RecordPreviewHighlight = {
|
|
625
731
|
key: string;
|
|
626
732
|
label: string;
|
|
627
|
-
value:
|
|
628
|
-
icon?:
|
|
733
|
+
value: React.ReactNode;
|
|
734
|
+
icon?: React.ComponentType<{
|
|
629
735
|
size?: number;
|
|
630
736
|
}>;
|
|
631
737
|
};
|
|
@@ -638,7 +744,24 @@ type RecordPreviewSection = {
|
|
|
638
744
|
key: string;
|
|
639
745
|
label: string;
|
|
640
746
|
count: number;
|
|
641
|
-
content?:
|
|
747
|
+
content?: React.ReactNode;
|
|
748
|
+
};
|
|
749
|
+
/** One tab of the panel's own mini detail view (a "tabs" capability with no
|
|
750
|
+
* your-moon/crisp equivalent -- crisp's own peek only ever shows Highlights
|
|
751
|
+
* + Activity + sections, never a tab bar). Built on crispy-seed's own
|
|
752
|
+
* `Tabs` primitive (`../Tabs`, itself built on seed's `tabs` recipe/
|
|
753
|
+
* tokens) rather than a hand-rolled tab strip, so it matches every other
|
|
754
|
+
* tabbed surface in this package. `content` is only rendered lazily in the
|
|
755
|
+
* sense that `Tabs.Content` already handles (hidden, not unmounted, once a
|
|
756
|
+
* tab has been visited) -- see `Tabs.tsx`. */
|
|
757
|
+
type RecordPreviewTab = {
|
|
758
|
+
key: string;
|
|
759
|
+
label: React.ReactNode;
|
|
760
|
+
content: React.ReactNode;
|
|
761
|
+
/** Rendered right after `label` inside the tab trigger, e.g. an unread
|
|
762
|
+
* count -- purely presentational, this component attaches no meaning to
|
|
763
|
+
* it. */
|
|
764
|
+
badge?: React.ReactNode;
|
|
642
765
|
};
|
|
643
766
|
/** The record this panel previews. Only `name` is read directly here --
|
|
644
767
|
* everything else the panel shows comes from `highlights`/`activity`/
|
|
@@ -650,7 +773,7 @@ type RecordPreviewRecord = {
|
|
|
650
773
|
name?: string;
|
|
651
774
|
[key: string]: unknown;
|
|
652
775
|
};
|
|
653
|
-
type RecordPreviewProps = Omit<
|
|
776
|
+
type RecordPreviewProps = Omit<React.ComponentPropsWithoutRef<"div">, "children" | "title" | "onResize"> & {
|
|
654
777
|
/** Whether the panel is mounted/visible. */
|
|
655
778
|
open: boolean;
|
|
656
779
|
onClose: () => void;
|
|
@@ -671,7 +794,7 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
671
794
|
nextRecordLabel?: string;
|
|
672
795
|
/** "2 of 37 in All Companies" (your-moon/crisp#413) -- a single
|
|
673
796
|
* pre-formatted string; omit for no counter at all. */
|
|
674
|
-
counterLabel?:
|
|
797
|
+
counterLabel?: React.ReactNode;
|
|
675
798
|
/**
|
|
676
799
|
* Lets a person drag the panel wider or narrower from its own left edge --
|
|
677
800
|
* this port reuses `ResizablePanel`'s own handle (`side="right"`, whose
|
|
@@ -687,7 +810,7 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
687
810
|
minWidth?: number;
|
|
688
811
|
maxWidth?: number;
|
|
689
812
|
/** The panel's heading, and so its accessible name. Defaults to `record.name`. */
|
|
690
|
-
title?:
|
|
813
|
+
title?: React.ReactNode;
|
|
691
814
|
/** Avatar image URL beside the title. Omit for an initials tile built from
|
|
692
815
|
* `record.name`'s first character. */
|
|
693
816
|
avatar?: string;
|
|
@@ -696,18 +819,49 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
696
819
|
record: RecordPreviewRecord | null;
|
|
697
820
|
/** Heading above the highlight cards (default "Highlights"). Omit the
|
|
698
821
|
* whole section by omitting `highlights`. */
|
|
699
|
-
highlightsLabel?:
|
|
822
|
+
highlightsLabel?: React.ReactNode;
|
|
700
823
|
highlights?: RecordPreviewHighlight[];
|
|
701
824
|
/** Heading above the activity feed (default "Activity"). */
|
|
702
|
-
activityLabel?:
|
|
703
|
-
viewAllActivityLabel?:
|
|
825
|
+
activityLabel?: React.ReactNode;
|
|
826
|
+
viewAllActivityLabel?: React.ReactNode;
|
|
704
827
|
onViewAllActivity?: () => void;
|
|
705
|
-
activity?:
|
|
828
|
+
activity?: React.ReactNode;
|
|
706
829
|
/** Collapsed sections below Activity (your-moon/crisp#413). Omit for no
|
|
707
830
|
* sections at all. */
|
|
708
831
|
sections?: RecordPreviewSection[];
|
|
832
|
+
/**
|
|
833
|
+
* A "mini detail view" -- renders a seed-idiomatic tab bar under the
|
|
834
|
+
* header instead of (or ahead of) the plain Highlights/Activity/sections
|
|
835
|
+
* layout. Omit for no tabs at all (the default; existing consumers are
|
|
836
|
+
* unaffected). When `highlights`/`activity`/`sections` are ALSO given
|
|
837
|
+
* alongside `tabs`, they're combined rather than dropped: an extra
|
|
838
|
+
* `overviewTabLabel` tab (default "Overview") is prepended, ahead of
|
|
839
|
+
* these `tabs`, containing exactly what the non-tabs layout would have
|
|
840
|
+
* rendered -- so a consumer moving to tabs doesn't have to re-author its
|
|
841
|
+
* existing overview content as a tab by hand.
|
|
842
|
+
*/
|
|
843
|
+
tabs?: RecordPreviewTab[];
|
|
844
|
+
/** Controlled active tab key. Pass with `onTabChange`; omit for
|
|
845
|
+
* uncontrolled (`defaultActiveTab`). Only meaningful with `tabs`. */
|
|
846
|
+
activeTab?: string;
|
|
847
|
+
/** Initial active tab key when uncontrolled. Defaults to the first tab
|
|
848
|
+
* (the synthesized "Overview" tab when highlights/activity/sections are
|
|
849
|
+
* combined in, otherwise the first entry of `tabs` itself). */
|
|
850
|
+
defaultActiveTab?: string;
|
|
851
|
+
onTabChange?: (key: string) => void;
|
|
852
|
+
/** Label for the synthesized overview tab -- see `tabs`'s own doc
|
|
853
|
+
* comment. @default "Overview" */
|
|
854
|
+
overviewTabLabel?: React.ReactNode;
|
|
709
855
|
/** Rendered below the panel's content, e.g. an Edit button. */
|
|
710
|
-
footer?:
|
|
856
|
+
footer?: React.ReactNode;
|
|
857
|
+
/**
|
|
858
|
+
* An optional dimming backdrop behind the panel -- OFF by default (this
|
|
859
|
+
* is a peek, not a modal: Attio's own peek never dims the table it
|
|
860
|
+
* floats over). Forwarded to `ResizablePanel`'s own `backdrop`; clicking
|
|
861
|
+
* it calls `onClose`, same as the panel's own close button.
|
|
862
|
+
* @default false
|
|
863
|
+
*/
|
|
864
|
+
backdrop?: boolean;
|
|
711
865
|
className?: string;
|
|
712
866
|
};
|
|
713
867
|
/**
|
|
@@ -716,14 +870,44 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
716
870
|
* `RecordPanel` (`product/recordpanel/`), built ON `ResizablePanel`
|
|
717
871
|
* (`side="right" floating`) rather than crisp's own duplicate absolute-
|
|
718
872
|
* positioning/slide-in/resize-handle implementation -- the outer shell (the
|
|
719
|
-
*
|
|
873
|
+
* enter/exit keyframe animation, the full-height overlay, the drag handle
|
|
720
874
|
* itself) all come from that primitive; this component only renders the
|
|
721
875
|
* CONTENT inside it.
|
|
876
|
+
*
|
|
877
|
+
* OVERLAY, not docked: `floating` (on the `ResizablePanel` this is built on)
|
|
878
|
+
* now means a real `position: absolute` overlay that reserves ZERO layout
|
|
879
|
+
* width -- opening this panel never shrinks or reflows a table beside it
|
|
880
|
+
* (your-moon/crisp#448 reversed an earlier in-flow/docked attempt at this
|
|
881
|
+
* exact spot, reported live as "table's action buttons moving"). Because of
|
|
882
|
+
* that, THIS COMPONENT OWNS ITS OWN POSITIONING -- a consumer does not wrap
|
|
883
|
+
* it in a flex row with the table; it renders `<RecordPreview>` as an
|
|
884
|
+
* ordinary sibling of the table. The one requirement: the shared parent
|
|
885
|
+
* (the table region's own wrapper) must itself be a positioned element
|
|
886
|
+
* (typically `position: relative`) with a real height, since that's the
|
|
887
|
+
* containing block this panel's `inset: 0` resolves against. See
|
|
888
|
+
* `DataTable.stories.tsx`'s own Showcase for the pattern:
|
|
889
|
+
*
|
|
890
|
+
* ```tsx
|
|
891
|
+
* <div style={{ position: "relative", flex: 1, minHeight: 0 }}>
|
|
892
|
+
* <DataTable style={{ width: "100%", height: "100%" }} ... />
|
|
893
|
+
* <RecordPreview open={open} record={record} onClose={onClose} ... />
|
|
894
|
+
* </div>
|
|
895
|
+
* ```
|
|
896
|
+
*
|
|
897
|
+
* Enter/exit: closing this panel is a state change (`open` -> false) that
|
|
898
|
+
* typically clears `record` in the SAME update (see the DataTable story's
|
|
899
|
+
* own `onClose={() => setPreviewRow(null)}`), so by the time an exit
|
|
900
|
+
* animation should play, the values this component would render are
|
|
901
|
+
* already gone. `usePresence` (`@seed-design/react-presence`, the same
|
|
902
|
+
* idiom Dialog/Drawer already use for their own floating layers) keeps the
|
|
903
|
+
* tree mounted for exactly the exit animation's duration; the snapshot
|
|
904
|
+
* below keeps the LAST visible props around for that same window, since
|
|
905
|
+
* without it the panel would animate out empty.
|
|
722
906
|
*/
|
|
723
|
-
declare function RecordPreview(
|
|
907
|
+
declare function RecordPreview(props: RecordPreviewProps): react_jsx_runtime.JSX.Element | null;
|
|
724
908
|
declare namespace RecordPreview {
|
|
725
909
|
var displayName: string;
|
|
726
910
|
}
|
|
727
911
|
|
|
728
912
|
export { DataTable, DataTableViewsControl, RecordPreview, ResizablePanel };
|
|
729
|
-
export type { DataTableColumn, DataTableColumnKind, DataTableProps, DataTableView, DataTableViewState, DataTableViewsControlProps, RecordPreviewHighlight, RecordPreviewProps, RecordPreviewRecord, RecordPreviewSection, ResizablePanelHandleVariant, ResizablePanelProps, ResizablePanelSide, ToolbarFilter, ToolbarFilterOp, ToolbarSort, ToolbarSortDirection };
|
|
913
|
+
export type { DataTableColumn, DataTableColumnKind, DataTableProps, DataTableView, DataTableViewState, DataTableViewsControlProps, RecordPreviewHighlight, RecordPreviewProps, RecordPreviewRecord, RecordPreviewSection, RecordPreviewTab, ResizablePanelHandleVariant, ResizablePanelProps, ResizablePanelSide, ToolbarFilter, ToolbarFilterOp, ToolbarSort, ToolbarSortDirection };
|