@crispy-seed/data-table 0.8.0 → 0.10.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 +116 -2
- package/dist/data-table-recipe.layered.css +121 -1
- package/dist/index.cjs +3506 -320
- package/dist/index.d.ts +159 -26
- package/dist/index.js +3508 -322
- package/dist/record-preview-recipe.css +16 -0
- package/dist/record-preview-recipe.layered.css +19 -0
- package/dist/resizable-panel-recipe.css +38 -10
- package/dist/resizable-panel-recipe.layered.css +42 -10
- package/dist/styles.css +182 -11
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -114,7 +114,7 @@ interface UseDataTableViewsProps {
|
|
|
114
114
|
storageKey?: string;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
type DataTableCellType = "text" | "entity" | "url" | "email" | "tags" | "status" | "number" | "currency" | "date" | "datetime" | "rating" | "checkbox";
|
|
117
|
+
type DataTableCellType = "text" | "entity" | "url" | "email" | "tags" | "status" | "number" | "currency" | "date" | "datetime" | "rating" | "checkbox" | "chip" | "chip-list";
|
|
118
118
|
|
|
119
119
|
/** A `select`/`reference`/`actor` editor's own choice list -- `value`/`label` are
|
|
120
120
|
* required (the committed string and what the row reads), `avatar` is read only by
|
|
@@ -269,6 +269,14 @@ interface DataTableColumn<TRow> {
|
|
|
269
269
|
onOpenPreview?: (row: TRow) => void;
|
|
270
270
|
/** `onOpenPreview` 아이콘의 aria-label입니다. @default "Open preview" */
|
|
271
271
|
openPreviewLabel?: string;
|
|
272
|
+
/**
|
|
273
|
+
* 셀 텍스트 옆에 고정으로 붙는 접미(trailing) 아이콘입니다 (예: 링크 열의 외부 링크
|
|
274
|
+
* 아이콘, 위치 열의 핀 아이콘) -- 텍스트가 길어져도 이 아이콘은 잘리거나 사라지지
|
|
275
|
+
* 않습니다 (cells.tsx의 `CellWithSuffix`: 텍스트 쪽만 `flex:1;min-width:0`로
|
|
276
|
+
* 줄임표 처리되고, 아이콘은 `flex-shrink:0`). `type: "text"`(기본)와 `"url"`/
|
|
277
|
+
* `"email"` 열에서 동작합니다.
|
|
278
|
+
*/
|
|
279
|
+
suffixIcon?: (row: TRow) => react.ReactNode;
|
|
272
280
|
}
|
|
273
281
|
interface DataTableProps<TRow extends {
|
|
274
282
|
id: string;
|
|
@@ -542,13 +550,42 @@ type ResizablePanelProps = Omit<react.ComponentPropsWithoutRef<"div">, "children
|
|
|
542
550
|
*/
|
|
543
551
|
max?: number | string;
|
|
544
552
|
/**
|
|
545
|
-
*
|
|
546
|
-
*
|
|
547
|
-
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
553
|
+
* Layout model. "docked" (default) is IN-FLOW: `spacer` reserves the
|
|
554
|
+
* panel's real width, shrinking a `flex: 1` sibling beside it (e.g. a
|
|
555
|
+
* table), flush with a hairline border -- unchanged since this
|
|
556
|
+
* primitive's own first version.
|
|
557
|
+
*
|
|
558
|
+
* "floating" is a true OVERLAY, not a bigger gutter on the docked look:
|
|
559
|
+
* this component's own outer element takes itself OUT of flow entirely
|
|
560
|
+
* (`position: absolute; inset: 0`) and renders no `spacer` at all -- it
|
|
561
|
+
* reserves ZERO layout width, so a sibling beside it (a table) never
|
|
562
|
+
* shrinks or reflows when this opens or resizes. The panel itself is
|
|
563
|
+
* pinned to one edge of that `inset: 0` box, spans its full height, and
|
|
564
|
+
* only the corners facing INTO the container are rounded (a left-edge
|
|
565
|
+
* shadow for `side="right"`, mirrored for `side="left"`) -- this is
|
|
566
|
+
* `RecordPreview`'s own peek panel (your-moon/crisp#448 reversed a
|
|
567
|
+
* docked/reflow attempt at this exact spot: "table's action buttons
|
|
568
|
+
* moving" when the panel opened).
|
|
569
|
+
*
|
|
570
|
+
* Because the outer element is now `position: absolute`, the consumer's
|
|
571
|
+
* own immediate parent (wherever this component -- or `RecordPreview` --
|
|
572
|
+
* is rendered) MUST itself be a positioned element (typically
|
|
573
|
+
* `position: relative`) with a real height, e.g. the table region's own
|
|
574
|
+
* wrapper div. No flex-row wrapper is needed or wanted: the table can be
|
|
575
|
+
* an ordinary 100%-width block and this panel a plain sibling.
|
|
550
576
|
*/
|
|
551
577
|
floating?: boolean;
|
|
578
|
+
/**
|
|
579
|
+
* An optional dimming backdrop behind a `floating` panel, covering the
|
|
580
|
+
* same `inset: 0` container -- OFF by default: this is a peek panel, not
|
|
581
|
+
* a modal, and Attio's own peek never dims the table it floats over.
|
|
582
|
+
* Meaningful only together with `floating`; ignored otherwise.
|
|
583
|
+
* @default false
|
|
584
|
+
*/
|
|
585
|
+
backdrop?: boolean;
|
|
586
|
+
/** Fires when the optional `backdrop` is clicked. Typically wired to the
|
|
587
|
+
* same handler as the panel's own close control. */
|
|
588
|
+
onBackdropClick?: () => void;
|
|
552
589
|
/** Resize-handle geometry -- "panel" (default) or "column" (table edges). */
|
|
553
590
|
handleVariant?: ResizablePanelHandleVariant;
|
|
554
591
|
/**
|
|
@@ -587,19 +624,18 @@ type ResizablePanelProps = Omit<react.ComponentPropsWithoutRef<"div">, "children
|
|
|
587
624
|
children?: react.ReactNode;
|
|
588
625
|
};
|
|
589
626
|
/**
|
|
590
|
-
* An adjustable-panel primitive
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
*
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
*
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
* recipe classes on top of it.
|
|
627
|
+
* An adjustable-panel primitive with two layout models (`floating`'s own doc
|
|
628
|
+
* comment above has the full contrast). Docked: a `spacer` reserves layout
|
|
629
|
+
* width and the panel overlays exactly that reservation, so a resize drag
|
|
630
|
+
* never causes a reflow glitch on the rest of the layout. Floating: no
|
|
631
|
+
* spacer at all -- this component's own outer element becomes a
|
|
632
|
+
* `position: absolute; inset: 0` overlay reserving zero width, with the
|
|
633
|
+
* panel itself pinned to one edge and spanning the full height of that box.
|
|
634
|
+
* Drag the edge handle to resize; constraints are CSS `min-width`/
|
|
635
|
+
* `max-width`, never re-clamped in JS. Ported from your-moon/crisp's
|
|
636
|
+
* `ResizablePanel` (`components/resizablepanel/`); state/drag behavior
|
|
637
|
+
* lives in `useResizablePanel` (`@seed-design/react-resizable-panel`), this
|
|
638
|
+
* component owns the DOM + recipe classes on top of it.
|
|
603
639
|
*/
|
|
604
640
|
declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "onResize"> & {
|
|
605
641
|
/** Which edge of its container the panel is anchored to. @default "left" */
|
|
@@ -621,13 +657,42 @@ declare const ResizablePanel: react.ForwardRefExoticComponent<Omit<Omit<react.De
|
|
|
621
657
|
*/
|
|
622
658
|
max?: number | string;
|
|
623
659
|
/**
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
*
|
|
660
|
+
* Layout model. "docked" (default) is IN-FLOW: `spacer` reserves the
|
|
661
|
+
* panel's real width, shrinking a `flex: 1` sibling beside it (e.g. a
|
|
662
|
+
* table), flush with a hairline border -- unchanged since this
|
|
663
|
+
* primitive's own first version.
|
|
664
|
+
*
|
|
665
|
+
* "floating" is a true OVERLAY, not a bigger gutter on the docked look:
|
|
666
|
+
* this component's own outer element takes itself OUT of flow entirely
|
|
667
|
+
* (`position: absolute; inset: 0`) and renders no `spacer` at all -- it
|
|
668
|
+
* reserves ZERO layout width, so a sibling beside it (a table) never
|
|
669
|
+
* shrinks or reflows when this opens or resizes. The panel itself is
|
|
670
|
+
* pinned to one edge of that `inset: 0` box, spans its full height, and
|
|
671
|
+
* only the corners facing INTO the container are rounded (a left-edge
|
|
672
|
+
* shadow for `side="right"`, mirrored for `side="left"`) -- this is
|
|
673
|
+
* `RecordPreview`'s own peek panel (your-moon/crisp#448 reversed a
|
|
674
|
+
* docked/reflow attempt at this exact spot: "table's action buttons
|
|
675
|
+
* moving" when the panel opened).
|
|
676
|
+
*
|
|
677
|
+
* Because the outer element is now `position: absolute`, the consumer's
|
|
678
|
+
* own immediate parent (wherever this component -- or `RecordPreview` --
|
|
679
|
+
* is rendered) MUST itself be a positioned element (typically
|
|
680
|
+
* `position: relative`) with a real height, e.g. the table region's own
|
|
681
|
+
* wrapper div. No flex-row wrapper is needed or wanted: the table can be
|
|
682
|
+
* an ordinary 100%-width block and this panel a plain sibling.
|
|
629
683
|
*/
|
|
630
684
|
floating?: boolean;
|
|
685
|
+
/**
|
|
686
|
+
* An optional dimming backdrop behind a `floating` panel, covering the
|
|
687
|
+
* same `inset: 0` container -- OFF by default: this is a peek panel, not
|
|
688
|
+
* a modal, and Attio's own peek never dims the table it floats over.
|
|
689
|
+
* Meaningful only together with `floating`; ignored otherwise.
|
|
690
|
+
* @default false
|
|
691
|
+
*/
|
|
692
|
+
backdrop?: boolean;
|
|
693
|
+
/** Fires when the optional `backdrop` is clicked. Typically wired to the
|
|
694
|
+
* same handler as the panel's own close control. */
|
|
695
|
+
onBackdropClick?: () => void;
|
|
631
696
|
/** Resize-handle geometry -- "panel" (default) or "column" (table edges). */
|
|
632
697
|
handleVariant?: ResizablePanelHandleVariant;
|
|
633
698
|
/**
|
|
@@ -689,6 +754,23 @@ type RecordPreviewSection = {
|
|
|
689
754
|
count: number;
|
|
690
755
|
content?: react.ReactNode;
|
|
691
756
|
};
|
|
757
|
+
/** One tab of the panel's own mini detail view (a "tabs" capability with no
|
|
758
|
+
* your-moon/crisp equivalent -- crisp's own peek only ever shows Highlights
|
|
759
|
+
* + Activity + sections, never a tab bar). Built on crispy-seed's own
|
|
760
|
+
* `Tabs` primitive (`../Tabs`, itself built on seed's `tabs` recipe/
|
|
761
|
+
* tokens) rather than a hand-rolled tab strip, so it matches every other
|
|
762
|
+
* tabbed surface in this package. `content` is only rendered lazily in the
|
|
763
|
+
* sense that `Tabs.Content` already handles (hidden, not unmounted, once a
|
|
764
|
+
* tab has been visited) -- see `Tabs.tsx`. */
|
|
765
|
+
type RecordPreviewTab = {
|
|
766
|
+
key: string;
|
|
767
|
+
label: react.ReactNode;
|
|
768
|
+
content: react.ReactNode;
|
|
769
|
+
/** Rendered right after `label` inside the tab trigger, e.g. an unread
|
|
770
|
+
* count -- purely presentational, this component attaches no meaning to
|
|
771
|
+
* it. */
|
|
772
|
+
badge?: react.ReactNode;
|
|
773
|
+
};
|
|
692
774
|
/** The record this panel previews. Only `name` is read directly here --
|
|
693
775
|
* everything else the panel shows comes from `highlights`/`activity`/
|
|
694
776
|
* `sections`, the consumer's own data. Unlike crisp's own `RecordPanel`
|
|
@@ -755,8 +837,39 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
755
837
|
/** Collapsed sections below Activity (your-moon/crisp#413). Omit for no
|
|
756
838
|
* sections at all. */
|
|
757
839
|
sections?: RecordPreviewSection[];
|
|
840
|
+
/**
|
|
841
|
+
* A "mini detail view" -- renders a seed-idiomatic tab bar under the
|
|
842
|
+
* header instead of (or ahead of) the plain Highlights/Activity/sections
|
|
843
|
+
* layout. Omit for no tabs at all (the default; existing consumers are
|
|
844
|
+
* unaffected). When `highlights`/`activity`/`sections` are ALSO given
|
|
845
|
+
* alongside `tabs`, they're combined rather than dropped: an extra
|
|
846
|
+
* `overviewTabLabel` tab (default "Overview") is prepended, ahead of
|
|
847
|
+
* these `tabs`, containing exactly what the non-tabs layout would have
|
|
848
|
+
* rendered -- so a consumer moving to tabs doesn't have to re-author its
|
|
849
|
+
* existing overview content as a tab by hand.
|
|
850
|
+
*/
|
|
851
|
+
tabs?: RecordPreviewTab[];
|
|
852
|
+
/** Controlled active tab key. Pass with `onTabChange`; omit for
|
|
853
|
+
* uncontrolled (`defaultActiveTab`). Only meaningful with `tabs`. */
|
|
854
|
+
activeTab?: string;
|
|
855
|
+
/** Initial active tab key when uncontrolled. Defaults to the first tab
|
|
856
|
+
* (the synthesized "Overview" tab when highlights/activity/sections are
|
|
857
|
+
* combined in, otherwise the first entry of `tabs` itself). */
|
|
858
|
+
defaultActiveTab?: string;
|
|
859
|
+
onTabChange?: (key: string) => void;
|
|
860
|
+
/** Label for the synthesized overview tab -- see `tabs`'s own doc
|
|
861
|
+
* comment. @default "Overview" */
|
|
862
|
+
overviewTabLabel?: react.ReactNode;
|
|
758
863
|
/** Rendered below the panel's content, e.g. an Edit button. */
|
|
759
864
|
footer?: react.ReactNode;
|
|
865
|
+
/**
|
|
866
|
+
* An optional dimming backdrop behind the panel -- OFF by default (this
|
|
867
|
+
* is a peek, not a modal: Attio's own peek never dims the table it
|
|
868
|
+
* floats over). Forwarded to `ResizablePanel`'s own `backdrop`; clicking
|
|
869
|
+
* it calls `onClose`, same as the panel's own close button.
|
|
870
|
+
* @default false
|
|
871
|
+
*/
|
|
872
|
+
backdrop?: boolean;
|
|
760
873
|
className?: string;
|
|
761
874
|
};
|
|
762
875
|
/**
|
|
@@ -765,10 +878,30 @@ type RecordPreviewProps = Omit<react.ComponentPropsWithoutRef<"div">, "children"
|
|
|
765
878
|
* `RecordPanel` (`product/recordpanel/`), built ON `ResizablePanel`
|
|
766
879
|
* (`side="right" floating`) rather than crisp's own duplicate absolute-
|
|
767
880
|
* positioning/slide-in/resize-handle implementation -- the outer shell (the
|
|
768
|
-
* enter/exit keyframe animation, the
|
|
881
|
+
* enter/exit keyframe animation, the full-height overlay, the drag handle
|
|
769
882
|
* itself) all come from that primitive; this component only renders the
|
|
770
883
|
* CONTENT inside it.
|
|
771
884
|
*
|
|
885
|
+
* OVERLAY, not docked: `floating` (on the `ResizablePanel` this is built on)
|
|
886
|
+
* now means a real `position: absolute` overlay that reserves ZERO layout
|
|
887
|
+
* width -- opening this panel never shrinks or reflows a table beside it
|
|
888
|
+
* (your-moon/crisp#448 reversed an earlier in-flow/docked attempt at this
|
|
889
|
+
* exact spot, reported live as "table's action buttons moving"). Because of
|
|
890
|
+
* that, THIS COMPONENT OWNS ITS OWN POSITIONING -- a consumer does not wrap
|
|
891
|
+
* it in a flex row with the table; it renders `<RecordPreview>` as an
|
|
892
|
+
* ordinary sibling of the table. The one requirement: the shared parent
|
|
893
|
+
* (the table region's own wrapper) must itself be a positioned element
|
|
894
|
+
* (typically `position: relative`) with a real height, since that's the
|
|
895
|
+
* containing block this panel's `inset: 0` resolves against. See
|
|
896
|
+
* `DataTable.stories.tsx`'s own Showcase for the pattern:
|
|
897
|
+
*
|
|
898
|
+
* ```tsx
|
|
899
|
+
* <div style={{ position: "relative", flex: 1, minHeight: 0 }}>
|
|
900
|
+
* <DataTable style={{ width: "100%", height: "100%" }} ... />
|
|
901
|
+
* <RecordPreview open={open} record={record} onClose={onClose} ... />
|
|
902
|
+
* </div>
|
|
903
|
+
* ```
|
|
904
|
+
*
|
|
772
905
|
* Enter/exit: closing this panel is a state change (`open` -> false) that
|
|
773
906
|
* typically clears `record` in the SAME update (see the DataTable story's
|
|
774
907
|
* own `onClose={() => setPreviewRow(null)}`), so by the time an exit
|
|
@@ -785,4 +918,4 @@ declare namespace RecordPreview {
|
|
|
785
918
|
}
|
|
786
919
|
|
|
787
920
|
export { DataTable, DataTableViewsControl, RecordPreview, ResizablePanel };
|
|
788
|
-
export type { DataTableColumn, DataTableColumnKind, DataTableProps, DataTableView, DataTableViewState, DataTableViewsControlProps, RecordPreviewHighlight, RecordPreviewProps, RecordPreviewRecord, RecordPreviewSection, ResizablePanelHandleVariant, ResizablePanelProps, ResizablePanelSide, ToolbarFilter, ToolbarFilterOp, ToolbarSort, ToolbarSortDirection };
|
|
921
|
+
export type { DataTableColumn, DataTableColumnKind, DataTableProps, DataTableView, DataTableViewState, DataTableViewsControlProps, RecordPreviewHighlight, RecordPreviewProps, RecordPreviewRecord, RecordPreviewSection, RecordPreviewTab, ResizablePanelHandleVariant, ResizablePanelProps, ResizablePanelSide, ToolbarFilter, ToolbarFilterOp, ToolbarSort, ToolbarSortDirection };
|