@crispy-seed/data-table 0.3.0 → 0.4.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/index.cjs CHANGED
@@ -2763,6 +2763,292 @@ const TextFieldTextarea = /*#__PURE__*/ React.forwardRef(({ className, autoresiz
2763
2763
  });
2764
2764
  TextFieldTextarea.displayName = "TextFieldTextarea";
2765
2765
 
2766
+ __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__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))}");
2767
+
2768
+ const createClassName = (className, variants, compoundVariants = [])=>{
2769
+ const variantKeys = Object.keys(variants);
2770
+ const variantValues = variantKeys.map((key)=>variants[key]);
2771
+ const variantClassName = variantKeys.map((key, index)=>`${className}--${key}_${variantValues[index]}`).join(" ");
2772
+ const compountVariantClassName = compoundVariants.filter((compoundVariant)=>Object.keys(compoundVariant).every((key)=>compoundVariant[key] === variants[key])).map((compoundVariant)=>`${className}--${Object.keys(compoundVariant).map((key)=>{
2773
+ return `${key}_${compoundVariant[key]}`;
2774
+ }).join("-")}`).join(" ");
2775
+ return [
2776
+ className,
2777
+ variantClassName,
2778
+ compountVariantClassName
2779
+ ].filter(Boolean).join(" ");
2780
+ };
2781
+ function mergeVariants(a, b) {
2782
+ const result = {
2783
+ ...a
2784
+ };
2785
+ for(const k in b){
2786
+ if (b[k] != null) {
2787
+ result[k] = b[k];
2788
+ }
2789
+ }
2790
+ return result;
2791
+ }
2792
+ function splitVariantProps(props, variantMap) {
2793
+ const variantProps = {};
2794
+ const otherProps = {};
2795
+ for(const key in props){
2796
+ if (variantMap[key] != null) {
2797
+ variantProps[key] = props[key];
2798
+ } else {
2799
+ otherProps[key] = props[key];
2800
+ }
2801
+ }
2802
+ return [
2803
+ variantProps,
2804
+ otherProps
2805
+ ];
2806
+ }
2807
+
2808
+ const dataTableSlotNames = [
2809
+ [
2810
+ "root",
2811
+ "seed-data-table__root"
2812
+ ],
2813
+ [
2814
+ "table",
2815
+ "seed-data-table__table"
2816
+ ],
2817
+ [
2818
+ "header",
2819
+ "seed-data-table__header"
2820
+ ],
2821
+ [
2822
+ "headerCell",
2823
+ "seed-data-table__headerCell"
2824
+ ],
2825
+ [
2826
+ "headerCellInner",
2827
+ "seed-data-table__headerCellInner"
2828
+ ],
2829
+ [
2830
+ "headerCellLabel",
2831
+ "seed-data-table__headerCellLabel"
2832
+ ],
2833
+ [
2834
+ "headerCellIcon",
2835
+ "seed-data-table__headerCellIcon"
2836
+ ],
2837
+ [
2838
+ "row",
2839
+ "seed-data-table__row"
2840
+ ],
2841
+ [
2842
+ "cell",
2843
+ "seed-data-table__cell"
2844
+ ],
2845
+ [
2846
+ "entity",
2847
+ "seed-data-table__entity"
2848
+ ],
2849
+ [
2850
+ "entityName",
2851
+ "seed-data-table__entityName"
2852
+ ],
2853
+ [
2854
+ "tagList",
2855
+ "seed-data-table__tagList"
2856
+ ],
2857
+ [
2858
+ "link",
2859
+ "seed-data-table__link"
2860
+ ],
2861
+ [
2862
+ "toolbar",
2863
+ "seed-data-table__toolbar"
2864
+ ],
2865
+ [
2866
+ "search",
2867
+ "seed-data-table__search"
2868
+ ],
2869
+ [
2870
+ "count",
2871
+ "seed-data-table__count"
2872
+ ],
2873
+ [
2874
+ "toolbarEnd",
2875
+ "seed-data-table__toolbarEnd"
2876
+ ],
2877
+ [
2878
+ "scrollArea",
2879
+ "seed-data-table__scrollArea"
2880
+ ],
2881
+ [
2882
+ "footer",
2883
+ "seed-data-table__footer"
2884
+ ],
2885
+ [
2886
+ "footerCell",
2887
+ "seed-data-table__footerCell"
2888
+ ],
2889
+ [
2890
+ "emptyState",
2891
+ "seed-data-table__emptyState"
2892
+ ],
2893
+ [
2894
+ "loadingState",
2895
+ "seed-data-table__loadingState"
2896
+ ],
2897
+ [
2898
+ "addRow",
2899
+ "seed-data-table__addRow"
2900
+ ],
2901
+ [
2902
+ "addRowCell",
2903
+ "seed-data-table__addRowCell"
2904
+ ],
2905
+ [
2906
+ "selectionCell",
2907
+ "seed-data-table__selectionCell"
2908
+ ]
2909
+ ];
2910
+ const defaultVariant$4 = {
2911
+ "surface": "card",
2912
+ "interactive": false
2913
+ };
2914
+ const compoundVariants$4 = [];
2915
+ const dataTableVariantMap = {
2916
+ "surface": [
2917
+ "card",
2918
+ "bleed"
2919
+ ],
2920
+ "interactive": [
2921
+ true,
2922
+ false
2923
+ ]
2924
+ };
2925
+ function dataTable(props) {
2926
+ return Object.fromEntries(dataTableSlotNames.map(([slot, className])=>{
2927
+ return [
2928
+ slot,
2929
+ createClassName(className, mergeVariants(defaultVariant$4, props), compoundVariants$4)
2930
+ ];
2931
+ }));
2932
+ }
2933
+ Object.assign(dataTable, {
2934
+ splitVariantProps: (props)=>splitVariantProps(props, dataTableVariantMap)
2935
+ }); // @recipe(seed): data-table
2936
+
2937
+ // The one `createSlotRecipeContext(dataTable)` call every sibling file in this
2938
+ // directory shares -- `ClassNamesProvider` and `withContext` must be the SAME
2939
+ // binding everywhere (a slot component built from a second, independent call would
2940
+ // read a DIFFERENT React context and never see the classNames `DataTableInner`
2941
+ // provides), so this is the one place that calls `createSlotRecipeContext`, and every
2942
+ // other file (`DataTable.tsx`, `column-menu.tsx`, `resize.tsx`, `column-calc.tsx`,
2943
+ // `toolbar.tsx`, `body-cells.tsx`, `editors.tsx`) imports its exports from here rather
2944
+ // than re-deriving its own.
2945
+ const { ClassNamesProvider: ClassNamesProvider$1, withContext: withContext$1, useClassNames: useClassNames$1 } = createSlotRecipeContext(dataTable);
2946
+
2947
+ /**
2948
+ * The pure filter itself, split out of `useSelectSearch` below so it can be
2949
+ * mutation-tested directly (the same "small pure function beside its own test" shape
2950
+ * `filtering.ts`'s `matchesSearch`/`getColumnValue` already use in this directory) --
2951
+ * case-insensitive substring match, on whitespace-trimmed input. An empty/whitespace-
2952
+ * only query returns `options` unfiltered rather than matching nothing, the same
2953
+ * "no query yet" case crisp's own `select.tsx` special-cases (`searchable && q`).
2954
+ */ function filterSelectOptions(options, query, getText) {
2955
+ const q = query.trim().toLowerCase();
2956
+ if (!q) return options;
2957
+ return options.filter((option)=>getText(option).toLowerCase().includes(q));
2958
+ }
2959
+ /**
2960
+ * Filters `options` by `getText(option)` against a live query string -- the one
2961
+ * concern every searchable Select popover shares (crisp's own `select.tsx` computes
2962
+ * this inline; this hook is `filterSelectOptions` above plus the query state it reads,
2963
+ * kept generic over `T` so it works for `DataTableEditOption` today and a future
2964
+ * filter-value picker's own option shape without a second copy of the same filter).
2965
+ */ function useSelectSearch(options, getText) {
2966
+ const [query, setQuery] = React__namespace.useState("");
2967
+ const filtered = React__namespace.useMemo(()=>filterSelectOptions(options, query, getText), [
2968
+ options,
2969
+ query,
2970
+ getText
2971
+ ]);
2972
+ return {
2973
+ query,
2974
+ setQuery,
2975
+ filtered
2976
+ };
2977
+ }
2978
+ /**
2979
+ * The search box itself -- crisp's own top-of-listbox filter field
2980
+ * (`select.tsx`'s `crisp-select-search`), styled with the SAME compact chrome
2981
+ * `toolbar.tsx`'s `SearchBox` already standardized for the table's own toolbar search
2982
+ * (seed's real `text-input.ts` outline-variant tokens, via the `dataTable` recipe's
2983
+ * own `search` slot -- not seed's documented `TextField`, measured too heavy for a
2984
+ * ~32px inline control; see `SearchBox`'s own comment for that measurement). Reusing
2985
+ * the SAME recipe slot here, rather than standing up a second near-identical one,
2986
+ * keeps every "small bordered search input" in this package pixel-identical by
2987
+ * construction -- the slot's `max-width: 280px` (a toolbar-row layout constraint, not
2988
+ * chrome) is overridden inline since this field fills its popover instead.
2989
+ *
2990
+ * Swallows every keydown except Escape before it can reach seed's own listbox
2991
+ * (`SelectContent`'s typeahead-by-keyboard): a search field that ALSO drives the
2992
+ * listbox's letter-jump would fight the query it is supposed to be typing into. Escape
2993
+ * passes through untouched -- `SelectRoot`'s own `onOpenChange` (in every caller) is
2994
+ * what actually closes the editor on Escape, not a handler on this field.
2995
+ *
2996
+ * `autoFocus` is applied imperatively (an effect + ref), not the native `autoFocus`
2997
+ * attribute -- lint (`a11y/noAutofocus`) bars that on a raw `<input>`, and this is the
2998
+ * same ref-and-focus shape crisp's own `select.tsx` already uses for its search field
2999
+ * (`searchRef.current?.focus({ preventScroll: true })` on open), not a workaround
3000
+ * invented for the lint rule.
3001
+ */ function SelectSearchField({ value, onChange, placeholder, "aria-label": ariaLabel, autoFocus, onKeyDown }) {
3002
+ const classNames = dataTable();
3003
+ const inputRef = React__namespace.useRef(null);
3004
+ React__namespace.useEffect(()=>{
3005
+ if (autoFocus) inputRef.current?.focus({
3006
+ preventScroll: true
3007
+ });
3008
+ }, [
3009
+ autoFocus
3010
+ ]);
3011
+ return /*#__PURE__*/ jsxRuntime.jsxs("span", {
3012
+ className: classNames.search,
3013
+ style: {
3014
+ display: "flex",
3015
+ maxWidth: "none",
3016
+ margin: 4
3017
+ },
3018
+ children: [
3019
+ /*#__PURE__*/ jsxRuntime.jsx(IconMagnifyingglassLine_default, {
3020
+ "aria-hidden": "true"
3021
+ }),
3022
+ /*#__PURE__*/ jsxRuntime.jsx("input", {
3023
+ ref: inputRef,
3024
+ type: "text",
3025
+ value: value,
3026
+ onChange: (event)=>onChange(event.target.value),
3027
+ placeholder: placeholder,
3028
+ "aria-label": ariaLabel ?? placeholder,
3029
+ onClick: (event)=>event.stopPropagation(),
3030
+ onKeyDown: (event)=>{
3031
+ if (event.key !== "Escape") event.stopPropagation();
3032
+ onKeyDown?.(event);
3033
+ }
3034
+ })
3035
+ ]
3036
+ });
3037
+ }
3038
+ /** The empty state shown when a search matches nothing -- crisp's own `searchable`
3039
+ * `emptyLabel` (`crisp-select-empty`), reproduced at the same inset/opacity/size the
3040
+ * ad-hoc `ReferenceEditor` "No users"/"No results" row already used before this file
3041
+ * existed. */ function SelectSearchEmpty({ children }) {
3042
+ return /*#__PURE__*/ jsxRuntime.jsx("div", {
3043
+ style: {
3044
+ padding: "6px 12px",
3045
+ opacity: 0.63,
3046
+ fontSize: 13
3047
+ },
3048
+ children: children
3049
+ });
3050
+ }
3051
+
2766
3052
  /** The raw value a live editor reads, distinct from `DataTableColumn.value` (the
2767
3053
  * accessor sort/search/filter/export share): `editValue` returns whatever TYPE the
2768
3054
  * editor itself expects -- a real `boolean` for `editor: "switch"`/`type:
@@ -2865,10 +3151,21 @@ function DateEditor({ column, value, pending, onCommit, onCancel }) {
2865
3151
  ////////////////////////////////////////////////////////////////////////////////////
2866
3152
  // -- editor: "select" -- double-click opens seed's own Select, auto-opened (seed's
2867
3153
  // `SelectRoot` takes `defaultOpen` directly -- unlike crisp's closed-API `Select`,
2868
- // which needs a synthetic click on its own trigger to start open). -------------
3154
+ // which needs a synthetic click on its own trigger to start open). A long option
3155
+ // list gets crisp's own search-on-top (`select-search.tsx`) for free, past
3156
+ // `SELECT_EDITOR_SEARCH_THRESHOLD` -- fewer options than that and a filter field
3157
+ // is pure noise above a list you can already scan (crisp's own `searchable` is
3158
+ // opt-in for the identical reason); `column.editorSearchable` overrides either way.
3159
+ /** Above this many options, `SelectEditor` turns its search field on by default --
3160
+ * below it, a filter box adds more chrome than it saves (nothing here claims this
3161
+ * exact number is measured; it is a judgment call, which is why `editorSearchable`
3162
+ * exists to override it either direction). */ const SELECT_EDITOR_SEARCH_THRESHOLD = 8;
2869
3163
  function SelectEditor({ column, value, pending, onCommit, onCancel }) {
2870
3164
  const options = column.options ?? [];
2871
3165
  const current = value == null ? "" : String(value);
3166
+ const searchable = column.editorSearchable ?? options.length > SELECT_EDITOR_SEARCH_THRESHOLD;
3167
+ const { query, setQuery, filtered } = useSelectSearch(options, (option)=>option.label);
3168
+ const visible = searchable ? filtered : options;
2872
3169
  return /*#__PURE__*/ jsxRuntime.jsxs(SelectRoot, {
2873
3170
  // Controlled open, per docs/examples/react/select/controlled-open.tsx --
2874
3171
  // this editor is only ever mounted while the cell IS editing, so it always
@@ -2900,38 +3197,54 @@ function SelectEditor({ column, value, pending, onCommit, onCancel }) {
2900
3197
  ]
2901
3198
  }),
2902
3199
  /*#__PURE__*/ jsxRuntime.jsx(SelectPositioner, {
2903
- children: /*#__PURE__*/ jsxRuntime.jsx(SelectContent, {
2904
- children: /*#__PURE__*/ jsxRuntime.jsx(SelectScrollArea, {
2905
- children: options.map((option)=>/*#__PURE__*/ jsxRuntime.jsxs(SelectItem, {
2906
- value: option.value,
2907
- label: option.label,
2908
- children: [
2909
- /*#__PURE__*/ jsxRuntime.jsx(SelectItemBody, {
2910
- children: /*#__PURE__*/ jsxRuntime.jsx(SelectItemLabel, {})
2911
- }),
2912
- /*#__PURE__*/ jsxRuntime.jsx(SelectItemIndicator, {
2913
- selected: /*#__PURE__*/ jsxRuntime.jsx(IconCheckmarkFatFill_default, {})
2914
- })
2915
- ]
2916
- }, option.value))
2917
- })
3200
+ children: /*#__PURE__*/ jsxRuntime.jsxs(SelectContent, {
3201
+ children: [
3202
+ searchable && /*#__PURE__*/ jsxRuntime.jsx(SelectSearchField, {
3203
+ autoFocus: true,
3204
+ value: query,
3205
+ onChange: setQuery,
3206
+ placeholder: column.editorSearchPlaceholder ?? "Search…",
3207
+ "aria-label": `Search ${column.key}`
3208
+ }),
3209
+ /*#__PURE__*/ jsxRuntime.jsxs(SelectScrollArea, {
3210
+ children: [
3211
+ searchable && visible.length === 0 && /*#__PURE__*/ jsxRuntime.jsx(SelectSearchEmpty, {
3212
+ children: column.editorEmptyLabel ?? "No results"
3213
+ }),
3214
+ visible.map((option)=>/*#__PURE__*/ jsxRuntime.jsxs(SelectItem, {
3215
+ value: option.value,
3216
+ label: option.label,
3217
+ children: [
3218
+ /*#__PURE__*/ jsxRuntime.jsx(SelectItemBody, {
3219
+ children: /*#__PURE__*/ jsxRuntime.jsx(SelectItemLabel, {})
3220
+ }),
3221
+ /*#__PURE__*/ jsxRuntime.jsx(SelectItemIndicator, {
3222
+ selected: /*#__PURE__*/ jsxRuntime.jsx(IconCheckmarkFatFill_default, {})
3223
+ })
3224
+ ]
3225
+ }, option.value))
3226
+ ]
3227
+ })
3228
+ ]
2918
3229
  })
2919
3230
  })
2920
3231
  ]
2921
3232
  });
2922
3233
  }
2923
3234
  ////////////////////////////////////////////////////////////////////////////////////
2924
- // -- editor: "reference" / "actor" -- same picker, search-enabled, each option
2925
- // carrying a small avatar (a photo for a real one, a generic person glyph for
2926
- // none) -- `actor` is `reference` over people specifically (crisp's own #449/
2927
- // #432 `ReferenceCell` shape), so the two share one component; only the search
2928
- // placeholder differs. Seed's `Select` has no built-in search combobox (unlike
2929
- // crisp's own `Select`), so this filters `refOptions` itself against a small
2930
- // `TextField` rendered as the content's own first row. --------------------------
3235
+ // -- editor: "reference" / "actor" -- same picker, ALWAYS search-enabled (unlike
3236
+ // `SelectEditor`'s threshold -- a reference/actor list is people/records, search
3237
+ // is the point regardless of how few there are today), each option carrying a
3238
+ // small avatar (a photo for a real one, a generic person glyph for none) --
3239
+ // `actor` is `reference` over people specifically (crisp's own #449/#432
3240
+ // `ReferenceCell` shape), so the two share one component; only the search
3241
+ // placeholder/empty copy differs. Seed's `Select` has no built-in search combobox
3242
+ // (unlike crisp's own `Select`), so this uses the shared `select-search.tsx`
3243
+ // field/hook -- the same one `SelectEditor` above uses -- rather than its own
3244
+ // copy of the query/filter/empty triangle. --------------------------------------
2931
3245
  function ReferenceEditor({ column, value, pending, onCommit, onCancel }) {
2932
- const [query, setQuery] = React__namespace.useState("");
2933
3246
  const options = column.refOptions ?? [];
2934
- const filtered = query.trim() ? options.filter((option)=>option.label.toLowerCase().includes(query.trim().toLowerCase())) : options;
3247
+ const { query, setQuery, filtered } = useSelectSearch(options, (option)=>option.label);
2935
3248
  const current = value == null ? "" : String(value);
2936
3249
  const isActor = column.editor === "actor";
2937
3250
  return /*#__PURE__*/ jsxRuntime.jsxs(SelectRoot, {
@@ -2961,40 +3274,17 @@ function ReferenceEditor({ column, value, pending, onCommit, onCancel }) {
2961
3274
  /*#__PURE__*/ jsxRuntime.jsx(SelectPositioner, {
2962
3275
  children: /*#__PURE__*/ jsxRuntime.jsxs(SelectContent, {
2963
3276
  children: [
2964
- /*#__PURE__*/ jsxRuntime.jsx(TextFieldRoot, {
2965
- size: "medium",
2966
- style: {
2967
- margin: 4
2968
- },
2969
- onKeyDown: (event)=>{
2970
- // The listbox's own typeahead/arrow handling lives on THIS field's
2971
- // sibling items, not on the field itself -- stop everything except
2972
- // Escape from also driving the listbox's own keyboard nav. Escape
2973
- // itself needs no special-casing to "reach" anything any more: it's
2974
- // SelectContent's own `DismissibleLayer` (Select.tsx) that closes the
2975
- // listbox, and that dismissal is a document-level listener outside
2976
- // this React subtree entirely -- a synthetic `stopPropagation` here
2977
- // was never able to block it either way, so the controlled `open`
2978
- // above (via `onOpenChange`) is what actually ends this cell's edit.
2979
- if (event.key !== "Escape") event.stopPropagation();
2980
- },
2981
- children: /*#__PURE__*/ jsxRuntime.jsx(TextFieldInput, {
2982
- autoFocus: true,
2983
- "aria-label": isActor ? "Search people" : `Search ${column.key}`,
2984
- placeholder: isActor ? "Search people…" : "Search…",
2985
- value: query,
2986
- onChange: (event)=>setQuery(event.target.value)
2987
- })
3277
+ /*#__PURE__*/ jsxRuntime.jsx(SelectSearchField, {
3278
+ autoFocus: true,
3279
+ value: query,
3280
+ onChange: setQuery,
3281
+ placeholder: column.refSearchPlaceholder ?? (isActor ? "Search people…" : "Search…"),
3282
+ "aria-label": isActor ? "Search people" : `Search ${column.key}`
2988
3283
  }),
2989
3284
  /*#__PURE__*/ jsxRuntime.jsxs(SelectScrollArea, {
2990
3285
  children: [
2991
- filtered.length === 0 && /*#__PURE__*/ jsxRuntime.jsx("div", {
2992
- style: {
2993
- padding: "6px 12px",
2994
- opacity: 0.63,
2995
- fontSize: 13
2996
- },
2997
- children: isActor ? "No users" : "No results"
3286
+ filtered.length === 0 && /*#__PURE__*/ jsxRuntime.jsx(SelectSearchEmpty, {
3287
+ children: column.refEmptyLabel ?? (isActor ? "No users" : "No results")
2998
3288
  }),
2999
3289
  filtered.map((option)=>/*#__PURE__*/ jsxRuntime.jsxs(SelectItem, {
3000
3290
  value: option.value,
@@ -3370,7 +3660,7 @@ function DisplayCellContent({ column, row, value, classNames, locale }) {
3370
3660
  }
3371
3661
  }
3372
3662
 
3373
- const { ClassNamesProvider: ClassNamesProvider$1, withContext: withContext$1, useClassNames: useClassNames$1 } = createSlotRecipeContext(menu.menu);
3663
+ const { ClassNamesProvider, withContext, useClassNames } = createSlotRecipeContext(menu.menu);
3374
3664
  const { PropsProvider: ItemPropsProvider, useProps: useItemProps, withContext: withItemContext, ClassNamesProvider: ItemClassNamesProvider } = createSlotRecipeContext(menuItem.menuItem);
3375
3665
  const withStateProps = createWithStateProps([
3376
3666
  reactMenu.useMenuContext
@@ -3381,7 +3671,7 @@ const withItemStateProps = createWithStateProps([
3381
3671
  const MenuRoot = (props)=>{
3382
3672
  const [variantProps, otherProps] = menu.menu.splitVariantProps(props);
3383
3673
  const classNames = menu.menu(variantProps);
3384
- return /*#__PURE__*/ jsxRuntime.jsx(ClassNamesProvider$1, {
3674
+ return /*#__PURE__*/ jsxRuntime.jsx(ClassNamesProvider, {
3385
3675
  value: classNames,
3386
3676
  children: /*#__PURE__*/ jsxRuntime.jsx(ItemPropsProvider, {
3387
3677
  value: {
@@ -3396,7 +3686,7 @@ const MenuRoot = (props)=>{
3396
3686
  reactMenu.Menu.Anchor;
3397
3687
  const MenuTrigger = reactMenu.Menu.Trigger;
3398
3688
  const MenuPositioner = /*#__PURE__*/ React__namespace.forwardRef(({ className, ...props }, ref)=>{
3399
- const classNames = useClassNames$1();
3689
+ const classNames = useClassNames();
3400
3690
  return /*#__PURE__*/ jsxRuntime.jsx(reactMenu.Menu.Positioner, {
3401
3691
  ref: ref,
3402
3692
  className: clsx(classNames.positioner, className),
@@ -3404,10 +3694,10 @@ const MenuPositioner = /*#__PURE__*/ React__namespace.forwardRef(({ className, .
3404
3694
  });
3405
3695
  });
3406
3696
  MenuPositioner.displayName = "MenuPositioner";
3407
- const MenuContent = withContext$1(reactMenu.Menu.Content, "content");
3408
- const MenuScrollArea = withContext$1(withStateProps(Primitive.div), "scrollArea");
3409
- withContext$1(reactMenu.Menu.Group, "group");
3410
- withContext$1(reactMenu.Menu.GroupLabel, "groupLabel");
3697
+ const MenuContent = withContext(reactMenu.Menu.Content, "content");
3698
+ const MenuScrollArea = withContext(withStateProps(Primitive.div), "scrollArea");
3699
+ withContext(reactMenu.Menu.Group, "group");
3700
+ withContext(reactMenu.Menu.GroupLabel, "groupLabel");
3411
3701
  const MenuItem = /*#__PURE__*/ React__namespace.forwardRef(({ className: propClassName, ...props }, ref)=>{
3412
3702
  const [variantProps, otherProps] = menuItem.menuItem.splitVariantProps(props);
3413
3703
  const parentProps = useItemProps();
@@ -3826,187 +4116,6 @@ function ColumnRenameInput({ column, initialLabel, onDone }) {
3826
4116
  });
3827
4117
  }
3828
4118
 
3829
- __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__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))}");
3830
-
3831
- const createClassName = (className, variants, compoundVariants = [])=>{
3832
- const variantKeys = Object.keys(variants);
3833
- const variantValues = variantKeys.map((key)=>variants[key]);
3834
- const variantClassName = variantKeys.map((key, index)=>`${className}--${key}_${variantValues[index]}`).join(" ");
3835
- const compountVariantClassName = compoundVariants.filter((compoundVariant)=>Object.keys(compoundVariant).every((key)=>compoundVariant[key] === variants[key])).map((compoundVariant)=>`${className}--${Object.keys(compoundVariant).map((key)=>{
3836
- return `${key}_${compoundVariant[key]}`;
3837
- }).join("-")}`).join(" ");
3838
- return [
3839
- className,
3840
- variantClassName,
3841
- compountVariantClassName
3842
- ].filter(Boolean).join(" ");
3843
- };
3844
- function mergeVariants(a, b) {
3845
- const result = {
3846
- ...a
3847
- };
3848
- for(const k in b){
3849
- if (b[k] != null) {
3850
- result[k] = b[k];
3851
- }
3852
- }
3853
- return result;
3854
- }
3855
- function splitVariantProps(props, variantMap) {
3856
- const variantProps = {};
3857
- const otherProps = {};
3858
- for(const key in props){
3859
- if (variantMap[key] != null) {
3860
- variantProps[key] = props[key];
3861
- } else {
3862
- otherProps[key] = props[key];
3863
- }
3864
- }
3865
- return [
3866
- variantProps,
3867
- otherProps
3868
- ];
3869
- }
3870
-
3871
- const dataTableSlotNames = [
3872
- [
3873
- "root",
3874
- "seed-data-table__root"
3875
- ],
3876
- [
3877
- "table",
3878
- "seed-data-table__table"
3879
- ],
3880
- [
3881
- "header",
3882
- "seed-data-table__header"
3883
- ],
3884
- [
3885
- "headerCell",
3886
- "seed-data-table__headerCell"
3887
- ],
3888
- [
3889
- "headerCellInner",
3890
- "seed-data-table__headerCellInner"
3891
- ],
3892
- [
3893
- "headerCellLabel",
3894
- "seed-data-table__headerCellLabel"
3895
- ],
3896
- [
3897
- "headerCellIcon",
3898
- "seed-data-table__headerCellIcon"
3899
- ],
3900
- [
3901
- "row",
3902
- "seed-data-table__row"
3903
- ],
3904
- [
3905
- "cell",
3906
- "seed-data-table__cell"
3907
- ],
3908
- [
3909
- "entity",
3910
- "seed-data-table__entity"
3911
- ],
3912
- [
3913
- "entityName",
3914
- "seed-data-table__entityName"
3915
- ],
3916
- [
3917
- "tagList",
3918
- "seed-data-table__tagList"
3919
- ],
3920
- [
3921
- "link",
3922
- "seed-data-table__link"
3923
- ],
3924
- [
3925
- "toolbar",
3926
- "seed-data-table__toolbar"
3927
- ],
3928
- [
3929
- "search",
3930
- "seed-data-table__search"
3931
- ],
3932
- [
3933
- "count",
3934
- "seed-data-table__count"
3935
- ],
3936
- [
3937
- "toolbarEnd",
3938
- "seed-data-table__toolbarEnd"
3939
- ],
3940
- [
3941
- "scrollArea",
3942
- "seed-data-table__scrollArea"
3943
- ],
3944
- [
3945
- "footer",
3946
- "seed-data-table__footer"
3947
- ],
3948
- [
3949
- "footerCell",
3950
- "seed-data-table__footerCell"
3951
- ],
3952
- [
3953
- "emptyState",
3954
- "seed-data-table__emptyState"
3955
- ],
3956
- [
3957
- "loadingState",
3958
- "seed-data-table__loadingState"
3959
- ],
3960
- [
3961
- "addRow",
3962
- "seed-data-table__addRow"
3963
- ],
3964
- [
3965
- "addRowCell",
3966
- "seed-data-table__addRowCell"
3967
- ],
3968
- [
3969
- "selectionCell",
3970
- "seed-data-table__selectionCell"
3971
- ]
3972
- ];
3973
- const defaultVariant$4 = {
3974
- "surface": "card",
3975
- "interactive": false
3976
- };
3977
- const compoundVariants$4 = [];
3978
- const dataTableVariantMap = {
3979
- "surface": [
3980
- "card",
3981
- "bleed"
3982
- ],
3983
- "interactive": [
3984
- true,
3985
- false
3986
- ]
3987
- };
3988
- function dataTable(props) {
3989
- return Object.fromEntries(dataTableSlotNames.map(([slot, className])=>{
3990
- return [
3991
- slot,
3992
- createClassName(className, mergeVariants(defaultVariant$4, props), compoundVariants$4)
3993
- ];
3994
- }));
3995
- }
3996
- Object.assign(dataTable, {
3997
- splitVariantProps: (props)=>splitVariantProps(props, dataTableVariantMap)
3998
- }); // @recipe(seed): data-table
3999
-
4000
- // The one `createSlotRecipeContext(dataTable)` call every sibling file in this
4001
- // directory shares -- `ClassNamesProvider` and `withContext` must be the SAME
4002
- // binding everywhere (a slot component built from a second, independent call would
4003
- // read a DIFFERENT React context and never see the classNames `DataTableInner`
4004
- // provides), so this is the one place that calls `createSlotRecipeContext`, and every
4005
- // other file (`DataTable.tsx`, `column-menu.tsx`, `resize.tsx`, `column-calc.tsx`,
4006
- // `toolbar.tsx`, `body-cells.tsx`, `editors.tsx`) imports its exports from here rather
4007
- // than re-deriving its own.
4008
- const { ClassNamesProvider, withContext, useClassNames } = createSlotRecipeContext(dataTable);
4009
-
4010
4119
  /**
4011
4120
  * A small inline spinner, not seed's own `ProgressCircle` -- that component's
4012
4121
  * smallest size (24px) is already bigger than crisp's own measured 16px loading
@@ -9649,8 +9758,8 @@ const formatFilterDate = (iso)=>{
9649
9758
  });
9650
9759
  }
9651
9760
 
9652
- const DataTableToolbar = withContext(Primitive.div, "toolbar");
9653
- const DataTableCount = withContext(Primitive.span, "count");
9761
+ const DataTableToolbar = withContext$1(Primitive.div, "toolbar");
9762
+ const DataTableCount = withContext$1(Primitive.span, "count");
9654
9763
  /**
9655
9764
  * The toolbar's own right-hand group -- `count`'s `marginInlineStart: auto` moved
9656
9765
  * here (off the `<span>` itself) so a consumer's `toolbarActions` and the row count
@@ -9661,7 +9770,7 @@ const DataTableCount = withContext(Primitive.span, "count");
9661
9770
  * it. `DataTable.tsx` always renders this wrapper once either `toolbarActions` or
9662
9771
  * `showCount` is on, so it degrades to exactly the old single-count layout when no
9663
9772
  * `toolbarActions` is passed.
9664
- */ const DataTableToolbarEnd = withContext(Primitive.div, "toolbarEnd");
9773
+ */ const DataTableToolbarEnd = withContext$1(Primitive.div, "toolbarEnd");
9665
9774
  /**
9666
9775
  * A compact, borderless search box -- crisp's own measured `.crisp-datatable-search`
9667
9776
  * (32px, `bgSurface` background, a leading icon, a soft rest-state shadow, a 1px brand
@@ -9816,7 +9925,7 @@ function DataTableInner(props, ref) {
9816
9925
  // loading/error/empty body, infinite scroll's sentinel, the add-row footer) reads
9817
9926
  // this ONE value rather than each re-deriving it, so they can never drift apart.
9818
9927
  const totalCols = columns.length + (selectable ? 1 : 0);
9819
- return /*#__PURE__*/ jsxRuntime.jsx(ClassNamesProvider, {
9928
+ return /*#__PURE__*/ jsxRuntime.jsx(ClassNamesProvider$1, {
9820
9929
  value: classNames,
9821
9930
  children: /*#__PURE__*/ jsxRuntime.jsxs(DataTableRoot, {
9822
9931
  ref: ref,
@@ -10071,7 +10180,7 @@ DataTableInner.displayName = "DataTable";
10071
10180
  // is a SIBLING of the toolbar (both inside `DataTablePrimitiveRoot`'s card `<div>`)
10072
10181
  // rather than `DataTablePrimitiveRoot` itself: a `<table>` cannot host the toolbar as a
10073
10182
  // child without the HTML parser foster-parenting it back out.
10074
- const DataTableTable = withContext(DataTableTable$1, "table");
10183
+ const DataTableTable = withContext$1(DataTableTable$1, "table");
10075
10184
  /** One `<col>` per rendered column (plus the 40px selection column, if any) -- the
10076
10185
  * SINGLE place a column's width is ever set now. Every row's header/body/footer cell
10077
10186
  * reads its own width off this shared `<colgroup>` by construction (native table
@@ -10096,15 +10205,15 @@ const DataTableTable = withContext(DataTableTable$1, "table");
10096
10205
  ]
10097
10206
  });
10098
10207
  }
10099
- const DataTableHeader = withContext(DataTableHeader$1, "header");
10100
- const DataTableHeaderCell = withContext(DataTableHeaderCell$1, "headerCell");
10208
+ const DataTableHeader = withContext$1(DataTableHeader$1, "header");
10209
+ const DataTableHeaderCell = withContext$1(DataTableHeaderCell$1, "headerCell");
10101
10210
  // `.crisp-datatable-th-inner` -- the flex row INSIDE a `<th>` (label + filter trigger +
10102
10211
  // sort chevron + column menu). See qvism-preset's own `headerCellInner` slot comment
10103
10212
  // for why this lives one level below the cell itself rather than on it.
10104
- const DataTableHeaderCellInner = withContext(Primitive.div, "headerCellInner");
10213
+ const DataTableHeaderCellInner = withContext$1(Primitive.div, "headerCellInner");
10105
10214
  /** The label text specifically -- the one thing in `DataTableHeaderCellInner` that
10106
10215
  * truncates; the trailing filter/sort/menu icons stay fully visible regardless of how
10107
- * long a column's own header text is. */ const DataTableHeaderCellLabel = withContext(Primitive.span, "headerCellLabel");
10216
+ * long a column's own header text is. */ const DataTableHeaderCellLabel = withContext$1(Primitive.span, "headerCellLabel");
10108
10217
  /**
10109
10218
  * A selection `<th>`/`<td>`/footer `<td>` composes ITS base slot (`headerCell`/`cell`/
10110
10219
  * `footerCell`) together with the `selectionCell` MODIFIER, rather than replacing it --
@@ -10115,7 +10224,7 @@ const DataTableHeaderCellInner = withContext(Primitive.div, "headerCellInner");
10115
10224
  * a second recipe call.
10116
10225
  */ function withSelectionCell(Component, baseSlot) {
10117
10226
  const StyledComponent = /*#__PURE__*/ React.forwardRef((props, ref)=>{
10118
- const classNames = useClassNames();
10227
+ const classNames = useClassNames$1();
10119
10228
  return /*#__PURE__*/ jsxRuntime.jsx(Component, {
10120
10229
  ref: ref,
10121
10230
  ...props,
@@ -10126,12 +10235,12 @@ const DataTableHeaderCellInner = withContext(Primitive.div, "headerCellInner");
10126
10235
  return StyledComponent;
10127
10236
  }
10128
10237
  const DataTableSelectionHeaderCell = withSelectionCell(DataTableHeaderCell$1, "headerCell");
10129
- const DataTableHeaderCellIcon = withContext(Primitive.span, "headerCellIcon");
10238
+ const DataTableHeaderCellIcon = withContext$1(Primitive.span, "headerCellIcon");
10130
10239
  // body has no CSS slot of its own in the rootage spec -- it is a plain structural
10131
10240
  // `<tbody>`, so it is not wrapped in `withContext`.
10132
10241
  const DataTableBody = DataTableBody$1;
10133
- const DataTableRow = withContext(DataTableRow$1, "row");
10134
- const DataTableCell = withContext(DataTableCell$1, "cell");
10242
+ const DataTableRow = withContext$1(DataTableRow$1, "row");
10243
+ const DataTableCell = withContext$1(DataTableCell$1, "cell");
10135
10244
  const DataTableSelectionCell = withSelectionCell(DataTableCell$1, "cell");
10136
10245
  // Tranche 4 -- column menu + reorder + resize + sticky columns. A scroll boundary
10137
10246
  // wrapping the whole `<table>`: `overflowX: auto` is what makes a wide table (more
@@ -10141,7 +10250,7 @@ const DataTableSelectionCell = withSelectionCell(DataTableCell$1, "cell");
10141
10250
  // stays out of this slot's own base css (nothing here has a bounded height of its own
10142
10251
  // to clip), so it never introduces a second vertical scrollbar next to whatever
10143
10252
  // ambient container the whole DataTable already sits in.
10144
- const DataTableScrollBodyBase = withContext(Primitive.div, "scrollArea");
10253
+ const DataTableScrollBodyBase = withContext$1(Primitive.div, "scrollArea");
10145
10254
  function DataTableScrollBody({ children, scrollProps }) {
10146
10255
  const { scrollAreaRef, scrolledStart, scrolledEnd, onScroll } = useDataTableContext();
10147
10256
  const { className: scrollClassName, style: scrollStyle, ...otherScrollProps } = scrollProps ?? {};
@@ -10156,7 +10265,7 @@ function DataTableScrollBody({ children, scrollProps }) {
10156
10265
  children: children
10157
10266
  });
10158
10267
  }
10159
- const DataTableFooterBase = withContext(Primitive.tfoot, "footer");
10268
+ const DataTableFooterBase = withContext$1(Primitive.tfoot, "footer");
10160
10269
  function DataTableFooter({ children, ...props }) {
10161
10270
  return /*#__PURE__*/ jsxRuntime.jsx(DataTableFooterBase, {
10162
10271
  ...props,
@@ -10165,7 +10274,7 @@ function DataTableFooter({ children, ...props }) {
10165
10274
  })
10166
10275
  });
10167
10276
  }
10168
- const DataTableFooterCell = withContext(Primitive.td, "footerCell");
10277
+ const DataTableFooterCell = withContext$1(Primitive.td, "footerCell");
10169
10278
  ////////////////////////////////////////////////////////////////////////////////////
10170
10279
  // Fix (bug report): karrot icons default to a 24px intrinsic SVG attribute size
10171
10280
  // -- see column-menu.tsx's own `SORT_ICON_SIZE` comment for the full mechanism.