@astryxdesign/core 0.1.0 → 0.1.1-canary.129bf0e

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 (155) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +68 -0
  3. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  4. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  5. package/dist/AvatarGroup/AvatarGroupOverflow.js +4 -1
  6. package/dist/Banner/Banner.d.ts +7 -0
  7. package/dist/Banner/Banner.d.ts.map +1 -1
  8. package/dist/Banner/Banner.js +9 -2
  9. package/dist/Button/Button.d.ts.map +1 -1
  10. package/dist/Button/Button.js +2 -0
  11. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  12. package/dist/Chat/ChatLayoutScrollButton.js +5 -1
  13. package/dist/ContextMenu/ContextMenu.js +2 -2
  14. package/dist/DropdownMenu/DropdownMenu.js +2 -2
  15. package/dist/DropdownMenu/{renderXDSDropdownItems.d.ts → renderDropdownItems.d.ts} +3 -3
  16. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -0
  17. package/dist/DropdownMenu/{renderXDSDropdownItems.js → renderDropdownItems.js} +2 -2
  18. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  19. package/dist/EmptyState/EmptyState.js +7 -1
  20. package/dist/HoverCard/HoverCard.d.ts +2 -2
  21. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  22. package/dist/HoverCard/HoverCard.js +18 -6
  23. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  24. package/dist/HoverCard/useHoverCard.js +6 -3
  25. package/dist/Layer/useLayer.d.ts +13 -0
  26. package/dist/Layer/useLayer.d.ts.map +1 -1
  27. package/dist/Layer/useLayer.js +7 -2
  28. package/dist/Layout/Layout.d.ts +10 -1
  29. package/dist/Layout/Layout.d.ts.map +1 -1
  30. package/dist/Layout/Layout.js +5 -1
  31. package/dist/Markdown/Markdown.d.ts.map +1 -1
  32. package/dist/Markdown/Markdown.js +13 -3
  33. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  34. package/dist/MobileNav/MobileNav.js +13 -0
  35. package/dist/Outline/Outline.d.ts +3 -2
  36. package/dist/Outline/Outline.d.ts.map +1 -1
  37. package/dist/Outline/Outline.js +23 -4
  38. package/dist/Outline/useScrollSpy.d.ts +14 -1
  39. package/dist/Outline/useScrollSpy.d.ts.map +1 -1
  40. package/dist/Outline/useScrollSpy.js +161 -50
  41. package/dist/Pagination/Pagination.d.ts.map +1 -1
  42. package/dist/Pagination/Pagination.js +31 -27
  43. package/dist/Resizable/useResizable.d.ts.map +1 -1
  44. package/dist/Resizable/useResizable.js +1 -5
  45. package/dist/Selector/Selector.d.ts.map +1 -1
  46. package/dist/Selector/Selector.js +1 -1
  47. package/dist/Table/BaseTable.d.ts.map +1 -1
  48. package/dist/Table/BaseTable.js +26 -8
  49. package/dist/Table/Table.d.ts.map +1 -1
  50. package/dist/Table/Table.js +30 -7
  51. package/dist/Table/index.d.ts +3 -1
  52. package/dist/Table/index.d.ts.map +1 -1
  53. package/dist/Table/index.js +1 -0
  54. package/dist/Table/plugins/stickyColumns/index.d.ts +3 -0
  55. package/dist/Table/plugins/stickyColumns/index.d.ts.map +1 -0
  56. package/dist/Table/plugins/stickyColumns/index.js +3 -0
  57. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts +25 -0
  58. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -0
  59. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +376 -0
  60. package/dist/Table/types.d.ts +90 -5
  61. package/dist/Table/types.d.ts.map +1 -1
  62. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  63. package/dist/Table/useBaseTablePlugins.js +1 -1
  64. package/dist/ToggleButton/ToggleButton.d.ts +10 -3
  65. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  66. package/dist/ToggleButton/ToggleButton.js +64 -18
  67. package/dist/astryx.css +11 -0
  68. package/dist/astryx.umd.js +147 -0
  69. package/dist/astryx.umd.js.map +7 -0
  70. package/dist/theme/Theme.js +1 -1
  71. package/dist/theme/defineTheme.d.ts +1 -1
  72. package/dist/theme/defineTheme.d.ts.map +1 -1
  73. package/dist/theme/defineTheme.js +1 -1
  74. package/dist/theme/index.d.ts +1 -1
  75. package/dist/theme/index.d.ts.map +1 -1
  76. package/dist/theme/index.js +1 -1
  77. package/dist/theme/syntax/defineSyntaxTheme.js +1 -1
  78. package/dist/theme/tokens.d.ts +1 -1
  79. package/dist/theme/tokens.js +4 -4
  80. package/dist/theme/useTheme.d.ts +2 -2
  81. package/dist/utils/dateParser.d.ts.map +1 -1
  82. package/dist/utils/dateParser.js +15 -2
  83. package/package.json +7 -3
  84. package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -0
  85. package/src/Banner/Banner.test.tsx +16 -7
  86. package/src/Banner/Banner.tsx +9 -2
  87. package/src/Button/Button.test.tsx +26 -11
  88. package/src/Button/Button.tsx +2 -0
  89. package/src/Chat/ChatLayoutScrollButton.tsx +7 -1
  90. package/src/Collapsible/useCollapsible.doc.mjs +2 -2
  91. package/src/ContextMenu/ContextMenu.tsx +2 -2
  92. package/src/DateInput/DateInput.test.tsx +68 -20
  93. package/src/Divider/Divider.doc.mjs +1 -1
  94. package/src/DropdownMenu/DropdownMenu.tsx +2 -2
  95. package/src/DropdownMenu/{renderXDSDropdownItems.tsx → renderDropdownItems.tsx} +2 -2
  96. package/src/EmptyState/EmptyState.test.tsx +4 -2
  97. package/src/EmptyState/EmptyState.tsx +6 -2
  98. package/src/FormLayout/FormLayout.doc.mjs +3 -3
  99. package/src/HoverCard/HoverCard.doc.mjs +3 -0
  100. package/src/HoverCard/HoverCard.test.tsx +178 -2
  101. package/src/HoverCard/HoverCard.tsx +20 -16
  102. package/src/HoverCard/useHoverCard.tsx +12 -10
  103. package/src/Icon/Icon.doc.mjs +4 -4
  104. package/src/Item/Item.doc.mjs +2 -2
  105. package/src/Layer/useLayer.doc.mjs +7 -2
  106. package/src/Layer/useLayer.tsx +19 -2
  107. package/src/Layout/Layout.doc.mjs +2 -1
  108. package/src/Layout/Layout.tsx +15 -1
  109. package/src/Layout/__tests__/childrenAsContent.test.tsx +59 -0
  110. package/src/Lightbox/Lightbox.doc.mjs +0 -2
  111. package/src/Link/Link.doc.mjs +3 -3
  112. package/src/Link/LinkProvider.doc.mjs +3 -3
  113. package/src/Markdown/Markdown.doc.mjs +6 -4
  114. package/src/Markdown/Markdown.test.tsx +17 -26
  115. package/src/Markdown/Markdown.tsx +16 -6
  116. package/src/MobileNav/MobileNav.doc.mjs +8 -8
  117. package/src/MobileNav/MobileNav.tsx +13 -0
  118. package/src/MobileNav/MobileNavReopen.test.tsx +118 -0
  119. package/src/Outline/Outline.doc.mjs +1 -1
  120. package/src/Outline/Outline.test.tsx +76 -38
  121. package/src/Outline/Outline.tsx +23 -4
  122. package/src/Outline/useScrollSpy.ts +196 -63
  123. package/src/Pagination/Pagination.test.tsx +137 -13
  124. package/src/Pagination/Pagination.tsx +33 -28
  125. package/src/Resizable/Resizable.doc.mjs +3 -3
  126. package/src/Resizable/useResizable.ts +1 -7
  127. package/src/Selector/Selector.doc.mjs +4 -0
  128. package/src/Selector/Selector.tsx +5 -6
  129. package/src/Skeleton/Skeleton.doc.mjs +11 -1
  130. package/src/Table/BaseTable.tsx +50 -24
  131. package/src/Table/Table.doc.mjs +3 -3
  132. package/src/Table/Table.tsx +22 -1
  133. package/src/Table/index.ts +3 -0
  134. package/src/Table/plugins/stickyColumns/index.ts +4 -0
  135. package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +163 -0
  136. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +414 -0
  137. package/src/Table/types.ts +96 -4
  138. package/src/Table/useBaseTablePlugins.ts +1 -0
  139. package/src/ToggleButton/ToggleButton.doc.mjs +2 -2
  140. package/src/ToggleButton/ToggleButton.test.tsx +148 -6
  141. package/src/ToggleButton/ToggleButton.tsx +83 -20
  142. package/src/Toolbar/Toolbar.doc.mjs +1 -1
  143. package/src/hooks/useEntryAnimation.doc.mjs +3 -3
  144. package/src/hooks/useMediaQuery.doc.mjs +2 -2
  145. package/src/hooks/useStreamingText.doc.mjs +3 -3
  146. package/src/theme/Theme.doc.mjs +2 -2
  147. package/src/theme/Theme.tsx +1 -1
  148. package/src/theme/defineTheme.ts +1 -1
  149. package/src/theme/index.ts +1 -1
  150. package/src/theme/syntax/defineSyntaxTheme.ts +1 -1
  151. package/src/theme/tokens.ts +4 -4
  152. package/src/theme/useTheme.ts +2 -2
  153. package/src/utils/dateParser.test.ts +26 -0
  154. package/src/utils/dateParser.ts +16 -2
  155. package/dist/DropdownMenu/renderXDSDropdownItems.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"BaseTable.d.ts","sourceRoot":"","sources":["../../src/Table/BaseTable.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAe,KAAK,YAAY,EAAkB,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AAGhF,OAAO,KAAK,EACV,cAAc,EAWf,MAAM,SAAS,CAAC;AA6fjB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,EAAqB,CACzC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;CAAC,KACrD,YAAY,CAAC"}
1
+ {"version":3,"file":"BaseTable.d.ts","sourceRoot":"","sources":["../../src/Table/BaseTable.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAe,KAAK,YAAY,EAAkB,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AAGhF,OAAO,KAAK,EACV,cAAc,EAYf,MAAM,SAAS,CAAC;AAwhBjB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,EAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3E,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;CAAC,KACrD,YAAY,CAAC"}
@@ -105,7 +105,7 @@ function TableRowInner({
105
105
  CellComponent
106
106
  }) {
107
107
  // Build cells first
108
- const cells = columns.map(col => {
108
+ const cells = columns.map((col, columnIndex) => {
109
109
  // Apply column alignment to body cells
110
110
  const initialCellHtmlProps = {};
111
111
  if (col.align) {
@@ -113,10 +113,13 @@ function TableRowInner({
113
113
  textAlign: col.align
114
114
  };
115
115
  }
116
- const cellRenderProps = applyPlugins(plugins, p => p.transformBodyCell, {
116
+ const initialBodyCellRenderProps = {
117
117
  htmlProps: initialCellHtmlProps,
118
- styles: []
119
- }, col, item);
118
+ styles: [],
119
+ columnIndex,
120
+ columns: columns
121
+ };
122
+ const cellRenderProps = applyPlugins(plugins, p => p.transformBodyCell, initialBodyCellRenderProps, col, item, columnIndex, columns);
120
123
  const isDefaultRenderer = !col.renderCell;
121
124
  const rawContent = isDefaultRenderer ? defaultCellRenderer(item, col.key) : col.renderCell?.(item) ?? null;
122
125
 
@@ -265,7 +268,7 @@ function BaseTableInner({
265
268
  });
266
269
 
267
270
  // --- Plugin pipeline: header cells ---
268
- const headerCells = resolvedColumns.map(col => {
271
+ const headerCells = resolvedColumns.map((col, columnIndex) => {
269
272
  const headerContent = col.header ?? col.key;
270
273
 
271
274
  // Build initial htmlProps with column alignment if specified
@@ -277,11 +280,14 @@ function BaseTableInner({
277
280
  textAlign: col.align
278
281
  };
279
282
  }
280
- const cellRenderProps = applyPlugins(plugins, p => p.transformHeaderCell, {
283
+ const initialHeaderRenderProps = {
281
284
  htmlProps: initialHeaderHtmlProps,
282
285
  styles: [],
283
- content: headerContent
284
- }, col);
286
+ content: headerContent,
287
+ columnIndex,
288
+ columns: resolvedColumns
289
+ };
290
+ const cellRenderProps = applyPlugins(plugins, p => p.transformHeaderCell, initialHeaderRenderProps, col, columnIndex, resolvedColumns);
285
291
 
286
292
  // Apply pre-computed column width styles on the <th>.
287
293
  // With table-layout: fixed, header cell sizing controls column widths.
@@ -381,8 +387,20 @@ function BaseTableInner({
381
387
  // when columns exceed the container width. This wrapper sits between
382
388
  // the <table> and transformTableContext, so plugin chrome (pagination,
383
389
  // toolbars) renders outside the scroll area.
390
+ //
391
+ // Before rendering the wrapper, run the plugin `transformScrollWrapper`
392
+ // pipeline so plugins can attach a ref to the scroll container (scroll-aware
393
+ // sticky shadows, virtualization) and inject before/after chrome.
384
394
  if (ScrollWrapper) {
395
+ const scrollWrapperRenderProps = applyPlugins(plugins, p => p.transformScrollWrapper, {
396
+ htmlProps: {},
397
+ styles: []
398
+ });
385
399
  tableElement = /*#__PURE__*/_jsx(ScrollWrapper, {
400
+ htmlProps: scrollWrapperRenderProps.htmlProps,
401
+ styles: scrollWrapperRenderProps.styles,
402
+ beforeTable: scrollWrapperRenderProps.beforeTable,
403
+ afterTable: scrollWrapperRenderProps.afterTable,
386
404
  children: tableElement
387
405
  });
388
406
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../src/Table/Table.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,WAAW,EAEZ,MAAM,SAAS,CAAC;AAMjB,oDAAoD;AAEpD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAE/D,kCAAkC;AAElC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,8DAA8D;AAE9D,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpD;;;;;GAKG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,IAAI,CACzE,cAAc,CAAC,CAAC,CAAC,EACjB,SAAS,GAAG,YAAY,CACzB;IACC,uCAAuC;IACvC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACnC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC1C;AA6HD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,KAAK,EAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;CAAC,KACjD,YAAY,CAAC"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../src/Table/Table.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAU,KAAK,YAAY,EAAE,KAAK,GAAG,EAAC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,WAAW,EAEZ,MAAM,SAAS,CAAC;AAOjB,oDAAoD;AAEpD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAE/D,kCAAkC;AAElC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjE,8DAA8D;AAE9D,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEpD;;;;;GAKG;AAEH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,IAAI,CACzE,cAAc,CAAC,CAAC,CAAC,EACjB,SAAS,GAAG,YAAY,CACzB;IACC,uCAAuC;IACvC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC;;;;;;;;;;;;;;;OAeG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACnC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAC1C;AAiJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,KAAK,EAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAA;CAAC,KACjD,YAAY,CAAC"}
@@ -41,7 +41,7 @@ import { themeProps } from "../utils/themeProps.js";
41
41
  *
42
42
  * @template T - The row data type
43
43
  */
44
- import { jsx as _jsx } from "react/jsx-runtime";
44
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
45
45
  // =============================================================================
46
46
  // StyleX Styles (table-level only; cell/row/header styles owned by components)
47
47
  // =============================================================================
@@ -53,14 +53,37 @@ const tableStyles = {
53
53
  $$css: true
54
54
  }
55
55
  };
56
+ const scrollWrapperStyles = {
57
+ base: {
58
+ kXHlph: "xw2csxc",
59
+ kuHK5b: "x5lxg6s",
60
+ $$css: true
61
+ },
62
+ containerBleed: {
63
+ keTefX: "xojxgvx",
64
+ k71WvV: "x1fcf3bl",
65
+ kzqmXN: "xx6qvi6",
66
+ keoZOQ: "xkibk3",
67
+ k1K539: "xlayyun",
68
+ $$css: true
69
+ }
70
+ };
56
71
  function TableScrollWrapper({
57
- children
72
+ children,
73
+ htmlProps,
74
+ styles: pluginStyles,
75
+ beforeTable,
76
+ afterTable
58
77
  }) {
59
- return /*#__PURE__*/_jsx("div", {
60
- ...mergeProps(themeProps('table-scroll-wrapper'), {
61
- className: "xw2csxc x5lxg6s xojxgvx x1fcf3bl xx6qvi6 xkibk3 xlayyun"
62
- }),
63
- children: children
78
+ const {
79
+ ref,
80
+ ...restHtmlProps
81
+ } = htmlProps ?? {};
82
+ return /*#__PURE__*/_jsxs("div", {
83
+ ref: ref,
84
+ ...restHtmlProps,
85
+ ...mergeProps(themeProps('table-scroll-wrapper'), stylex.props(scrollWrapperStyles.base, scrollWrapperStyles.containerBleed, ...(pluginStyles ?? []))),
86
+ children: [beforeTable, children, afterTable]
64
87
  });
65
88
  }
66
89
 
@@ -22,10 +22,11 @@ export { useTablePagination, paginateData } from './plugins/pagination';
22
22
  export { useTableColumnSettings } from './plugins/columnSettings';
23
23
  export { useTableColumnSettingsState } from './plugins/columnSettings';
24
24
  export { useTableColumnResize } from './plugins/columnResize';
25
+ export { useTableStickyColumns } from './plugins/stickyColumns';
25
26
  export { useTableFiltering, useTableFilterState, toSearchFilters, } from './plugins/filtering';
26
27
  export { useBaseTablePlugins } from './useBaseTablePlugins';
27
28
  export { proportional, pixel, generateColumns, resolveColumnWidths, DEFAULT_MIN_COLUMN_WIDTH, } from './columnUtils';
28
- export type { TableColumn, TableColumnAlign, TableVerticalAlign, ColumnWidth, ProportionalWidth, PixelWidth, TablePlugin, TableRenderProps, HeaderRowRenderProps, HeaderCellRenderProps, BodyRowRenderProps, BodyCellRenderProps, BaseTableProps, } from './types';
29
+ export type { TableColumn, TableColumnAlign, TableVerticalAlign, ColumnWidth, ProportionalWidth, PixelWidth, TablePlugin, TableRenderProps, HeaderRowRenderProps, HeaderCellRenderProps, BodyRowRenderProps, BodyCellRenderProps, ScrollWrapperRenderProps, BaseTableProps, } from './types';
29
30
  export type { TableProps, TableDensity, TableDividers, TableTextOverflow, } from './Table';
30
31
  export type { TableRowProps } from './TableRow';
31
32
  export type { TableCellProps } from './TableCell';
@@ -42,5 +43,6 @@ export type { UseTablePaginationConfig } from './plugins/pagination';
42
43
  export type { UseTableColumnSettingsConfig, ColumnSettingsOption, } from './plugins/columnSettings';
43
44
  export type { UseTableColumnSettingsStateConfig, UseTableColumnSettingsStateReturn, } from './plugins/columnSettings';
44
45
  export type { UseTableColumnResizeConfig } from './plugins/columnResize';
46
+ export type { UseTableStickyColumnsConfig } from './plugins/stickyColumns';
45
47
  export type { UseTableFilteringConfig, TableFilterState, TableFilterVariant, TableFilterValue, TableFilterFieldRef, } from './plugins/filtering';
46
48
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Table/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Table/index.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,7 @@ export { useTablePagination, paginateData } from "./plugins/pagination/index.js"
26
26
  export { useTableColumnSettings } from "./plugins/columnSettings/index.js";
27
27
  export { useTableColumnSettingsState } from "./plugins/columnSettings/index.js";
28
28
  export { useTableColumnResize } from "./plugins/columnResize/index.js";
29
+ export { useTableStickyColumns } from "./plugins/stickyColumns/index.js";
29
30
  export { useTableFiltering, useTableFilterState, toSearchFilters } from "./plugins/filtering/index.js";
30
31
  export { useBaseTablePlugins } from "./useBaseTablePlugins.js";
31
32
  export { proportional, pixel, generateColumns, resolveColumnWidths, DEFAULT_MIN_COLUMN_WIDTH } from "./columnUtils.js";
@@ -0,0 +1,3 @@
1
+ export { useTableStickyColumns } from './useTableStickyColumns';
2
+ export type { UseTableStickyColumnsConfig } from './useTableStickyColumns';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/stickyColumns/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAC,2BAA2B,EAAC,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,3 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ export { useTableStickyColumns } from "./useTableStickyColumns.js";
@@ -0,0 +1,25 @@
1
+ import type { TablePlugin } from '../../types';
2
+ /**
3
+ * Config for {@link useTableStickyColumns}. Provide at least one of
4
+ * `startKeys` / `endKeys` to pin columns.
5
+ *
6
+ * @remarks Every field is optional by design, so `useTableStickyColumns({})`
7
+ * compiles and is an intentional no-op that pins nothing — the hook returns a
8
+ * plugin that passes every cell through untouched. This lets callers compute
9
+ * the config conditionally (e.g. `endKeys: enabled ? ['notes'] : undefined`)
10
+ * without branching on whether to install the plugin at all.
11
+ */
12
+ export interface UseTableStickyColumnsConfig {
13
+ /**
14
+ * Column keys pinned to the START (inline-start / left in LTR) edge — the
15
+ * contiguous run from the first column through the last listed key.
16
+ */
17
+ startKeys?: string[];
18
+ /**
19
+ * Column keys pinned to the END (inline-end / right in LTR) edge — the
20
+ * contiguous run from the first listed key through the last column.
21
+ */
22
+ endKeys?: string[];
23
+ }
24
+ export declare function useTableStickyColumns<T extends Record<string, unknown>>(config: UseTableStickyColumnsConfig): TablePlugin<T>;
25
+ //# sourceMappingURL=useTableStickyColumns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTableStickyColumns.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/stickyColumns/useTableStickyColumns.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAEV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAOrB;;;;;;;;;GASG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAoND,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,MAAM,EAAE,2BAA2B,GAClC,WAAW,CAAC,CAAC,CAAC,CAmJhB"}
@@ -0,0 +1,376 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file useTableStickyColumns.tsx
7
+ * @input React, StyleX, theme tokens, Table types
8
+ * @output Exports useTableStickyColumns hook and UseTableStickyColumnsConfig type
9
+ * @position Sticky-columns plugin; consumed by Table via plugins prop
10
+ *
11
+ * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/core/src/Table/Table.doc.mjs (sticky-columns documentation)
13
+ * - /packages/core/src/Table/index.ts (exports)
14
+ */
15
+ import { useCallback, useMemo, useRef } from 'react';
16
+ import * as stylex from '@stylexjs/stylex';
17
+ import "../../../theme/tokens.stylex.js";
18
+ import { colorVars } from "../../../theme/tokens.stylex.js";
19
+ import { DEFAULT_MIN_COLUMN_WIDTH } from "../../columnUtils.js";
20
+
21
+ // =============================================================================
22
+ // Config
23
+ // =============================================================================
24
+
25
+ /**
26
+ * Config for {@link useTableStickyColumns}. Provide at least one of
27
+ * `startKeys` / `endKeys` to pin columns.
28
+ *
29
+ * @remarks Every field is optional by design, so `useTableStickyColumns({})`
30
+ * compiles and is an intentional no-op that pins nothing — the hook returns a
31
+ * plugin that passes every cell through untouched. This lets callers compute
32
+ * the config conditionally (e.g. `endKeys: enabled ? ['notes'] : undefined`)
33
+ * without branching on whether to install the plugin at all.
34
+ */
35
+
36
+ // =============================================================================
37
+ // Width helpers
38
+ // =============================================================================
39
+
40
+ /**
41
+ * Resolve a column's pixel width for cumulative offset math. Mirrors the
42
+ * resize plugin's fallback so offsets line up with rendered widths:
43
+ * pixel columns use their value; proportional columns use their declared
44
+ * minWidth (or the default); unknown widths use the default.
45
+ */
46
+ function getColumnWidth(col) {
47
+ const w = col.width;
48
+ if (!w) {
49
+ return DEFAULT_MIN_COLUMN_WIDTH;
50
+ }
51
+ if (w.type === 'pixel') {
52
+ return w.value;
53
+ }
54
+ // proportional
55
+ return w.minWidth ?? DEFAULT_MIN_COLUMN_WIDTH;
56
+ }
57
+
58
+ /**
59
+ * Columns pinned to the START edge, keyed by column key → cumulative inline
60
+ * offset in pixels. The pinned block is the CONTIGUOUS run of leading columns
61
+ * from index 0 through the last column whose key is in `startKeys` (inclusive),
62
+ * INCLUDING synthetic columns (selection checkbox, row-index, …) that sit to
63
+ * the start of the user's sticky column. Returns `null` when no start-sticky
64
+ * column is present or column context is unavailable.
65
+ */
66
+ function computeStartOffsets(columns, startKeys) {
67
+ if (!columns || columns.length === 0 || startKeys.length === 0) {
68
+ return null;
69
+ }
70
+ let lastStickyIndex = -1;
71
+ for (let i = 0; i < columns.length; i++) {
72
+ if (startKeys.includes(columns[i].key)) {
73
+ lastStickyIndex = i;
74
+ }
75
+ }
76
+ if (lastStickyIndex === -1) {
77
+ return null;
78
+ }
79
+ const offsets = new Map();
80
+ let cumulative = 0;
81
+ for (let i = 0; i <= lastStickyIndex; i++) {
82
+ offsets.set(columns[i].key, cumulative);
83
+ cumulative += getColumnWidth(columns[i]);
84
+ }
85
+ return offsets;
86
+ }
87
+
88
+ /**
89
+ * Mirror image of {@link computeStartOffsets} — columns pinned to the END edge,
90
+ * keyed by column key → cumulative inline-end offset. The pinned block is the
91
+ * CONTIGUOUS run of trailing columns from the FIRST column whose key is in
92
+ * `endKeys` through the last column (inclusive). Offsets accumulate from the
93
+ * end edge — the last column gets `0`, its neighbor gets that column's width,
94
+ * etc. Returns `null` when no end-sticky column is present.
95
+ */
96
+ function computeEndOffsets(columns, endKeys) {
97
+ if (!columns || columns.length === 0 || endKeys.length === 0) {
98
+ return null;
99
+ }
100
+ let firstStickyIndex = -1;
101
+ for (let i = 0; i < columns.length; i++) {
102
+ if (endKeys.includes(columns[i].key)) {
103
+ firstStickyIndex = i;
104
+ break;
105
+ }
106
+ }
107
+ if (firstStickyIndex === -1) {
108
+ return null;
109
+ }
110
+ const offsets = new Map();
111
+ let cumulative = 0;
112
+ for (let i = columns.length - 1; i >= firstStickyIndex; i--) {
113
+ offsets.set(columns[i].key, cumulative);
114
+ cumulative += getColumnWidth(columns[i]);
115
+ }
116
+ return offsets;
117
+ }
118
+ /**
119
+ * Resolve how a single column should be pinned given the start/end configs and
120
+ * the full column list. A key (mis)configured on both edges resolves to start.
121
+ * Returns `null` for columns that should not be pinned.
122
+ */
123
+ function resolveStickySide(columns, columnKey, startKeys, endKeys) {
124
+ const startOffsets = computeStartOffsets(columns, startKeys);
125
+ if (startOffsets?.has(columnKey)) {
126
+ return {
127
+ edge: 'start',
128
+ offset: startOffsets.get(columnKey) ?? 0
129
+ };
130
+ }
131
+ const endOffsets = computeEndOffsets(columns, endKeys);
132
+ if (endOffsets?.has(columnKey)) {
133
+ return {
134
+ edge: 'end',
135
+ offset: endOffsets.get(columnKey) ?? 0
136
+ };
137
+ }
138
+ return null;
139
+ }
140
+
141
+ // =============================================================================
142
+ // Styles
143
+ // =============================================================================
144
+
145
+ // CSS variables toggled on the scroll container by the layout ref. The cell
146
+ // ::after shadows read these, so each edge's shadow only shows when there is
147
+ // horizontally-scrolled content hidden behind that edge. We use CSS variables
148
+ // (not stylex.when.ancestor) because StyleX ancestor selectors support pseudo-
149
+ // classes only, not attribute/className matching — a CSS variable inherited
150
+ // from the scroll container is the supported way to gate descendant styles on
151
+ // container scroll state.
152
+ const SHADOW_VAR_START = '--table-sticky-shadow-start';
153
+ const SHADOW_VAR_END = '--table-sticky-shadow-end';
154
+ const stickyStyles = {
155
+ cell: {
156
+ kVAEAm: "x7wzq59",
157
+ kWkggS: "x10xzikg",
158
+ kHypHr: "xx83zyx",
159
+ kVQacm: "x1rea2x4",
160
+ $$css: true
161
+ },
162
+ headerCell: {
163
+ kY2c9j: "xzkaem6",
164
+ $$css: true
165
+ },
166
+ bodyCell: {
167
+ kY2c9j: "x1vjfegm",
168
+ $$css: true
169
+ }
170
+ };
171
+
172
+ // A soft drop shadow over the scrolling region, matching the EPS sticky-column
173
+ // treatment. `border-collapse: collapse` tables (Astryx Table uses
174
+ // table-layout: fixed + border-collapse: collapse) do NOT paint `box-shadow`
175
+ // on the cells themselves in Chromium, so the shadow is cast by a ::after strip
176
+ // positioned just outside the pinned edge, filled with a soft gradient that
177
+ // fades from a shadow tint to transparent over the scrolled content. Sticky
178
+ // cells set `overflow: visible` (above) so this strip isn't clipped. Its
179
+ // opacity reads a CSS variable inherited from the scroll container, which the
180
+ // layout ref toggles between 0 and 1 on scroll so the shadow only shows when
181
+ // there is hidden content behind that edge.
182
+ const SHADOW_WIDTH = '6px';
183
+ // A subtle tint that fades to transparent. --color-shadow is only ~10% alpha,
184
+ // which reads too faintly here, so use a slightly stronger but still soft tint.
185
+ const SHADOW_TINT = 'light-dark(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.32))';
186
+ const shadowStyles = {
187
+ start: {
188
+ k5JduY: "x1s928wv",
189
+ kwXMNM: "x1j6awrg",
190
+ k3foIR: "x1m1drc7",
191
+ k8Iv0R: "x1xrz1ek",
192
+ kH8aOt: "x1unh1gc",
193
+ kkgrvl: "xzkji8o",
194
+ kLigFv: "x1qyefdi",
195
+ kloYau: "x2q1x1w",
196
+ kFJxch: "x17s1k9h",
197
+ kypkao: "x1sggmfs",
198
+ kNctxI: "x156sm4c",
199
+ $$css: true
200
+ },
201
+ end: {
202
+ k5JduY: "x1s928wv",
203
+ kwXMNM: "x1j6awrg",
204
+ k3foIR: "x1m1drc7",
205
+ k8Iv0R: "x1xrz1ek",
206
+ kc1e00: "x1iygr5g",
207
+ kkgrvl: "xzkji8o",
208
+ kLigFv: "xvs0bi2",
209
+ kloYau: "x2q1x1w",
210
+ kFJxch: "x17s1k9h",
211
+ kypkao: "x1c2idit",
212
+ kNctxI: "x14ofgck",
213
+ $$css: true
214
+ }
215
+ };
216
+
217
+ // Stable empty default so an unset start/end doesn't allocate a fresh array
218
+ // (and bust the memo) on every render.
219
+ const EMPTY = [];
220
+
221
+ // =============================================================================
222
+ // Hook
223
+ // =============================================================================
224
+
225
+ export function useTableStickyColumns(config) {
226
+ const {
227
+ startKeys,
228
+ endKeys
229
+ } = config;
230
+ const start = startKeys ?? EMPTY;
231
+ const end = endKeys ?? EMPTY;
232
+ const hasStart = start.length > 0;
233
+ const hasEnd = end.length > 0;
234
+
235
+ // Live snapshot of the resolved config, read inside the (memoized) transforms
236
+ // and the scroll-shadow callback. Keeping these in a ref lets the plugin memo
237
+ // be computed once (deps: only the stable scroll-shadow callback) while never
238
+ // reading stale config — consumers typically pass fresh array literals each
239
+ // render, so we never want array identity in the deps.
240
+ const stateRef = useRef({
241
+ start,
242
+ end,
243
+ hasStart,
244
+ hasEnd
245
+ });
246
+ stateRef.current = {
247
+ start,
248
+ end,
249
+ hasStart,
250
+ hasEnd
251
+ };
252
+
253
+ // Scroll-aware shadows: toggle CSS variables on the scroll container so each
254
+ // edge's shadow only paints when there is hidden, horizontally-scrolled
255
+ // content behind that edge. Implemented with a callback ref + scroll/resize
256
+ // listeners (synchronizing with the DOM) rather than React state, so
257
+ // scrolling never triggers re-renders.
258
+ const detachRef = useRef(null);
259
+ const attachScrollShadow = useCallback(el => {
260
+ detachRef.current?.();
261
+ detachRef.current = null;
262
+ if (!el) {
263
+ return;
264
+ }
265
+ const update = () => {
266
+ const {
267
+ hasStart: hs,
268
+ hasEnd: he
269
+ } = stateRef.current;
270
+ const maxScroll = el.scrollWidth - el.clientWidth;
271
+ const hasOverflow = maxScroll > 1;
272
+ if (hs) {
273
+ el.style.setProperty(SHADOW_VAR_START, hasOverflow && el.scrollLeft > 1 ? '1' : '0');
274
+ }
275
+ if (he) {
276
+ el.style.setProperty(SHADOW_VAR_END, hasOverflow && el.scrollLeft < maxScroll - 1 ? '1' : '0');
277
+ }
278
+ };
279
+ el.addEventListener('scroll', update, {
280
+ passive: true
281
+ });
282
+ const resizeObserver = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(update) : null;
283
+ resizeObserver?.observe(el);
284
+ update();
285
+ detachRef.current = () => {
286
+ el.removeEventListener('scroll', update);
287
+ resizeObserver?.disconnect();
288
+ };
289
+ }, []);
290
+ return useMemo(() => ({
291
+ transformHeaderCell(props, column) {
292
+ const {
293
+ start: s,
294
+ end: e
295
+ } = stateRef.current;
296
+ const side = resolveStickySide(props.columns, column.key, s, e);
297
+ if (!side) {
298
+ return props;
299
+ }
300
+ // position/inline-offset are runtime values → set via inline style so
301
+ // they are authoritative regardless of plugin composition order (the
302
+ // resize plugin also writes inline style on header cells).
303
+ const offsetStyle = side.edge === 'start' ? {
304
+ insetInlineStart: `${side.offset}px`
305
+ } : {
306
+ insetInlineEnd: `${side.offset}px`
307
+ };
308
+ return {
309
+ ...props,
310
+ htmlProps: {
311
+ ...props.htmlProps,
312
+ style: {
313
+ ...props.htmlProps.style,
314
+ ...offsetStyle
315
+ }
316
+ },
317
+ styles: [...props.styles, stickyStyles.cell, stickyStyles.headerCell, side.edge === 'start' ? shadowStyles.start : shadowStyles.end]
318
+ };
319
+ },
320
+ transformBodyCell(props, column) {
321
+ const {
322
+ start: s,
323
+ end: e
324
+ } = stateRef.current;
325
+ const side = resolveStickySide(props.columns, column.key, s, e);
326
+ if (!side) {
327
+ return props;
328
+ }
329
+ const offsetStyle = side.edge === 'start' ? {
330
+ insetInlineStart: `${side.offset}px`
331
+ } : {
332
+ insetInlineEnd: `${side.offset}px`
333
+ };
334
+ return {
335
+ ...props,
336
+ htmlProps: {
337
+ ...props.htmlProps,
338
+ style: {
339
+ ...props.htmlProps.style,
340
+ ...offsetStyle
341
+ }
342
+ },
343
+ styles: [...props.styles, stickyStyles.cell, stickyStyles.bodyCell, side.edge === 'start' ? shadowStyles.start : shadowStyles.end]
344
+ };
345
+ },
346
+ transformScrollWrapper(props) {
347
+ // No pinned edges → nothing to gate; leave the wrapper untouched.
348
+ if (!stateRef.current.hasStart && !stateRef.current.hasEnd) {
349
+ return props;
350
+ }
351
+ // Compose with any ref a prior plugin (e.g. virtualization) set on the
352
+ // scroll container.
353
+ const existingRef = props.htmlProps.ref;
354
+ const mergedRef = node => {
355
+ attachScrollShadow(node);
356
+ if (typeof existingRef === 'function') {
357
+ existingRef(node);
358
+ } else if (existingRef != null) {
359
+ // RefObject — assign through its writable `.current`.
360
+ existingRef.current = node;
361
+ }
362
+ };
363
+ return {
364
+ ...props,
365
+ htmlProps: {
366
+ ...props.htmlProps,
367
+ ref: mergedRef
368
+ }
369
+ };
370
+ }
371
+ }),
372
+ // The returned plugin's transforms read live config from `stateRef` and
373
+ // `attachScrollShadow` is stable (empty deps), so the plugin object can be
374
+ // computed once and reused across renders.
375
+ [attachScrollShadow]);
376
+ }