@crispy-seed/data-table 0.9.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 +109 -0
- package/dist/data-table-recipe.layered.css +118 -0
- package/dist/index.cjs +491 -35
- package/dist/index.d.ts +50 -42
- package/dist/index.js +492 -36
- package/dist/styles.css +118 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ function __insertCSS(code) {
|
|
|
10
10
|
|
|
11
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
12
12
|
import * as React from 'react';
|
|
13
|
-
import React__default, { forwardRef, useCallback,
|
|
13
|
+
import React__default, { forwardRef, useCallback, useState, useMemo, useRef, useEffect, createContext, useContext, useId } from 'react';
|
|
14
14
|
import { dataAttr, elementProps, ariaAttr, mergeProps as mergeProps$1, buttonProps } from '@seed-design/dom-utils';
|
|
15
15
|
import { checkbox } from '@seed-design/css/recipes/checkbox';
|
|
16
16
|
import { checkmark } from '@seed-design/css/recipes/checkmark';
|
|
@@ -882,6 +882,40 @@ function useDataTableColumnCalc(props) {
|
|
|
882
882
|
};
|
|
883
883
|
}
|
|
884
884
|
|
|
885
|
+
function sameCell$1(a, id, key) {
|
|
886
|
+
return a !== null && a.id === id && a.key === key;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Tracks which single cell (if any) is showing its "show full content" overlay
|
|
890
|
+
* (DATATABLE-ATTIO-SPEC.md's cell-expand feature, #12) for the READ-ONLY case -- a
|
|
891
|
+
* non-`editable` column with truncated content, which has nothing to commit and so
|
|
892
|
+
* no reason to go through `useDataTableEdit`'s `editingCell`. An `editable` column's
|
|
893
|
+
* own truncated-cell overlay instead reuses `useDataTableEdit`'s `startEdit`/
|
|
894
|
+
* `editingCell` directly (the styled layer's `body-cells.tsx` picks which of the two
|
|
895
|
+
* a given activation opens) -- "for editable cells it's the editor" per the spec,
|
|
896
|
+
* not a second parallel state machine duplicating what editing already tracks.
|
|
897
|
+
*
|
|
898
|
+
* Only one cell can be peeked at a time, the same single-cell shape
|
|
899
|
+
* `useDataTableEdit`'s `editingCell` already uses -- this table has no multi-cell
|
|
900
|
+
* expand any more than it has multi-cell edit.
|
|
901
|
+
*/ function useDataTableCellPeek() {
|
|
902
|
+
const [peekedCell, setPeekedCell] = useState(null);
|
|
903
|
+
const isPeeking = useCallback((id, key)=>sameCell$1(peekedCell, id, key), [
|
|
904
|
+
peekedCell
|
|
905
|
+
]);
|
|
906
|
+
const openPeek = useCallback((id, key)=>setPeekedCell({
|
|
907
|
+
id,
|
|
908
|
+
key
|
|
909
|
+
}), []);
|
|
910
|
+
const closePeek = useCallback(()=>setPeekedCell(null), []);
|
|
911
|
+
return {
|
|
912
|
+
peekedCell,
|
|
913
|
+
isPeeking,
|
|
914
|
+
openPeek,
|
|
915
|
+
closePeek
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
|
|
885
919
|
// Select's `dom.ts` reads state off REAL rendered elements (aria-disabled, data-value)
|
|
886
920
|
// because its options register asynchronously through a floating-ui list and the DOM
|
|
887
921
|
// is the one thing always in sync with `elementsRef`. DataTable's selection has no
|
|
@@ -1897,6 +1931,11 @@ function useDataTable(props) {
|
|
|
1897
1931
|
const columnCalc = useDataTableColumnCalc(props);
|
|
1898
1932
|
const scroll = useDataTableScroll();
|
|
1899
1933
|
const edit = useDataTableEdit(props);
|
|
1934
|
+
// Feature C (#12) -- which single cell (if any) is showing its read-only "show
|
|
1935
|
+
// full content" overlay. Independent of `edit` above -- see
|
|
1936
|
+
// `useDataTableCellPeek.ts`'s own doc comment for why an `editable` column's
|
|
1937
|
+
// truncated-cell overlay reuses `edit` instead of this.
|
|
1938
|
+
const peek = useDataTableCellPeek();
|
|
1900
1939
|
// Wired to `scroll`'s own scroll-container ref (not a fresh one of its own) so a
|
|
1901
1940
|
// BOUNDED table's auto-load triggers off its own internal scroll, not the
|
|
1902
1941
|
// browsing viewport -- see useDataTableInfiniteScroll.ts's own doc comment.
|
|
@@ -1914,6 +1953,7 @@ function useDataTable(props) {
|
|
|
1914
1953
|
...columnCalc,
|
|
1915
1954
|
...scroll,
|
|
1916
1955
|
...edit,
|
|
1956
|
+
...peek,
|
|
1917
1957
|
...infiniteScroll,
|
|
1918
1958
|
rootProps: elementProps({
|
|
1919
1959
|
role: "table"
|
|
@@ -2554,6 +2594,41 @@ function toneFor(value) {
|
|
|
2554
2594
|
}
|
|
2555
2595
|
return BADGE_TONES[hash % BADGE_TONES.length];
|
|
2556
2596
|
}
|
|
2597
|
+
// Feature A/B (#9/#8) -- Attio's own flat 12-swatch chip palette, ported from
|
|
2598
|
+
// crisp's `tokens/palette.ts` (`tagSwatch1..12`, measured live off Attio) rather
|
|
2599
|
+
// than seed's own 6-tone `Badge` (`BADGE_TONES` above): a swatch, unlike a Badge
|
|
2600
|
+
// tone, has no ring/border and its ink is a FLAT black on every swatch (crisp's own
|
|
2601
|
+
// `tagSwatchInk`, `#000000` -- every swatch background is already a pale tint, so
|
|
2602
|
+
// one dark foreground reads on all 12), not a per-tone contrast color. No seed token
|
|
2603
|
+
// lands on any of these 12 hex values, so -- same footnote as the qvism recipe's own
|
|
2604
|
+
// `ATTIO_BRAND_BLUE`/`RATING_FILLED` literals -- they stay literal here too.
|
|
2605
|
+
const CHIP_SWATCHES = [
|
|
2606
|
+
"#fff3cc",
|
|
2607
|
+
"#f4fbcb",
|
|
2608
|
+
"#fdf7c4",
|
|
2609
|
+
"#feecf3",
|
|
2610
|
+
"#e0fced",
|
|
2611
|
+
"#ddf7ff",
|
|
2612
|
+
"#f6f7f7",
|
|
2613
|
+
"#ffebeb",
|
|
2614
|
+
"#feeee1",
|
|
2615
|
+
"#e5eeff",
|
|
2616
|
+
"#f5f0ff",
|
|
2617
|
+
"#fdedff"
|
|
2618
|
+
];
|
|
2619
|
+
const CHIP_SWATCH_INK = "#000000";
|
|
2620
|
+
/** Same stable multiply-and-add hash `toneFor` above already uses over seed's 6
|
|
2621
|
+
* Badge tones, just over this file's own 12-swatch palette instead -- same value,
|
|
2622
|
+
* same swatch, every render (crisp's own `toneFor`, `datatable.tsx`). */ function swatchIndexFor(value) {
|
|
2623
|
+
let hash = 0;
|
|
2624
|
+
for(let index = 0; index < value.length; index++){
|
|
2625
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
2626
|
+
}
|
|
2627
|
+
return hash % CHIP_SWATCHES.length;
|
|
2628
|
+
}
|
|
2629
|
+
function swatchColorFor(value) {
|
|
2630
|
+
return CHIP_SWATCHES[swatchIndexFor(value)];
|
|
2631
|
+
}
|
|
2557
2632
|
function initialsFor(name) {
|
|
2558
2633
|
const parts = name.trim().split(/\s+/);
|
|
2559
2634
|
return ((parts[0]?.[0] ?? "") + (parts[1]?.[0] ?? "")).toUpperCase() || "?";
|
|
@@ -2668,11 +2743,89 @@ function StatusCell({ value }) {
|
|
|
2668
2743
|
children: status
|
|
2669
2744
|
});
|
|
2670
2745
|
}
|
|
2671
|
-
|
|
2746
|
+
/** One swatch chip -- `style` carries the per-value background/ink (computed by
|
|
2747
|
+
* `swatchColorFor`/`CHIP_SWATCH_INK` above) since neither is a recipe token, the
|
|
2748
|
+
* same "literal color as a computed prop" call `RatingCell`'s star fill already
|
|
2749
|
+
* makes. Shared by `ChipCell` (Feature A, single value) and `ChipListCell`/
|
|
2750
|
+
* editors.tsx's `ChipListEditor` (Feature B, multi value) so all three chip
|
|
2751
|
+
* renderings stay byte-identical. */ function SwatchChip({ value, className, children }) {
|
|
2752
|
+
return /*#__PURE__*/ jsxs("span", {
|
|
2753
|
+
className: className,
|
|
2754
|
+
style: {
|
|
2755
|
+
backgroundColor: swatchColorFor(value),
|
|
2756
|
+
color: CHIP_SWATCH_INK
|
|
2757
|
+
},
|
|
2758
|
+
children: [
|
|
2759
|
+
value,
|
|
2760
|
+
children
|
|
2761
|
+
]
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
/** `type: "chip"` (Feature A, #9) -- a single value rendered as one colored chip,
|
|
2765
|
+
* the color derived deterministically from the value string (`swatchColorFor`):
|
|
2766
|
+
* same value, same color, every render, every column. For a column like provider/
|
|
2767
|
+
* tenant/vendor/status/select where a plain `Badge` (seed's 6-tone `status`/`tags`
|
|
2768
|
+
* types above) doesn't need to be color-STABLE per value -- this one does. */ function ChipCell({ value, className }) {
|
|
2769
|
+
const text = value == null ? "" : String(value);
|
|
2770
|
+
if (!text) return null;
|
|
2771
|
+
return /*#__PURE__*/ jsx(SwatchChip, {
|
|
2772
|
+
value: text,
|
|
2773
|
+
className: className
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2776
|
+
/** `type: "chip-list"`, READ-ONLY (Feature B, #8) -- multiple swatch chips, no add/
|
|
2777
|
+
* remove affordances. The editable case is editors.tsx's `ChipListEditor`, an
|
|
2778
|
+
* always-live widget (interacting with it IS the commit, the same `switch`/
|
|
2779
|
+
* `rating`/`checkbox` shape `body-cells.tsx`'s `isAlwaysLiveEditable` already
|
|
2780
|
+
* covers) -- this component only ever renders the REST display. */ function ChipListCell({ value, className, chipClassName }) {
|
|
2781
|
+
const tags = Array.isArray(value) ? value.filter((tag)=>!!tag) : [];
|
|
2782
|
+
if (!tags.length) return null;
|
|
2783
|
+
return /*#__PURE__*/ jsx("span", {
|
|
2784
|
+
className: className,
|
|
2785
|
+
children: tags.map((tag)=>/*#__PURE__*/ jsx(SwatchChip, {
|
|
2786
|
+
value: tag,
|
|
2787
|
+
className: chipClassName
|
|
2788
|
+
}, tag))
|
|
2789
|
+
});
|
|
2790
|
+
}
|
|
2791
|
+
/**
|
|
2792
|
+
* Feature D (#13) -- generic text+affix composition: `suffix` (if given) renders as
|
|
2793
|
+
* a `flex-shrink: 0` icon beside the text, and the TEXT itself (not the outer `<td>`)
|
|
2794
|
+
* gets its own `flex: 1 1 0%; min-width: 0` + ellipsis, so a long value truncates
|
|
2795
|
+
* while the affix stays visible instead of being squeezed out of the cell entirely
|
|
2796
|
+
* (the bug: composing text+icon inside a plain truncating `<td>` lets the icon
|
|
2797
|
+
* scroll/clip away with the text, since a flex child never inherits its PARENT's
|
|
2798
|
+
* own `text-overflow`). `data-seed-truncate` on the text span is what `truncate.ts`'s
|
|
2799
|
+
* `isCellTruncated` (Feature C's click-to-expand gate) measures instead of the
|
|
2800
|
+
* `<td>` itself for exactly the same reason -- see that file's own comment.
|
|
2801
|
+
* Any FUTURE cell composing a fixed leading/trailing glyph beside truncating text
|
|
2802
|
+
* should render through this component rather than re-deriving the same three-slot
|
|
2803
|
+
* flex shape.
|
|
2804
|
+
*/ function CellWithSuffix({ text, suffix, rowClassName, textClassName, suffixClassName }) {
|
|
2805
|
+
if (!suffix) return /*#__PURE__*/ jsx(Fragment, {
|
|
2806
|
+
children: text
|
|
2807
|
+
});
|
|
2808
|
+
return /*#__PURE__*/ jsxs("span", {
|
|
2809
|
+
className: rowClassName,
|
|
2810
|
+
children: [
|
|
2811
|
+
/*#__PURE__*/ jsx("span", {
|
|
2812
|
+
className: textClassName,
|
|
2813
|
+
"data-seed-truncate": "",
|
|
2814
|
+
children: text
|
|
2815
|
+
}),
|
|
2816
|
+
/*#__PURE__*/ jsx("span", {
|
|
2817
|
+
className: suffixClassName,
|
|
2818
|
+
children: suffix
|
|
2819
|
+
})
|
|
2820
|
+
]
|
|
2821
|
+
});
|
|
2822
|
+
}
|
|
2823
|
+
function LinkCell({ column, value, row, className, rowClassName, textClassName, suffixClassName }) {
|
|
2672
2824
|
const text = value == null ? "" : String(value);
|
|
2673
2825
|
if (!text) return null;
|
|
2674
2826
|
const isUrl = column.type === "url";
|
|
2675
2827
|
const href = isUrl ? /^https?:\/\//.test(text) ? text : `https://${text}` : `mailto:${text}`;
|
|
2828
|
+
const suffix = column.suffixIcon?.(row);
|
|
2676
2829
|
return /*#__PURE__*/ jsx("a", {
|
|
2677
2830
|
className: className,
|
|
2678
2831
|
href: href,
|
|
@@ -2681,7 +2834,13 @@ function LinkCell({ column, value, className }) {
|
|
|
2681
2834
|
// A link cell points somewhere other than "select this row" -- its own
|
|
2682
2835
|
// navigation must not also fire a row click handler.
|
|
2683
2836
|
onClick: (event)=>event.stopPropagation(),
|
|
2684
|
-
children:
|
|
2837
|
+
children: /*#__PURE__*/ jsx(CellWithSuffix, {
|
|
2838
|
+
text: text,
|
|
2839
|
+
suffix: suffix,
|
|
2840
|
+
rowClassName: rowClassName,
|
|
2841
|
+
textClassName: textClassName,
|
|
2842
|
+
suffixClassName: suffixClassName
|
|
2843
|
+
})
|
|
2685
2844
|
});
|
|
2686
2845
|
}
|
|
2687
2846
|
// Attio's own measured 5-point star path (crisp's `RATING_STAR_D`, traced from the
|
|
@@ -2707,8 +2866,7 @@ function RatingCell({ value, maxRating = 5 }) {
|
|
|
2707
2866
|
},
|
|
2708
2867
|
children: Array.from({
|
|
2709
2868
|
length: maxRating
|
|
2710
|
-
}, (_, index)
|
|
2711
|
-
/*#__PURE__*/ jsx("svg", {
|
|
2869
|
+
}, (_, index)=>/*#__PURE__*/ jsx("svg", {
|
|
2712
2870
|
width: 16,
|
|
2713
2871
|
height: 16,
|
|
2714
2872
|
viewBox: "0 0 16 16",
|
|
@@ -3199,7 +3357,7 @@ const TextFieldTextarea = /*#__PURE__*/ forwardRef(({ className, autoresize = tr
|
|
|
3199
3357
|
});
|
|
3200
3358
|
TextFieldTextarea.displayName = "TextFieldTextarea";
|
|
3201
3359
|
|
|
3202
|
-
__insertCSS(".seed-data-table__root{box-sizing:border-box;display:flex;flex-direction:column;width:100%;border-width:1px;border-style:solid;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}.seed-data-table__table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.seed-data-table__headerCell{box-sizing:border-box;position:sticky;top:0;z-index:2;vertical-align:middle;text-align:start;padding:0;height:var(--seed-dimension-x10);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium);letter-spacing:-.14px}.seed-data-table__headerCell:last-child{border-inline-end:none}.seed-data-table__headerCell[data-sortable]{cursor:pointer;user-select:none}.seed-data-table__headerCell [data-chevron]{opacity:0;transition:opacity .12s}.seed-data-table__headerCell[data-sortable]:hover [data-chevron]{opacity:.6}.seed-data-table__headerCell[data-sorted] [data-chevron]{opacity:1;color:var(--seed-color-fg-neutral)}.seed-data-table__headerCell:hover [data-column-menu]{opacity:1}.seed-data-table__headerCell [data-column-menu]:focus-visible,.seed-data-table__headerCell [data-column-menu][data-open]{opacity:1}.seed-data-table__headerCell[data-dragging]{opacity:.5}.seed-data-table__headerCell[data-sticky]{position:sticky;z-index:3;background-color:var(--seed-color-bg-layer-default)}.seed-data-table__headerCell{outline:var(--seed-dimension-x0_5) solid transparent;outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell:is(:focus-visible,[data-focus-visible]){outline:var(--seed-dimension-x0_5) solid var(--seed-color-stroke-focus-ring);outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell .seed-data-table-resize-handle{position:absolute;top:0;inset-inline-end:calc(7px / -2);width:7px;height:100%;z-index:4;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none}.seed-data-table__headerCell .seed-data-table-resize-handle-inner{width:3px;height:100%;border-radius:3px;background-color:#0298d9;opacity:0;transition:opacity .1s}.seed-data-table__headerCell .seed-data-table-resize-handle:hover .seed-data-table-resize-handle-inner,.seed-data-table__headerCell .seed-data-table-resize-handle[data-resizing] .seed-data-table-resize-handle-inner{opacity:1}.seed-data-table__headerCellInner{box-sizing:border-box;display:flex;align-items:center;width:100%;height:100%;min-width:0;gap:var(--seed-dimension-x1_5);padding-inline:var(--seed-dimension-x3)}.seed-data-table__headerCellLabel{min-width:0;flex:1 1 0%;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__headerCellIcon{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;justify-content:center;width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-subtle);border:none;background:0 0;padding:0;font:inherit;cursor:pointer}.seed-data-table__headerCellIcon[data-active]{color:var(--seed-color-fg-neutral)}.seed-data-table__headerCellIcon[data-column-menu]{opacity:0;transition:opacity .12s}.seed-data-table__row{position:relative;background-color:var(--seed-color-bg-layer-default);--seed-data-table-row-bg:var(--seed-color-bg-layer-default)}.seed-data-table__row[data-clickable]{cursor:pointer}.seed-data-table__row:is([aria-selected=true],[data-selected]){background-color:color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default));--seed-data-table-row-bg:color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default))}.seed-data-table__row:is([aria-selected=true],[data-selected]):is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default)));--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default)))}.seed-data-table__cell{box-sizing:border-box;position:relative;vertical-align:middle;text-align:start;height:var(--seed-dimension-x9);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-top:none;border-inline-start:none;padding-block:0;padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-regular);letter-spacing:-.14px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cell:last-child{border-inline-end:none}tbody tr:last-child .seed-data-table__cell{border-bottom:none}.seed-data-table__cell[data-numeric]{text-align:end;font-variant-numeric:tabular-nums}.seed-data-table__cell[data-sticky]{position:sticky;z-index:1;background-color:var(--seed-data-table-row-bg)}.seed-data-table__cell[data-editable]{cursor:default}.seed-data-table__cell .seed-data-table-edit-picker{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);min-width:0}.seed-data-table__cell .seed-data-table-edit-pending{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);animation:rotate .6s linear infinite}.seed-data-table__cell .seed-data-table-edit-error{position:absolute;top:100%;inset-inline-start:var(--seed-dimension-x3);inset-inline-end:var(--seed-dimension-x3);z-index:2;padding-top:2px;font-size:12px;line-height:1.3;color:var(--seed-color-fg-critical);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entity{display:flex;align-items:center;min-width:0;gap:var(--seed-dimension-x1_5)}.seed-data-table__entityName{min-width:0;font-weight:var(--seed-font-weight-medium);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__tagList{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);overflow:hidden;min-width:0}.seed-data-table__entityActions{display:flex;align-items:center;gap:6px;margin-inline-start:auto;flex-shrink:0;opacity:0;transition:opacity .15s}tr:hover .seed-data-table__entityActions{opacity:1}.seed-data-table__entityActions:focus-within{opacity:1}.seed-data-table__entityAction{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;flex-shrink:0;transition:background-color .2s,color .2s,box-shadow .2s}.seed-data-table__entityAction:hover{background:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__link{color:var(--seed-color-fg-neutral);text-decoration:none;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__link:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__toolbar{box-sizing:border-box;display:flex;align-items:center;width:100%;flex-shrink:0;min-height:49px;gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x3);border-top:1px solid var(--seed-color-stroke-neutral-muted)}.seed-data-table__search{position:relative;display:inline-flex;align-items:center;flex:1 1 0%;max-width:280px}.seed-data-table__search svg{position:absolute;inset-inline-start:var(--seed-dimension-x2);width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-muted);pointer-events:none}.seed-data-table__search input{width:100%;height:var(--seed-dimension-x8);padding-inline-start:var(--seed-dimension-x7);padding-inline-end:var(--seed-dimension-x2);border:none;border-radius:var(--seed-radius-r2);background-color:var(--seed-color-bg-layer-default);box-shadow:inset 0 0 0 1px var(--seed-color-stroke-neutral-weak);font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);outline:0;transition:box-shadow .1s var(--seed-timing-function-easing)}.seed-data-table__search input::placeholder{color:var(--seed-color-fg-neutral-subtle)}.seed-data-table__search input:focus{box-shadow:inset 0 0 0 2px var(--seed-color-stroke-neutral-contrast)}.seed-data-table__count{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t3);font-variant-numeric:tabular-nums}.seed-data-table__toolbarEnd{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;gap:var(--seed-dimension-x2)}.seed-data-table__scrollArea{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;flex:1 1 auto;min-height:0;overflow-x:auto;overflow-y:auto}.seed-data-table__scrollArea[data-scrolled-start] [data-sticky-edge]{clip-path:inset(0 -38px 0 0);box-shadow:6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__scrollArea[data-scrolled-end] [data-sticky-edge-end]{clip-path:inset(0 0 0 -38px);box-shadow:-6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__footerCell{box-sizing:border-box;position:sticky;bottom:0;z-index:2;vertical-align:middle;padding:0;height:var(--seed-dimension-x9);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none}.seed-data-table__footerCell:last-child{border-inline-end:none}.seed-data-table__footerCell .seed-data-table-column-calc-trigger{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);width:100%;height:100%;min-width:0;margin:0;padding:0 var(--seed-dimension-x3);border:none;background:0 0;color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap;overflow:clip;cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__footerCell .seed-data-table-column-calc-trigger:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__footerCell .seed-data-table-column-calc-trigger[data-align=right]{justify-content:flex-end}.seed-data-table__footerCell .seed-data-table-column-calc-trigger svg{flex-shrink:0;opacity:.7}.seed-data-table__footerCell .seed-data-table-column-calc-placeholder{overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-value{min-width:0;flex-shrink:1;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-op{min-width:0;flex-shrink:1;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__emptyState{box-sizing:border-box;text-align:center;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t4)}.seed-data-table__loadingState{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:10px;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium)}.seed-data-table__loadingState[data-inline]{padding-block:0;padding-inline:0;height:var(--seed-dimension-x9)}.seed-data-table__loadingState .seed-data-table-loading-spinner{flex-shrink:0;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);animation:rotate .6s linear infinite}.seed-data-table__addRowCell{box-sizing:border-box;padding:0;border-top:none}.seed-data-table__addRow{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;border:none;border-top:1px solid var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);height:var(--seed-dimension-x9);gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x2);color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__addRow:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,var(--seed-color-bg-layer-default));color:var(--seed-color-fg-neutral)}.seed-data-table__addRow svg{flex-shrink:0}.seed-data-table__selectionCell{text-align:center;padding:0}.seed-data-table__root--surface_card{border-color:var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);border-radius:var(--seed-radius-r3)}.seed-data-table__root--surface_bleed{border-color:var(--seed-color-bg-transparent);background-color:var(--seed-color-bg-transparent)}.seed-data-table__row--interactive_true{transition:background-color .12s}.seed-data-table__row--interactive_true:is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,transparent);--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, var(--seed-color-bg-layer-default))}");
|
|
3360
|
+
__insertCSS(".seed-data-table__root{box-sizing:border-box;display:flex;flex-direction:column;width:100%;border-width:1px;border-style:solid;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif}.seed-data-table__table{width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.seed-data-table__headerCell{box-sizing:border-box;position:sticky;top:0;z-index:2;vertical-align:middle;text-align:start;padding:0;height:var(--seed-dimension-x10);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none;color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium);letter-spacing:-.14px}.seed-data-table__headerCell:last-child{border-inline-end:none}.seed-data-table__headerCell[data-sortable]{cursor:pointer;user-select:none}.seed-data-table__headerCell [data-chevron]{opacity:0;transition:opacity .12s}.seed-data-table__headerCell[data-sortable]:hover [data-chevron]{opacity:.6}.seed-data-table__headerCell[data-sorted] [data-chevron]{opacity:1;color:var(--seed-color-fg-neutral)}.seed-data-table__headerCell:hover [data-column-menu]{opacity:1}.seed-data-table__headerCell [data-column-menu]:focus-visible,.seed-data-table__headerCell [data-column-menu][data-open]{opacity:1}.seed-data-table__headerCell[data-dragging]{opacity:.5}.seed-data-table__headerCell[data-sticky]{position:sticky;z-index:3;background-color:var(--seed-color-bg-layer-default)}.seed-data-table__headerCell{outline:var(--seed-dimension-x0_5) solid transparent;outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell:is(:focus-visible,[data-focus-visible]){outline:var(--seed-dimension-x0_5) solid var(--seed-color-stroke-focus-ring);outline-offset:calc(var(--seed-dimension-x0_5) * -1)}.seed-data-table__headerCell .seed-data-table-resize-handle{position:absolute;top:0;inset-inline-end:calc(7px / -2);width:7px;height:100%;z-index:4;display:flex;align-items:center;justify-content:center;cursor:col-resize;touch-action:none}.seed-data-table__headerCell .seed-data-table-resize-handle-inner{width:3px;height:100%;border-radius:3px;background-color:#0298d9;opacity:0;transition:opacity .1s}.seed-data-table__headerCell .seed-data-table-resize-handle:hover .seed-data-table-resize-handle-inner,.seed-data-table__headerCell .seed-data-table-resize-handle[data-resizing] .seed-data-table-resize-handle-inner{opacity:1}.seed-data-table__headerCellInner{box-sizing:border-box;display:flex;align-items:center;width:100%;height:100%;min-width:0;gap:var(--seed-dimension-x1_5);padding-inline:var(--seed-dimension-x3)}.seed-data-table__headerCellLabel{min-width:0;flex:1 1 0%;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__headerCellIcon{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;justify-content:center;width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-subtle);border:none;background:0 0;padding:0;font:inherit;cursor:pointer}.seed-data-table__headerCellIcon[data-active]{color:var(--seed-color-fg-neutral)}.seed-data-table__headerCellIcon[data-column-menu]{opacity:0;transition:opacity .12s}.seed-data-table__row{position:relative;background-color:var(--seed-color-bg-layer-default);--seed-data-table-row-bg:var(--seed-color-bg-layer-default)}.seed-data-table__row[data-clickable]{cursor:pointer}.seed-data-table__row:is([aria-selected=true],[data-selected]){background-color:color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default));--seed-data-table-row-bg:color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default))}.seed-data-table__row:is([aria-selected=true],[data-selected]):is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,color-mix(in srgb,#0298d9 10%,var(--seed-color-bg-layer-default)));--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, color-mix(in srgb, #0298d9 10%, var(--seed-color-bg-layer-default)))}.seed-data-table__cell{box-sizing:border-box;position:relative;vertical-align:middle;text-align:start;height:var(--seed-dimension-x9);border-bottom:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-top:none;border-inline-start:none;padding-block:0;padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-regular);letter-spacing:-.14px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cell:last-child{border-inline-end:none}tbody tr:last-child .seed-data-table__cell{border-bottom:none}.seed-data-table__cell[data-numeric]{text-align:end;font-variant-numeric:tabular-nums}.seed-data-table__cell[data-sticky]{position:sticky;z-index:1;background-color:var(--seed-data-table-row-bg)}.seed-data-table__cell[data-editable]{cursor:default}.seed-data-table__cell .seed-data-table-edit-picker{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);min-width:0}.seed-data-table__cell .seed-data-table-edit-pending{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);animation:rotate .6s linear infinite}.seed-data-table__cell .seed-data-table-edit-error{position:absolute;top:100%;inset-inline-start:var(--seed-dimension-x3);inset-inline-end:var(--seed-dimension-x3);z-index:2;padding-top:2px;font-size:12px;line-height:1.3;color:var(--seed-color-fg-critical);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__entity{display:flex;align-items:center;min-width:0;gap:var(--seed-dimension-x1_5)}.seed-data-table__entityName{min-width:0;font-weight:var(--seed-font-weight-medium);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__tagList{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);overflow:hidden;min-width:0}.seed-data-table__entityActions{display:flex;align-items:center;gap:6px;margin-inline-start:auto;flex-shrink:0;opacity:0;transition:opacity .15s}tr:hover .seed-data-table__entityActions{opacity:1}.seed-data-table__entityActions:focus-within{opacity:1}.seed-data-table__entityAction{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin:0;padding:2px;border:none;border-radius:6px;background:0 0;font-family:inherit;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent);cursor:pointer;flex-shrink:0;transition:background-color .2s,color .2s,box-shadow .2s}.seed-data-table__entityAction:hover{background:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__link{color:var(--seed-color-fg-neutral);text-decoration:none;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__link:is(:hover,[data-hover]){text-decoration:underline}.seed-data-table__chip{box-sizing:border-box;display:inline-flex;align-items:center;flex-shrink:0;max-width:100%;height:22px;padding:0 4px;border-radius:7px;font-size:10px;font-weight:var(--seed-font-weight-regular);line-height:22px;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__chipList{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--seed-dimension-x1_5);overflow:hidden;min-width:0;width:100%}.seed-data-table__chipRemove{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:12px;height:12px;margin:0;margin-inline-start:2px;padding:0;border:none;border-radius:999px;background:0 0;color:inherit;opacity:.6;cursor:pointer;transition:opacity .12s,background-color .12s}.seed-data-table__chipRemove:hover{opacity:1;background-color:rgba(0,0,0,.08)}.seed-data-table__chipInput{flex:1 1 auto;min-width:40px;height:22px;margin:0;padding:0;border:none;outline:0;background:0 0;font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);letter-spacing:-.14px}.seed-data-table__expandOverlay{box-sizing:border-box;position:absolute;top:-1px;inset-inline-start:-1px;inset-inline-end:-1px;z-index:10;min-height:calc(100% + 2px);display:flex;align-items:flex-start;padding-inline:var(--seed-dimension-x3);padding-block:var(--seed-dimension-x3);background-color:var(--seed-color-bg-layer-floating);border-radius:var(--seed-radius-r5);box-shadow:inset 0 0 0 1px var(--seed-color-stroke-neutral-weak),var(--seed-shadow-s3);color:var(--seed-color-fg-neutral);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);letter-spacing:-.14px;cursor:default}.seed-data-table__expandOverlayText{width:100%;min-width:0;white-space:normal;word-break:break-word}.seed-data-table__cellSuffixRow{display:flex;align-items:center;gap:4px;min-width:0;width:100%}.seed-data-table__cellSuffixText{flex:1 1 0%;min-width:0;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__cellSuffixIcon{flex-shrink:0;display:inline-flex;align-items:center;color:color-mix(in srgb,var(--seed-color-fg-neutral) 55%,transparent)}.seed-data-table__toolbar{box-sizing:border-box;display:flex;align-items:center;width:100%;flex-shrink:0;min-height:49px;gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x3);border-top:1px solid var(--seed-color-stroke-neutral-muted)}.seed-data-table__search{position:relative;display:inline-flex;align-items:center;flex:1 1 0%;max-width:280px}.seed-data-table__search svg{position:absolute;inset-inline-start:var(--seed-dimension-x2);width:var(--seed-dimension-x4);height:var(--seed-dimension-x4);color:var(--seed-color-fg-neutral-muted);pointer-events:none}.seed-data-table__search input{width:100%;height:var(--seed-dimension-x8);padding-inline-start:var(--seed-dimension-x7);padding-inline-end:var(--seed-dimension-x2);border:none;border-radius:var(--seed-radius-r2);background-color:var(--seed-color-bg-layer-default);box-shadow:inset 0 0 0 1px var(--seed-color-stroke-neutral-weak);font-family:inherit;font-size:var(--seed-font-size-t4);color:var(--seed-color-fg-neutral);outline:0;transition:box-shadow .1s var(--seed-timing-function-easing)}.seed-data-table__search input::placeholder{color:var(--seed-color-fg-neutral-subtle)}.seed-data-table__search input:focus{box-shadow:inset 0 0 0 2px var(--seed-color-stroke-neutral-contrast)}.seed-data-table__count{flex-shrink:0;color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t3);font-variant-numeric:tabular-nums}.seed-data-table__toolbarEnd{flex-shrink:0;margin-inline-start:auto;display:inline-flex;align-items:center;gap:var(--seed-dimension-x2)}.seed-data-table__scrollArea{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;flex:1 1 auto;min-height:0;overflow-x:auto;overflow-y:auto}.seed-data-table__scrollArea[data-scrolled-start] [data-sticky-edge]{clip-path:inset(0 -38px 0 0);box-shadow:6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__scrollArea[data-scrolled-end] [data-sticky-edge-end]{clip-path:inset(0 0 0 -38px);box-shadow:-6px 0 16px 4px rgba(0,0,0,.12)}.seed-data-table__footerCell{box-sizing:border-box;position:sticky;bottom:0;z-index:2;vertical-align:middle;padding:0;height:var(--seed-dimension-x9);background-color:var(--seed-color-bg-layer-default);border-top:1px solid var(--seed-color-stroke-neutral-muted);border-inline-end:1px solid var(--seed-color-stroke-neutral-muted);border-inline-start:none}.seed-data-table__footerCell:last-child{border-inline-end:none}.seed-data-table__footerCell .seed-data-table-column-calc-trigger{display:flex;align-items:center;gap:var(--seed-dimension-x1_5);width:100%;height:100%;min-width:0;margin:0;padding:0 var(--seed-dimension-x3);border:none;background:0 0;color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);font-weight:var(--seed-font-weight-medium);white-space:nowrap;overflow:clip;cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__footerCell .seed-data-table-column-calc-trigger:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,transparent);color:var(--seed-color-fg-neutral)}.seed-data-table__footerCell .seed-data-table-column-calc-trigger[data-align=right]{justify-content:flex-end}.seed-data-table__footerCell .seed-data-table-column-calc-trigger svg{flex-shrink:0;opacity:.7}.seed-data-table__footerCell .seed-data-table-column-calc-placeholder{overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-value{min-width:0;flex-shrink:1;color:var(--seed-color-fg-neutral);font-variant-numeric:tabular-nums;overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__footerCell .seed-data-table-column-calc-op{min-width:0;flex-shrink:1;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);overflow:clip;text-overflow:ellipsis;white-space:nowrap}.seed-data-table__emptyState{box-sizing:border-box;text-align:center;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:var(--seed-color-fg-neutral-subtle);font-size:var(--seed-font-size-t4)}.seed-data-table__loadingState{box-sizing:border-box;display:flex;align-items:center;justify-content:center;gap:10px;padding-block:var(--seed-dimension-x8);padding-inline:var(--seed-dimension-x3);color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);font-size:var(--seed-font-size-t4);line-height:var(--seed-line-height-t4);font-weight:var(--seed-font-weight-medium)}.seed-data-table__loadingState[data-inline]{padding-block:0;padding-inline:0;height:var(--seed-dimension-x9)}.seed-data-table__loadingState .seed-data-table-loading-spinner{flex-shrink:0;color:color-mix(in srgb,var(--seed-color-fg-neutral) 63%,transparent);animation:rotate .6s linear infinite}.seed-data-table__addRowCell{box-sizing:border-box;padding:0;border-top:none}.seed-data-table__addRow{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;border:none;border-top:1px solid var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);height:var(--seed-dimension-x9);gap:var(--seed-dimension-x2);padding-inline:var(--seed-dimension-x2);color:var(--seed-color-fg-neutral-subtle);font-family:inherit;font-size:var(--seed-font-size-t4);cursor:pointer;transition:background-color .12s,color .12s}.seed-data-table__addRow:hover{background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 4%,var(--seed-color-bg-layer-default));color:var(--seed-color-fg-neutral)}.seed-data-table__addRow svg{flex-shrink:0}.seed-data-table__selectionCell{text-align:center;padding:0}.seed-data-table__root--surface_card{border-color:var(--seed-color-stroke-neutral-muted);background-color:var(--seed-color-bg-layer-default);border-radius:var(--seed-radius-r3)}.seed-data-table__root--surface_bleed{border-color:var(--seed-color-bg-transparent);background-color:var(--seed-color-bg-transparent)}.seed-data-table__row--interactive_true{transition:background-color .12s}.seed-data-table__row--interactive_true:is(:hover,[data-hover]){background-color:color-mix(in srgb,var(--seed-color-fg-neutral) 3%,transparent);--seed-data-table-row-bg:color-mix(in srgb, var(--seed-color-fg-neutral) 3%, var(--seed-color-bg-layer-default))}");
|
|
3203
3361
|
|
|
3204
3362
|
const createClassName = (className, variants, compoundVariants = [])=>{
|
|
3205
3363
|
const variantKeys = Object.keys(variants);
|
|
@@ -3294,6 +3452,42 @@ const dataTableSlotNames = [
|
|
|
3294
3452
|
"link",
|
|
3295
3453
|
"seed-data-table__link"
|
|
3296
3454
|
],
|
|
3455
|
+
[
|
|
3456
|
+
"chip",
|
|
3457
|
+
"seed-data-table__chip"
|
|
3458
|
+
],
|
|
3459
|
+
[
|
|
3460
|
+
"chipList",
|
|
3461
|
+
"seed-data-table__chipList"
|
|
3462
|
+
],
|
|
3463
|
+
[
|
|
3464
|
+
"chipRemove",
|
|
3465
|
+
"seed-data-table__chipRemove"
|
|
3466
|
+
],
|
|
3467
|
+
[
|
|
3468
|
+
"chipInput",
|
|
3469
|
+
"seed-data-table__chipInput"
|
|
3470
|
+
],
|
|
3471
|
+
[
|
|
3472
|
+
"expandOverlay",
|
|
3473
|
+
"seed-data-table__expandOverlay"
|
|
3474
|
+
],
|
|
3475
|
+
[
|
|
3476
|
+
"expandOverlayText",
|
|
3477
|
+
"seed-data-table__expandOverlayText"
|
|
3478
|
+
],
|
|
3479
|
+
[
|
|
3480
|
+
"cellSuffixRow",
|
|
3481
|
+
"seed-data-table__cellSuffixRow"
|
|
3482
|
+
],
|
|
3483
|
+
[
|
|
3484
|
+
"cellSuffixText",
|
|
3485
|
+
"seed-data-table__cellSuffixText"
|
|
3486
|
+
],
|
|
3487
|
+
[
|
|
3488
|
+
"cellSuffixIcon",
|
|
3489
|
+
"seed-data-table__cellSuffixIcon"
|
|
3490
|
+
],
|
|
3297
3491
|
[
|
|
3298
3492
|
"entityActions",
|
|
3299
3493
|
"seed-data-table__entityActions"
|
|
@@ -3868,6 +4062,103 @@ function RatingEditor({ column, value, pending, onCommit }) {
|
|
|
3868
4062
|
]
|
|
3869
4063
|
});
|
|
3870
4064
|
}
|
|
4065
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
4066
|
+
// -- editable: "chip-list" (Feature B, #8) -- always-live, the same shape
|
|
4067
|
+
// `SwitchEditor`/`CheckboxEditor`/`RatingEditor` above already establish
|
|
4068
|
+
// (interacting with the widget IS the commit, no double-click gate, no separate
|
|
4069
|
+
// rest display -- `body-cells.tsx`'s `isAlwaysLiveEditable` covers it alongside
|
|
4070
|
+
// them). A gated open/close state (like `SelectEditor`'s) would fight adding
|
|
4071
|
+
// MULTIPLE tags in one sitting: `useDataTableEdit`'s `commitEdit` closes editing
|
|
4072
|
+
// the instant a SYNC commit resolves, so a gated chip editor would close itself
|
|
4073
|
+
// after the very first tag. Always-live sidesteps that entirely -- there is no
|
|
4074
|
+
// `editingCell` to close, the widget is simply always the cell's own content.
|
|
4075
|
+
// Every add/remove commits the FULL next array through the same one-string
|
|
4076
|
+
// contract every other editor already uses (`useDataTableEdit`'s own doc
|
|
4077
|
+
// comment): `JSON.stringify(nextTags)`, which the consumer's `onEdit` parses
|
|
4078
|
+
// back -- crisp/GRC's contract stays "one string in, no typed union", not a
|
|
4079
|
+
// second commit shape invented for just this column.
|
|
4080
|
+
function ChipListEditor({ column, value, pending, onCommit, classNames }) {
|
|
4081
|
+
const tags = Array.isArray(value) ? value.filter((tag)=>!!tag) : [];
|
|
4082
|
+
const [draft, setDraft] = React.useState("");
|
|
4083
|
+
function commitTags(next) {
|
|
4084
|
+
onCommit(JSON.stringify(next));
|
|
4085
|
+
}
|
|
4086
|
+
function addTag() {
|
|
4087
|
+
const tag = draft.trim();
|
|
4088
|
+
setDraft("");
|
|
4089
|
+
if (!tag || tags.includes(tag)) return;
|
|
4090
|
+
commitTags([
|
|
4091
|
+
...tags,
|
|
4092
|
+
tag
|
|
4093
|
+
]);
|
|
4094
|
+
}
|
|
4095
|
+
function removeTag(tag) {
|
|
4096
|
+
commitTags(tags.filter((existing)=>existing !== tag));
|
|
4097
|
+
}
|
|
4098
|
+
return(// biome-ignore lint/a11y/noStaticElementInteractions: not a widget -- this span never responds to interaction on ITSELF, only stops propagation of events that already occurred on a real interactive descendant (the remove buttons, the add-tag input). No role fits it because it isn't a control.
|
|
4099
|
+
/*#__PURE__*/ jsxs("span", {
|
|
4100
|
+
className: classNames.chipList,
|
|
4101
|
+
onClick: (event)=>event.stopPropagation(),
|
|
4102
|
+
children: [
|
|
4103
|
+
tags.map((tag)=>/*#__PURE__*/ jsx(SwatchChip, {
|
|
4104
|
+
value: tag,
|
|
4105
|
+
className: classNames.chip,
|
|
4106
|
+
children: /*#__PURE__*/ jsx("button", {
|
|
4107
|
+
type: "button",
|
|
4108
|
+
disabled: pending,
|
|
4109
|
+
"aria-label": `Remove ${tag}`,
|
|
4110
|
+
className: classNames.chipRemove,
|
|
4111
|
+
onClick: ()=>removeTag(tag),
|
|
4112
|
+
children: /*#__PURE__*/ jsx(IconXmarkLine_default, {
|
|
4113
|
+
size: 10
|
|
4114
|
+
})
|
|
4115
|
+
})
|
|
4116
|
+
}, tag)),
|
|
4117
|
+
/*#__PURE__*/ jsx("input", {
|
|
4118
|
+
className: classNames.chipInput,
|
|
4119
|
+
value: draft,
|
|
4120
|
+
disabled: pending,
|
|
4121
|
+
placeholder: tags.length ? "" : "Add…",
|
|
4122
|
+
"aria-label": `Add tag to ${column.key}`,
|
|
4123
|
+
onChange: (event)=>setDraft(event.target.value),
|
|
4124
|
+
onKeyDown: (event)=>{
|
|
4125
|
+
event.stopPropagation();
|
|
4126
|
+
if (event.key === "Enter") {
|
|
4127
|
+
event.preventDefault();
|
|
4128
|
+
addTag();
|
|
4129
|
+
} else if (event.key === "Backspace" && draft === "" && tags.length > 0) {
|
|
4130
|
+
removeTag(tags[tags.length - 1]);
|
|
4131
|
+
} else if (event.key === "Escape") {
|
|
4132
|
+
setDraft("");
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
}),
|
|
4136
|
+
pending && /*#__PURE__*/ jsx(EditPendingIndicator, {})
|
|
4137
|
+
]
|
|
4138
|
+
}));
|
|
4139
|
+
}
|
|
4140
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
4141
|
+
// -- Feature C (#12): cell-expand "show full content" overlay -- an anchored box
|
|
4142
|
+
// (position:absolute over the cell it belongs to, grows in HEIGHT, elevated)
|
|
4143
|
+
// that wraps whatever a truncated cell would otherwise show inline: an editable
|
|
4144
|
+
// column's OWN editor node (unchanged, just relocated into this box instead of
|
|
4145
|
+
// rendered flush in the 36px row) for the editable case, or the plain full value
|
|
4146
|
+
// for a read-only one. `body-cells.tsx` decides WHEN to render this (a click on a
|
|
4147
|
+
// cell whose content is actually truncated, `truncate.ts`'s `isCellTruncated`);
|
|
4148
|
+
// this component only supplies the box.
|
|
4149
|
+
function CellExpandOverlay({ className, children }) {
|
|
4150
|
+
return(// `stopPropagation` -- an overlay sits on top of (and past) its own cell/row;
|
|
4151
|
+
// a click anywhere inside it must never ALSO fire the row's own `onRowClick`,
|
|
4152
|
+
// the same guard every other interactive cell affordance in this directory
|
|
4153
|
+
// already applies (`LinkCell`, `EntityCell`'s preview button, editors.tsx's
|
|
4154
|
+
// `TextEditor` root).
|
|
4155
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: not a widget -- this div never responds to interaction on ITSELF, only stops propagation of events that already occurred on a real interactive descendant (the editor/text it wraps). No role fits it because it isn't a control.
|
|
4156
|
+
/*#__PURE__*/ jsx("div", {
|
|
4157
|
+
className: className,
|
|
4158
|
+
onClick: (event)=>event.stopPropagation(),
|
|
4159
|
+
children: children
|
|
4160
|
+
}));
|
|
4161
|
+
}
|
|
3871
4162
|
|
|
3872
4163
|
// Row-narrowing for the toolbar's search box -- split out of DataTable.tsx the way
|
|
3873
4164
|
// cells.tsx splits out cell-type rendering: a self-contained, independently testable
|
|
@@ -3907,49 +4198,167 @@ function RatingEditor({ column, value, pending, onCommit }) {
|
|
|
3907
4198
|
return data.filter((row)=>searchableColumns.some((column)=>matchesSearch(getColumnValue(column, row), query)));
|
|
3908
4199
|
}
|
|
3909
4200
|
|
|
4201
|
+
// Feature C (#12) -- the click-to-expand gate: measures whether a cell's rendered
|
|
4202
|
+
// content is ACTUALLY truncated right now, so a single click only opens the
|
|
4203
|
+
// anchored overlay (editors.tsx's `CellExpandOverlay`) when there's real hidden
|
|
4204
|
+
// content to show, never on a short value that already fits. Isolated out of
|
|
4205
|
+
// body-cells.tsx the same way select-search.tsx/filtering.ts already split their own
|
|
4206
|
+
// concerns out of the styled layer, so this one pure DOM read is unit-testable on
|
|
4207
|
+
// its own (a plain `<td>`'s own truncate CSS vs. a suffix-icon cell's nested flex
|
|
4208
|
+
// child need two different elements measured -- see below).
|
|
4209
|
+
//
|
|
4210
|
+
// This one genuinely reads a real, laid-out DOM element (`scrollWidth`/
|
|
4211
|
+
// `clientWidth`), unlike react-headless/data-table/src/dom.ts's own helpers (plain
|
|
4212
|
+
// data in, plain data out) -- it lives in the REACT (styled) package rather than
|
|
4213
|
+
// react-headless for that reason: measuring actual layout is a rendering concern,
|
|
4214
|
+
// not table state.
|
|
4215
|
+
function isCellTruncated(cell) {
|
|
4216
|
+
// The common case: a plain cell's own `white-space: nowrap; overflow: clip` (the
|
|
4217
|
+
// `cell` recipe slot) makes the `<td>` ITSELF overflow once its text is longer
|
|
4218
|
+
// than the column is wide.
|
|
4219
|
+
if (cell.scrollWidth > cell.clientWidth) return true;
|
|
4220
|
+
// A cell composing a suffix icon beside its text (cells.tsx's `CellWithSuffix`,
|
|
4221
|
+
// Feature D) wraps the text in its OWN `flex: 1 1 0%; min-width: 0` child instead
|
|
4222
|
+
// -- that flex child never lets the `<td>` itself overflow (it's constrained to
|
|
4223
|
+
// the remaining row width by construction), so the truncating element to measure
|
|
4224
|
+
// is the flex child, marked `data-seed-truncate` by whichever cell renderer
|
|
4225
|
+
// applies its own ellipsis (`CellWithSuffix`'s text span today; any future
|
|
4226
|
+
// truncating inner element should carry the same marker).
|
|
4227
|
+
const targets = cell.querySelectorAll("[data-seed-truncate]");
|
|
4228
|
+
for (const target of targets){
|
|
4229
|
+
if (target.scrollWidth > target.clientWidth) return true;
|
|
4230
|
+
}
|
|
4231
|
+
return false;
|
|
4232
|
+
}
|
|
4233
|
+
|
|
3910
4234
|
/** `editable` + one of these shapes needs no double-click gate and no separate rest
|
|
3911
4235
|
* display -- interacting with the widget itself IS the commit gesture (crisp's own
|
|
3912
4236
|
* #453/#760/#761: `switch`/`rating`/`checkbox` never had a meaningfully different
|
|
3913
|
-
* "rest" state to show).
|
|
4237
|
+
* "rest" state to show). `chip-list` (Feature B, #8) joins them for a different
|
|
4238
|
+
* reason -- see `ChipListEditor`'s own doc comment (editors.tsx): a GATED chip
|
|
4239
|
+
* editor would close itself the instant the first tag committed. Every other
|
|
4240
|
+
* `editable` column opens on double-click. */ function isAlwaysLiveEditable(column) {
|
|
3914
4241
|
if (!column.editable) return false;
|
|
3915
|
-
return column.editor === "switch" || column.type === "rating" || column.type === "checkbox";
|
|
4242
|
+
return column.editor === "switch" || column.type === "rating" || column.type === "checkbox" || column.type === "chip-list";
|
|
3916
4243
|
}
|
|
3917
4244
|
function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyFirst, stickyLast }) {
|
|
3918
4245
|
const effective = useEffectiveColumns(columns, {
|
|
3919
4246
|
selectable,
|
|
3920
4247
|
stickyFirst
|
|
3921
4248
|
});
|
|
3922
|
-
const { startEdit } = useDataTableContext();
|
|
3923
4249
|
return /*#__PURE__*/ jsx(Fragment, {
|
|
3924
4250
|
children: effective.map((entry, index)=>{
|
|
3925
4251
|
const { column } = entry;
|
|
3926
4252
|
const isLast = index === effective.length - 1;
|
|
3927
4253
|
const sticky = pinnedCellProps(entry, stickyLast, isLast);
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
return /*#__PURE__*/ jsx(DataTableCell, {
|
|
3935
|
-
"data-numeric": dataAttr(column.type === "number" || column.type === "currency"),
|
|
3936
|
-
"data-editable": dataAttr(!!column.editable),
|
|
3937
|
-
"data-sticky": sticky["data-sticky"],
|
|
3938
|
-
"data-sticky-edge": sticky["data-sticky-edge"],
|
|
3939
|
-
"data-sticky-edge-end": sticky["data-sticky-edge-end"],
|
|
3940
|
-
style: sticky.style,
|
|
3941
|
-
onDoubleClick: gated ? ()=>startEdit(row.id, column.key) : undefined,
|
|
3942
|
-
children: /*#__PURE__*/ jsx(CellContent, {
|
|
3943
|
-
column: column,
|
|
3944
|
-
row: row,
|
|
3945
|
-
rowId: row.id,
|
|
3946
|
-
classNames: classNames,
|
|
3947
|
-
locale: locale
|
|
3948
|
-
})
|
|
4254
|
+
return /*#__PURE__*/ jsx(DataTableBodyCell, {
|
|
4255
|
+
column: column,
|
|
4256
|
+
row: row,
|
|
4257
|
+
classNames: classNames,
|
|
4258
|
+
locale: locale,
|
|
4259
|
+
sticky: sticky
|
|
3949
4260
|
}, column.key);
|
|
3950
4261
|
})
|
|
3951
4262
|
});
|
|
3952
4263
|
}
|
|
4264
|
+
/**
|
|
4265
|
+
* One `<td>` -- split out of `ColumnBodyCells`'s own map (which now only computes
|
|
4266
|
+
* per-column LAYOUT, `pinnedCellProps`) so this component can own its own per-cell
|
|
4267
|
+
* "is the Feature C overlay open" local state (`overlayOpen`) without re-deriving it
|
|
4268
|
+
* on every row's render. React keeps this instance stable across re-renders because
|
|
4269
|
+
* `ColumnBodyCells` keys it by `column.key` the same way it always keyed the bare
|
|
4270
|
+
* `<DataTableCell>` before this split.
|
|
4271
|
+
*/ function DataTableBodyCell({ column, row, classNames, locale, sticky }) {
|
|
4272
|
+
const { startEdit, isEditing, isPeeking, openPeek, closePeek } = useDataTableContext();
|
|
4273
|
+
const cellRef = React.useRef(null);
|
|
4274
|
+
// Feature C (#12) -- whether THIS activation (click or double-click) should
|
|
4275
|
+
// render as the anchored overlay rather than plain inline. Frozen at the moment
|
|
4276
|
+
// of activation (re-measured every time, never left stale) rather than derived
|
|
4277
|
+
// from `isEditing`/`isPeeking` alone, because those two states don't carry "was
|
|
4278
|
+
// the content actually truncated when this opened" on their own -- a SHORT
|
|
4279
|
+
// editable cell's existing double-click-to-edit (tranche 5, unchanged) must keep
|
|
4280
|
+
// rendering exactly as it always has, not suddenly gain overlay chrome.
|
|
4281
|
+
const [overlayOpen, setOverlayOpen] = React.useState(false);
|
|
4282
|
+
const alwaysLive = isAlwaysLiveEditable(column);
|
|
4283
|
+
// A gated `editable` column (everything except the always-live widgets) opens on
|
|
4284
|
+
// double-click -- Attio's own measured gesture (crisp's #411), matched here
|
|
4285
|
+
// rather than a single click, which stays "select this cell" in crisp's own
|
|
4286
|
+
// spreadsheet model and would otherwise be indistinguishable from this table's
|
|
4287
|
+
// plain row click. Feature C ADDS a single click as a SECOND way in, but only
|
|
4288
|
+
// when the cell's content is actually truncated (see `handleClick` below) --
|
|
4289
|
+
// double-click keeps working unconditionally, same as before this feature.
|
|
4290
|
+
const gated = column.editable && !alwaysLive;
|
|
4291
|
+
function handleDoubleClick(event) {
|
|
4292
|
+
if (!gated) return;
|
|
4293
|
+
setOverlayOpen(isCellTruncated(event.currentTarget));
|
|
4294
|
+
startEdit(row.id, column.key);
|
|
4295
|
+
}
|
|
4296
|
+
function handleClick(event) {
|
|
4297
|
+
if (!isCellTruncated(event.currentTarget)) return;
|
|
4298
|
+
if (gated) {
|
|
4299
|
+
setOverlayOpen(true);
|
|
4300
|
+
startEdit(row.id, column.key);
|
|
4301
|
+
} else if (alwaysLive) {
|
|
4302
|
+
// No separate open/edit state to start -- the always-live widget already
|
|
4303
|
+
// renders unconditionally; this only switches ITS OWN box to the anchored
|
|
4304
|
+
// overlay so a long chip list (etc.) gets room to show every chip.
|
|
4305
|
+
setOverlayOpen(true);
|
|
4306
|
+
} else {
|
|
4307
|
+
setOverlayOpen(true);
|
|
4308
|
+
openPeek(row.id, column.key);
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
// Closes the overlay on Escape or an outside click/pointerdown -- a gated
|
|
4312
|
+
// editor's OWN Escape/blur handling already ends `isEditing` on its own (see
|
|
4313
|
+
// `TextEditor`/`SelectEditor`'s existing onCancel/onOpenChange wiring), which
|
|
4314
|
+
// alone is enough to hide a GATED cell's overlay (its render below is gated on
|
|
4315
|
+
// `isEditing` too); this listener is what the PEEK and ALWAYS-LIVE cases need,
|
|
4316
|
+
// since neither has any other mechanism that ever calls `closePeek`/resets
|
|
4317
|
+
// `overlayOpen` on its own.
|
|
4318
|
+
React.useEffect(()=>{
|
|
4319
|
+
if (!overlayOpen) return;
|
|
4320
|
+
function handlePointerDown(event) {
|
|
4321
|
+
if (cellRef.current && !cellRef.current.contains(event.target)) {
|
|
4322
|
+
setOverlayOpen(false);
|
|
4323
|
+
closePeek();
|
|
4324
|
+
}
|
|
4325
|
+
}
|
|
4326
|
+
function handleKeyDown(event) {
|
|
4327
|
+
if (event.key !== "Escape") return;
|
|
4328
|
+
setOverlayOpen(false);
|
|
4329
|
+
closePeek();
|
|
4330
|
+
}
|
|
4331
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
4332
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
4333
|
+
return ()=>{
|
|
4334
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
4335
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
4336
|
+
};
|
|
4337
|
+
}, [
|
|
4338
|
+
overlayOpen,
|
|
4339
|
+
closePeek
|
|
4340
|
+
]);
|
|
4341
|
+
const overlayActive = overlayOpen && (alwaysLive || isEditing(row.id, column.key) || isPeeking(row.id, column.key));
|
|
4342
|
+
return /*#__PURE__*/ jsx(DataTableCell, {
|
|
4343
|
+
ref: cellRef,
|
|
4344
|
+
"data-numeric": dataAttr(column.type === "number" || column.type === "currency"),
|
|
4345
|
+
"data-editable": dataAttr(!!column.editable),
|
|
4346
|
+
"data-sticky": sticky["data-sticky"],
|
|
4347
|
+
"data-sticky-edge": sticky["data-sticky-edge"],
|
|
4348
|
+
"data-sticky-edge-end": sticky["data-sticky-edge-end"],
|
|
4349
|
+
style: sticky.style,
|
|
4350
|
+
onClick: handleClick,
|
|
4351
|
+
onDoubleClick: handleDoubleClick,
|
|
4352
|
+
children: /*#__PURE__*/ jsx(CellContent, {
|
|
4353
|
+
column: column,
|
|
4354
|
+
row: row,
|
|
4355
|
+
rowId: row.id,
|
|
4356
|
+
classNames: classNames,
|
|
4357
|
+
locale: locale,
|
|
4358
|
+
overlayActive: overlayActive
|
|
4359
|
+
})
|
|
4360
|
+
});
|
|
4361
|
+
}
|
|
3953
4362
|
/**
|
|
3954
4363
|
* Dispatches to whichever of cells.tsx's static renderers or editors.tsx's live
|
|
3955
4364
|
* editors applies to THIS column/row right now -- always-live first (no rest state to
|
|
@@ -3957,7 +4366,7 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
|
|
|
3957
4366
|
* display (a custom `render` wins there, same as before `editable` existed; it never
|
|
3958
4367
|
* overrides an actual editing/always-live state, matching crisp's own split between
|
|
3959
4368
|
* `renderTyped`'s rest-state branch and the editing branches above it).
|
|
3960
|
-
*/ function CellContent({ column, row, rowId, classNames, locale }) {
|
|
4369
|
+
*/ function CellContent({ column, row, rowId, classNames, locale, overlayActive }) {
|
|
3961
4370
|
const { isEditing, isPending, getEditError, commitEdit, cancelEdit } = useDataTableContext();
|
|
3962
4371
|
const rawValue = getColumnValue(column, row);
|
|
3963
4372
|
const pending = isPending(rowId, column.key);
|
|
@@ -3986,6 +4395,14 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
|
|
|
3986
4395
|
pending: pending,
|
|
3987
4396
|
onCommit: commit
|
|
3988
4397
|
});
|
|
4398
|
+
} else if (column.editable && column.type === "chip-list") {
|
|
4399
|
+
node = /*#__PURE__*/ jsx(ChipListEditor, {
|
|
4400
|
+
column: column,
|
|
4401
|
+
value: resolveEditValue(column, row, rawValue),
|
|
4402
|
+
pending: pending,
|
|
4403
|
+
onCommit: commit,
|
|
4404
|
+
classNames: classNames
|
|
4405
|
+
});
|
|
3989
4406
|
} else if (column.editable && isEditing(rowId, column.key)) {
|
|
3990
4407
|
if (column.editor === "select") {
|
|
3991
4408
|
node = /*#__PURE__*/ jsx(SelectEditor, {
|
|
@@ -4021,6 +4438,10 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
|
|
|
4021
4438
|
});
|
|
4022
4439
|
}
|
|
4023
4440
|
} else {
|
|
4441
|
+
// Feature C (#12), read-only case: `DataTableBodyCell`'s own `isPeeking` already
|
|
4442
|
+
// decided whether the overlay should be open (folded into `overlayActive`
|
|
4443
|
+
// below) -- this branch always renders the SAME `DisplayCellContent` either
|
|
4444
|
+
// way, just possibly relocated into the overlay box.
|
|
4024
4445
|
node = /*#__PURE__*/ jsx(DisplayCellContent, {
|
|
4025
4446
|
column: column,
|
|
4026
4447
|
row: row,
|
|
@@ -4031,7 +4452,13 @@ function ColumnBodyCells({ columns, row, classNames, locale, selectable, stickyF
|
|
|
4031
4452
|
}
|
|
4032
4453
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
4033
4454
|
children: [
|
|
4034
|
-
|
|
4455
|
+
overlayActive ? /*#__PURE__*/ jsx(CellExpandOverlay, {
|
|
4456
|
+
className: classNames.expandOverlay,
|
|
4457
|
+
children: column.editable ? node : /*#__PURE__*/ jsx("span", {
|
|
4458
|
+
className: classNames.expandOverlayText,
|
|
4459
|
+
children: node
|
|
4460
|
+
})
|
|
4461
|
+
}) : node,
|
|
4035
4462
|
error && /*#__PURE__*/ jsx(EditError, {
|
|
4036
4463
|
message: error
|
|
4037
4464
|
})
|
|
@@ -4062,7 +4489,11 @@ function DisplayCellContent({ column, row, value, classNames, locale }) {
|
|
|
4062
4489
|
return /*#__PURE__*/ jsx(LinkCell, {
|
|
4063
4490
|
column: column,
|
|
4064
4491
|
value: value,
|
|
4065
|
-
|
|
4492
|
+
row: row,
|
|
4493
|
+
className: classNames.link,
|
|
4494
|
+
rowClassName: classNames.cellSuffixRow,
|
|
4495
|
+
textClassName: classNames.cellSuffixText,
|
|
4496
|
+
suffixClassName: classNames.cellSuffixIcon
|
|
4066
4497
|
});
|
|
4067
4498
|
case "tags":
|
|
4068
4499
|
return /*#__PURE__*/ jsx(TagsCell, {
|
|
@@ -4073,6 +4504,17 @@ function DisplayCellContent({ column, row, value, classNames, locale }) {
|
|
|
4073
4504
|
return /*#__PURE__*/ jsx(StatusCell, {
|
|
4074
4505
|
value: value
|
|
4075
4506
|
});
|
|
4507
|
+
case "chip":
|
|
4508
|
+
return /*#__PURE__*/ jsx(ChipCell, {
|
|
4509
|
+
value: value,
|
|
4510
|
+
className: classNames.chip
|
|
4511
|
+
});
|
|
4512
|
+
case "chip-list":
|
|
4513
|
+
return /*#__PURE__*/ jsx(ChipListCell, {
|
|
4514
|
+
value: value,
|
|
4515
|
+
className: classNames.chipList,
|
|
4516
|
+
chipClassName: classNames.chip
|
|
4517
|
+
});
|
|
4076
4518
|
case "number":
|
|
4077
4519
|
return /*#__PURE__*/ jsx(Fragment, {
|
|
4078
4520
|
children: formatNumberCell(value, locale)
|
|
@@ -4099,9 +4541,23 @@ function DisplayCellContent({ column, row, value, classNames, locale }) {
|
|
|
4099
4541
|
value: value
|
|
4100
4542
|
});
|
|
4101
4543
|
default:
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4544
|
+
{
|
|
4545
|
+
const text = value == null ? null : String(value);
|
|
4546
|
+
const suffix = column.suffixIcon?.(row);
|
|
4547
|
+
// Feature D (#13) -- a plain text column carrying a `suffixIcon` (e.g. a
|
|
4548
|
+
// location column's pin glyph) composes through the same `CellWithSuffix`
|
|
4549
|
+
// LinkCell already uses, so the icon never gets squeezed out by a long value.
|
|
4550
|
+
if (!suffix || text == null) return /*#__PURE__*/ jsx(Fragment, {
|
|
4551
|
+
children: text
|
|
4552
|
+
});
|
|
4553
|
+
return /*#__PURE__*/ jsx(CellWithSuffix, {
|
|
4554
|
+
text: text,
|
|
4555
|
+
suffix: suffix,
|
|
4556
|
+
rowClassName: classNames.cellSuffixRow,
|
|
4557
|
+
textClassName: classNames.cellSuffixText,
|
|
4558
|
+
suffixClassName: classNames.cellSuffixIcon
|
|
4559
|
+
});
|
|
4560
|
+
}
|
|
4105
4561
|
}
|
|
4106
4562
|
}
|
|
4107
4563
|
|