@crispy-seed/data-table 0.10.4 → 0.10.5

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.
Files changed (3) hide show
  1. package/dist/index.cjs +138 -17
  2. package/dist/index.js +138 -17
  3. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -1696,24 +1696,33 @@ function useDataTableSort(props) {
1696
1696
  // already passes its "cleared" shape through unconditionally; this now matches.
1697
1697
  onChange: onSortChange
1698
1698
  });
1699
+ // 3-state cycle (DATATABLE-ATTIO-SPEC.md: "asc/desc/none cycle") -- clicking a
1700
+ // DIFFERENT column always starts it fresh at asc, discarding whatever the previous
1701
+ // column's direction was (this stays a SINGLE-column secondary affordance, never a
1702
+ // second multi-sort list of its own). Clicking the SAME column steps asc -> desc ->
1703
+ // undefined ("none", i.e. this column drops out of the sort entirely) -> asc again.
1704
+ // Before this, the cycle wrapped desc -> asc forever, with no click-driven way back
1705
+ // to unsorted at all (a reported gap: "sort asc/desc has no option for no sort on
1706
+ // columns") -- `clearSort` below was the ONLY way there, now it's one of two.
1699
1707
  const toggleSort = React.useCallback((key)=>{
1700
1708
  setSort((current)=>{
1701
1709
  if (!current || current.key !== key) return {
1702
1710
  key,
1703
1711
  dir: "asc"
1704
1712
  };
1705
- return {
1713
+ if (current.dir === "asc") return {
1706
1714
  key,
1707
- dir: current.dir === "asc" ? "desc" : "asc"
1715
+ dir: "desc"
1708
1716
  };
1717
+ return undefined;
1709
1718
  });
1710
1719
  }, [
1711
1720
  setSort
1712
1721
  ]);
1713
- /** Attio/GRC's "Remove sort" -- the header click cycle (above) only ever toggles
1714
- * asc/desc once a column has been clicked once; this is the only way back to no
1715
- * sort at all. Exposed for a column's own header menu (`column-menu.tsx`'s
1716
- * `ColumnMenu`) to offer as a "Clear sort" item when that column is the sorted one. */ const clearSort = React.useCallback(()=>setSort(undefined), [
1722
+ /** Attio/GRC's "Remove sort" -- a second way back to no sort at all (the header
1723
+ * click cycle above reaches it too, on a column's third click), exposed for a
1724
+ * column's own header menu (`column-menu.tsx`'s `ColumnMenu`) to offer as a
1725
+ * "Clear sort" item when that column is the sorted one, without three clicks. */ const clearSort = React.useCallback(()=>setSort(undefined), [
1717
1726
  setSort
1718
1727
  ]);
1719
1728
  const getHeaderCellProps = React.useCallback((columnKey, sortable)=>{
@@ -1746,7 +1755,12 @@ function useDataTableSort(props) {
1746
1755
  sort,
1747
1756
  toggleSort,
1748
1757
  clearSort,
1749
- getHeaderCellProps
1758
+ getHeaderCellProps,
1759
+ // Exposed for `useDataTable.ts`'s own composition ONLY (unifying this single
1760
+ // click-to-sort column with `useDataTableToolbarSort`'s ordered list) -- not part
1761
+ // of the documented header-click contract (`toggleSort`/`clearSort` above are),
1762
+ // so no consumer-facing doc comment promotes it as a control of its own.
1763
+ setSort
1750
1764
  };
1751
1765
  }
1752
1766
 
@@ -1850,11 +1864,14 @@ const EMPTY_SORTS = [];
1850
1864
  * concern rather than folded into `useDataTableSort` (DATATABLE-ATTIO-SPEC.md: "compose,
1851
1865
  * don't fatten one hook"). `useDataTableSort` still owns the single click-to-sort
1852
1866
  * column/direction a header's own click toggles -- that stays Attio's SECONDARY sort
1853
- * affordance, untouched by this hook. This one is the PRIMARY toolbar Sort control: add
1854
- * a condition, pick its field/direction, reorder, remove -- multiple conditions apply in
1855
- * list order (sort[0] wins, later ones break ties; see the styled layer's
1856
- * `applyToolbarSorts`). The styled layer decides how the two combine (DataTable.tsx:
1857
- * toolbar sorts win when any exist, the single click-to-sort column otherwise).
1867
+ * affordance, a separate hook from this one. They are NOT independent state, though:
1868
+ * `useDataTable.ts`'s own composition keeps a header-driven column's entry in THIS
1869
+ * array in sync (added/updated/removed as that column's header cycles asc/desc/none),
1870
+ * so a consumer controlling only `toolbarSorts`/`onToolbarSortsChange` still sees a
1871
+ * header click, and the toolbar's own "Remove sort" x on that same entry clears the
1872
+ * header's side too. Multiple conditions apply in list order (sort[0] wins, later ones
1873
+ * break ties; see the styled layer's `applyToolbarSorts`). The styled layer
1874
+ * (`DataTable.tsx`) decides how the merged result actually sorts `data`.
1858
1875
  */ function useDataTableToolbarSort(props) {
1859
1876
  const { toolbarSorts: sortsProp, defaultToolbarSorts = EMPTY_SORTS, onToolbarSortsChange } = props;
1860
1877
  const [toolbarSorts = EMPTY_SORTS, setToolbarSorts] = useControllableState$1({
@@ -1939,8 +1956,13 @@ const EMPTY_SORTS = [];
1939
1956
  // header "is/is not" picker) -- DATATABLE-ATTIO-SPEC.md's Attio/crisp `TableToolbar`
1940
1957
  // model is now the PRIMARY filter/sort UX, not a per-column header affordance. They stay
1941
1958
  // SEPARATE sub-hooks from `useDataTableSort` rather than folded into it ("compose, don't
1942
- // fatten one hook") -- the styled layer decides how the toolbar's multi-condition sort
1943
- // and the header's single click-to-sort combine (DataTable.tsx).
1959
+ // fatten one hook") -- but this composition point below DOES reconcile the two into one
1960
+ // state (the two `useEffect`s after `infiniteScroll`), so a header click and the
1961
+ // toolbar's own Sort popover always agree on what's sorted, regardless of which prop
1962
+ // pair (`sort`/`onSortChange` or `toolbarSorts`/`onToolbarSortsChange`) a consumer
1963
+ // actually controls. `DataTable.tsx` (styled) still decides how the RESULT actually
1964
+ // sorts `data` (`effectiveSorts`/`applyToolbarSorts`) -- this layer only keeps the two
1965
+ // STATE pools in agreement.
1944
1966
  function useDataTable(props) {
1945
1967
  const sort = useDataTableSort(props);
1946
1968
  const selection = useDataTableSelection(props);
@@ -1963,6 +1985,105 @@ function useDataTable(props) {
1963
1985
  ...props,
1964
1986
  scrollRootRef: scroll.elementRef
1965
1987
  });
1988
+ // Unifies `sort` (the header's own single click-to-sort column, above) with
1989
+ // `toolbarSort.toolbarSorts` (the toolbar Sort popover's ordered list, above) into
1990
+ // ONE state instead of two -- before this, a header click only ever moved `sort`,
1991
+ // invisible to a consumer controlling `toolbarSorts`/`onToolbarSortsChange` (the
1992
+ // reported bug: clicking a header did nothing to the array the consumer's own Sort
1993
+ // popover reads, so the toolbar's "Sort" trigger/count and its popover rows silently
1994
+ // ignored every header click).
1995
+ //
1996
+ // ONE effect, not two -- an earlier version split this into a forward
1997
+ // (`sort` -> `toolbarSorts`) and a reverse (`toolbarSorts` -> `sort`) effect, each
1998
+ // keyed off its own dependency. That raced on the very first render: `useEffect`
1999
+ // runs every effect once on mount regardless of what "changed", so with
2000
+ // `defaultSort` set, the reverse effect ran in the SAME commit as the forward one,
2001
+ // read `toolbarSorts` BEFORE the forward effect's own (still-queued, not yet
2002
+ // re-rendered) write had landed, saw no entry for the column yet, and immediately
2003
+ // cleared `sort` right back out -- the defaultSort silently never took effect.
2004
+ // `settledRef` sidesteps this: it remembers the last `{key,dir}` this effect itself
2005
+ // confirmed, so on every run it can tell WHICH side moved since then, instead of
2006
+ // guessing from which dependency happens to have triggered the re-run.
2007
+ const settledRef = React.useRef({
2008
+ key: undefined,
2009
+ dir: undefined
2010
+ });
2011
+ React.useEffect(()=>{
2012
+ const curSort = sort.sort;
2013
+ const curEntry = curSort ? toolbarSort.toolbarSorts.find((s)=>s.key === curSort.key) : undefined;
2014
+ const settled = settledRef.current;
2015
+ const sortUnchangedSinceSettled = settled.key === curSort?.key && settled.dir === curSort?.dir;
2016
+ if (sortUnchangedSinceSettled) {
2017
+ // `sort` itself hasn't moved since we last settled -- if this effect is running
2018
+ // at all, `toolbarSorts` is what changed, so REVERSE-sync: the toolbar Sort
2019
+ // popover's own "Remove sort" x, or its direction select, touching this exact
2020
+ // column. Never reaches across to adopt some OTHER column added independently
2021
+ // via that popover -- only the column `sort` is already tracking.
2022
+ if (!curSort) return;
2023
+ if (!curEntry) {
2024
+ sort.clearSort();
2025
+ settledRef.current = {
2026
+ key: undefined,
2027
+ dir: undefined
2028
+ };
2029
+ } else if (curEntry.dir !== curSort.dir) {
2030
+ sort.setSort({
2031
+ key: curSort.key,
2032
+ dir: curEntry.dir
2033
+ });
2034
+ settledRef.current = {
2035
+ key: curSort.key,
2036
+ dir: curEntry.dir
2037
+ };
2038
+ }
2039
+ return;
2040
+ }
2041
+ // `sort` moved (a header click, Enter/Space, or `clearSort` -- column-menu.tsx's
2042
+ // menu item calls that directly, bypassing `toggleSort`) -- FORWARD-sync:
2043
+ // add/update/remove THIS column's own entry in `toolbarSorts`, leaving every
2044
+ // OTHER entry (added independently via the toolbar's own "+ Add sort") untouched.
2045
+ // The functional updater reads the CURRENT array off `current`, never off
2046
+ // `toolbarSort.toolbarSorts` in this closure, so a stale render can never clobber
2047
+ // an entry the toolbar's own popover added a moment earlier.
2048
+ const prevKey = settled.key;
2049
+ toolbarSort.setToolbarSorts((current)=>{
2050
+ let updated = current;
2051
+ if (prevKey && prevKey !== curSort?.key) {
2052
+ updated = updated.filter((s)=>s.key !== prevKey);
2053
+ }
2054
+ if (curSort) {
2055
+ const idx = updated.findIndex((s)=>s.key === curSort.key);
2056
+ if (idx === -1) {
2057
+ updated = [
2058
+ ...updated,
2059
+ {
2060
+ key: curSort.key,
2061
+ dir: curSort.dir
2062
+ }
2063
+ ];
2064
+ } else if (updated[idx].dir !== curSort.dir) {
2065
+ updated = updated.map((s, i)=>i === idx ? {
2066
+ ...s,
2067
+ dir: curSort.dir
2068
+ } : s);
2069
+ }
2070
+ }
2071
+ return updated;
2072
+ });
2073
+ settledRef.current = curSort ? {
2074
+ key: curSort.key,
2075
+ dir: curSort.dir
2076
+ } : {
2077
+ key: undefined,
2078
+ dir: undefined
2079
+ };
2080
+ }, [
2081
+ sort.sort,
2082
+ toolbarSort.toolbarSorts,
2083
+ toolbarSort.setToolbarSorts,
2084
+ sort.clearSort,
2085
+ sort.setSort
2086
+ ]);
1966
2087
  return {
1967
2088
  ...sort,
1968
2089
  ...selection,
@@ -5400,9 +5521,9 @@ function ColumnRenameInput({ column, initialLabel, onDone }) {
5400
5521
  const columnLabel = typeof label === "string" ? label : column.key;
5401
5522
  const pinned = isColumnPinned(column.key);
5402
5523
  // Attio/GRC's "Remove sort" (live-review fix D) -- the header's own click-to-sort
5403
- // (`SortIndicator`/`toggleSort`, above) only cycles asc/desc once a column has been
5404
- // clicked; this is the only affordance back to no sort at all, so it only makes
5405
- // sense to show on the column that IS currently sorted.
5524
+ // (`SortIndicator`/`toggleSort`, above) already cycles asc -> desc -> none on its
5525
+ // own third click, but this stays as a one-click shortcut to the same place, so it
5526
+ // only makes sense to show on the column that IS currently sorted.
5406
5527
  const isSorted = sort?.key === column.key;
5407
5528
  const stopPropagation = (event)=>event.stopPropagation();
5408
5529
  return(// Live-review fix (D): a `MenuItem` inside `MenuPositioner` renders through a
package/dist/index.js CHANGED
@@ -1677,24 +1677,33 @@ function useDataTableSort(props) {
1677
1677
  // already passes its "cleared" shape through unconditionally; this now matches.
1678
1678
  onChange: onSortChange
1679
1679
  });
1680
+ // 3-state cycle (DATATABLE-ATTIO-SPEC.md: "asc/desc/none cycle") -- clicking a
1681
+ // DIFFERENT column always starts it fresh at asc, discarding whatever the previous
1682
+ // column's direction was (this stays a SINGLE-column secondary affordance, never a
1683
+ // second multi-sort list of its own). Clicking the SAME column steps asc -> desc ->
1684
+ // undefined ("none", i.e. this column drops out of the sort entirely) -> asc again.
1685
+ // Before this, the cycle wrapped desc -> asc forever, with no click-driven way back
1686
+ // to unsorted at all (a reported gap: "sort asc/desc has no option for no sort on
1687
+ // columns") -- `clearSort` below was the ONLY way there, now it's one of two.
1680
1688
  const toggleSort = useCallback((key)=>{
1681
1689
  setSort((current)=>{
1682
1690
  if (!current || current.key !== key) return {
1683
1691
  key,
1684
1692
  dir: "asc"
1685
1693
  };
1686
- return {
1694
+ if (current.dir === "asc") return {
1687
1695
  key,
1688
- dir: current.dir === "asc" ? "desc" : "asc"
1696
+ dir: "desc"
1689
1697
  };
1698
+ return undefined;
1690
1699
  });
1691
1700
  }, [
1692
1701
  setSort
1693
1702
  ]);
1694
- /** Attio/GRC's "Remove sort" -- the header click cycle (above) only ever toggles
1695
- * asc/desc once a column has been clicked once; this is the only way back to no
1696
- * sort at all. Exposed for a column's own header menu (`column-menu.tsx`'s
1697
- * `ColumnMenu`) to offer as a "Clear sort" item when that column is the sorted one. */ const clearSort = useCallback(()=>setSort(undefined), [
1703
+ /** Attio/GRC's "Remove sort" -- a second way back to no sort at all (the header
1704
+ * click cycle above reaches it too, on a column's third click), exposed for a
1705
+ * column's own header menu (`column-menu.tsx`'s `ColumnMenu`) to offer as a
1706
+ * "Clear sort" item when that column is the sorted one, without three clicks. */ const clearSort = useCallback(()=>setSort(undefined), [
1698
1707
  setSort
1699
1708
  ]);
1700
1709
  const getHeaderCellProps = useCallback((columnKey, sortable)=>{
@@ -1727,7 +1736,12 @@ function useDataTableSort(props) {
1727
1736
  sort,
1728
1737
  toggleSort,
1729
1738
  clearSort,
1730
- getHeaderCellProps
1739
+ getHeaderCellProps,
1740
+ // Exposed for `useDataTable.ts`'s own composition ONLY (unifying this single
1741
+ // click-to-sort column with `useDataTableToolbarSort`'s ordered list) -- not part
1742
+ // of the documented header-click contract (`toggleSort`/`clearSort` above are),
1743
+ // so no consumer-facing doc comment promotes it as a control of its own.
1744
+ setSort
1731
1745
  };
1732
1746
  }
1733
1747
 
@@ -1831,11 +1845,14 @@ const EMPTY_SORTS = [];
1831
1845
  * concern rather than folded into `useDataTableSort` (DATATABLE-ATTIO-SPEC.md: "compose,
1832
1846
  * don't fatten one hook"). `useDataTableSort` still owns the single click-to-sort
1833
1847
  * column/direction a header's own click toggles -- that stays Attio's SECONDARY sort
1834
- * affordance, untouched by this hook. This one is the PRIMARY toolbar Sort control: add
1835
- * a condition, pick its field/direction, reorder, remove -- multiple conditions apply in
1836
- * list order (sort[0] wins, later ones break ties; see the styled layer's
1837
- * `applyToolbarSorts`). The styled layer decides how the two combine (DataTable.tsx:
1838
- * toolbar sorts win when any exist, the single click-to-sort column otherwise).
1848
+ * affordance, a separate hook from this one. They are NOT independent state, though:
1849
+ * `useDataTable.ts`'s own composition keeps a header-driven column's entry in THIS
1850
+ * array in sync (added/updated/removed as that column's header cycles asc/desc/none),
1851
+ * so a consumer controlling only `toolbarSorts`/`onToolbarSortsChange` still sees a
1852
+ * header click, and the toolbar's own "Remove sort" x on that same entry clears the
1853
+ * header's side too. Multiple conditions apply in list order (sort[0] wins, later ones
1854
+ * break ties; see the styled layer's `applyToolbarSorts`). The styled layer
1855
+ * (`DataTable.tsx`) decides how the merged result actually sorts `data`.
1839
1856
  */ function useDataTableToolbarSort(props) {
1840
1857
  const { toolbarSorts: sortsProp, defaultToolbarSorts = EMPTY_SORTS, onToolbarSortsChange } = props;
1841
1858
  const [toolbarSorts = EMPTY_SORTS, setToolbarSorts] = useControllableState$1({
@@ -1920,8 +1937,13 @@ const EMPTY_SORTS = [];
1920
1937
  // header "is/is not" picker) -- DATATABLE-ATTIO-SPEC.md's Attio/crisp `TableToolbar`
1921
1938
  // model is now the PRIMARY filter/sort UX, not a per-column header affordance. They stay
1922
1939
  // SEPARATE sub-hooks from `useDataTableSort` rather than folded into it ("compose, don't
1923
- // fatten one hook") -- the styled layer decides how the toolbar's multi-condition sort
1924
- // and the header's single click-to-sort combine (DataTable.tsx).
1940
+ // fatten one hook") -- but this composition point below DOES reconcile the two into one
1941
+ // state (the two `useEffect`s after `infiniteScroll`), so a header click and the
1942
+ // toolbar's own Sort popover always agree on what's sorted, regardless of which prop
1943
+ // pair (`sort`/`onSortChange` or `toolbarSorts`/`onToolbarSortsChange`) a consumer
1944
+ // actually controls. `DataTable.tsx` (styled) still decides how the RESULT actually
1945
+ // sorts `data` (`effectiveSorts`/`applyToolbarSorts`) -- this layer only keeps the two
1946
+ // STATE pools in agreement.
1925
1947
  function useDataTable(props) {
1926
1948
  const sort = useDataTableSort(props);
1927
1949
  const selection = useDataTableSelection(props);
@@ -1944,6 +1966,105 @@ function useDataTable(props) {
1944
1966
  ...props,
1945
1967
  scrollRootRef: scroll.elementRef
1946
1968
  });
1969
+ // Unifies `sort` (the header's own single click-to-sort column, above) with
1970
+ // `toolbarSort.toolbarSorts` (the toolbar Sort popover's ordered list, above) into
1971
+ // ONE state instead of two -- before this, a header click only ever moved `sort`,
1972
+ // invisible to a consumer controlling `toolbarSorts`/`onToolbarSortsChange` (the
1973
+ // reported bug: clicking a header did nothing to the array the consumer's own Sort
1974
+ // popover reads, so the toolbar's "Sort" trigger/count and its popover rows silently
1975
+ // ignored every header click).
1976
+ //
1977
+ // ONE effect, not two -- an earlier version split this into a forward
1978
+ // (`sort` -> `toolbarSorts`) and a reverse (`toolbarSorts` -> `sort`) effect, each
1979
+ // keyed off its own dependency. That raced on the very first render: `useEffect`
1980
+ // runs every effect once on mount regardless of what "changed", so with
1981
+ // `defaultSort` set, the reverse effect ran in the SAME commit as the forward one,
1982
+ // read `toolbarSorts` BEFORE the forward effect's own (still-queued, not yet
1983
+ // re-rendered) write had landed, saw no entry for the column yet, and immediately
1984
+ // cleared `sort` right back out -- the defaultSort silently never took effect.
1985
+ // `settledRef` sidesteps this: it remembers the last `{key,dir}` this effect itself
1986
+ // confirmed, so on every run it can tell WHICH side moved since then, instead of
1987
+ // guessing from which dependency happens to have triggered the re-run.
1988
+ const settledRef = useRef({
1989
+ key: undefined,
1990
+ dir: undefined
1991
+ });
1992
+ useEffect(()=>{
1993
+ const curSort = sort.sort;
1994
+ const curEntry = curSort ? toolbarSort.toolbarSorts.find((s)=>s.key === curSort.key) : undefined;
1995
+ const settled = settledRef.current;
1996
+ const sortUnchangedSinceSettled = settled.key === curSort?.key && settled.dir === curSort?.dir;
1997
+ if (sortUnchangedSinceSettled) {
1998
+ // `sort` itself hasn't moved since we last settled -- if this effect is running
1999
+ // at all, `toolbarSorts` is what changed, so REVERSE-sync: the toolbar Sort
2000
+ // popover's own "Remove sort" x, or its direction select, touching this exact
2001
+ // column. Never reaches across to adopt some OTHER column added independently
2002
+ // via that popover -- only the column `sort` is already tracking.
2003
+ if (!curSort) return;
2004
+ if (!curEntry) {
2005
+ sort.clearSort();
2006
+ settledRef.current = {
2007
+ key: undefined,
2008
+ dir: undefined
2009
+ };
2010
+ } else if (curEntry.dir !== curSort.dir) {
2011
+ sort.setSort({
2012
+ key: curSort.key,
2013
+ dir: curEntry.dir
2014
+ });
2015
+ settledRef.current = {
2016
+ key: curSort.key,
2017
+ dir: curEntry.dir
2018
+ };
2019
+ }
2020
+ return;
2021
+ }
2022
+ // `sort` moved (a header click, Enter/Space, or `clearSort` -- column-menu.tsx's
2023
+ // menu item calls that directly, bypassing `toggleSort`) -- FORWARD-sync:
2024
+ // add/update/remove THIS column's own entry in `toolbarSorts`, leaving every
2025
+ // OTHER entry (added independently via the toolbar's own "+ Add sort") untouched.
2026
+ // The functional updater reads the CURRENT array off `current`, never off
2027
+ // `toolbarSort.toolbarSorts` in this closure, so a stale render can never clobber
2028
+ // an entry the toolbar's own popover added a moment earlier.
2029
+ const prevKey = settled.key;
2030
+ toolbarSort.setToolbarSorts((current)=>{
2031
+ let updated = current;
2032
+ if (prevKey && prevKey !== curSort?.key) {
2033
+ updated = updated.filter((s)=>s.key !== prevKey);
2034
+ }
2035
+ if (curSort) {
2036
+ const idx = updated.findIndex((s)=>s.key === curSort.key);
2037
+ if (idx === -1) {
2038
+ updated = [
2039
+ ...updated,
2040
+ {
2041
+ key: curSort.key,
2042
+ dir: curSort.dir
2043
+ }
2044
+ ];
2045
+ } else if (updated[idx].dir !== curSort.dir) {
2046
+ updated = updated.map((s, i)=>i === idx ? {
2047
+ ...s,
2048
+ dir: curSort.dir
2049
+ } : s);
2050
+ }
2051
+ }
2052
+ return updated;
2053
+ });
2054
+ settledRef.current = curSort ? {
2055
+ key: curSort.key,
2056
+ dir: curSort.dir
2057
+ } : {
2058
+ key: undefined,
2059
+ dir: undefined
2060
+ };
2061
+ }, [
2062
+ sort.sort,
2063
+ toolbarSort.toolbarSorts,
2064
+ toolbarSort.setToolbarSorts,
2065
+ sort.clearSort,
2066
+ sort.setSort
2067
+ ]);
1947
2068
  return {
1948
2069
  ...sort,
1949
2070
  ...selection,
@@ -5381,9 +5502,9 @@ function ColumnRenameInput({ column, initialLabel, onDone }) {
5381
5502
  const columnLabel = typeof label === "string" ? label : column.key;
5382
5503
  const pinned = isColumnPinned(column.key);
5383
5504
  // Attio/GRC's "Remove sort" (live-review fix D) -- the header's own click-to-sort
5384
- // (`SortIndicator`/`toggleSort`, above) only cycles asc/desc once a column has been
5385
- // clicked; this is the only affordance back to no sort at all, so it only makes
5386
- // sense to show on the column that IS currently sorted.
5505
+ // (`SortIndicator`/`toggleSort`, above) already cycles asc -> desc -> none on its
5506
+ // own third click, but this stays as a one-click shortcut to the same place, so it
5507
+ // only makes sense to show on the column that IS currently sorted.
5387
5508
  const isSorted = sort?.key === column.key;
5388
5509
  const stopPropagation = (event)=>event.stopPropagation();
5389
5510
  return(// Live-review fix (D): a `MenuItem` inside `MenuPositioner` renders through a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crispy-seed/data-table",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "description": "Self-contained, publishable build of seed-design's Attio-measured DataTable, ResizablePanel and RecordPreview — one install, one CSS import.",
5
5
  "repository": {
6
6
  "type": "git",