jattac.libs.web.responsive-table 0.12.0-rc.4 → 0.13.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/README.md +92 -13
- package/dist/Hooks/useTablePlugins.d.ts +0 -8
- package/dist/Plugins/IResponsiveTablePlugin.d.ts +0 -6
- package/dist/UI/DetailRow.d.ts +1 -2
- package/dist/UI/ResponsiveTable.d.ts +0 -11
- package/dist/UI/TableBodyRow.d.ts +6 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.es.js +156 -327
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +155 -327
- package/dist/index.js.map +1 -1
- package/docs/api.md +102 -22
- package/docs/development.md +1 -2
- package/docs/examples.md +57 -1
- package/docs/expand-collapse.md +630 -0
- package/docs/features.md +6 -0
- package/docs/recommendations.md +376 -0
- package/package.json +1 -1
- package/dist/Plugins/InfiniteScrollPlugin.d.ts +0 -13
- package/dist/UI/InfiniteTable.d.ts +0 -46
package/README.md
CHANGED
|
@@ -18,6 +18,19 @@ npm install jattac.libs.web.responsive-table jattac.libs.web.zest-textbox react-
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
+
## Table of Contents
|
|
22
|
+
|
|
23
|
+
* [Built-in Filter](#built-in-filter)
|
|
24
|
+
* [Delightful Data Fetching: Smart Data Source](#delightful-data-fetching-smart-data-source)
|
|
25
|
+
* [Basic Implementation](#basic-implementation)
|
|
26
|
+
* [Handling Interactive Elements](#handling-interactive-elements)
|
|
27
|
+
* [Expandable Rows](#expandable-rows)
|
|
28
|
+
* [Row Interaction & Feedback](#row-interaction--feedback)
|
|
29
|
+
* [Loading States & Animations](#loading-states--animations)
|
|
30
|
+
* [Documentation Directory](#documentation-directory)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
21
34
|
## Built-in Filter
|
|
22
35
|
|
|
23
36
|
Enable the search box with one prop. A clear (×) button appears automatically when the field has text.
|
|
@@ -144,38 +157,102 @@ For a deep dive into more complex scenarios, see the **[Handling Interactive Ele
|
|
|
144
157
|
|
|
145
158
|
## Expandable Rows
|
|
146
159
|
|
|
147
|
-
Pass `expandRowRenderer` to reveal arbitrary content below any row.
|
|
160
|
+
Pass `expandRowRenderer` to reveal arbitrary content below any row. Each expandable row gets a chevron in a dedicated left column (▶ collapsed, ▾ expanded). Returning `null` or `undefined` for a row suppresses its toggle entirely — that row renders flat with no visual affordance.
|
|
148
161
|
|
|
149
162
|
```tsx
|
|
150
163
|
<ResponsiveTable
|
|
151
164
|
data={orders}
|
|
152
165
|
columnDefinitions={columns}
|
|
153
|
-
expandRowRenderer={(order) =>
|
|
154
|
-
<OrderLineItems orderId={order.id} />
|
|
155
|
-
)}
|
|
166
|
+
expandRowRenderer={(order) => <OrderLineItems orderId={order.id} />}
|
|
156
167
|
/>
|
|
157
168
|
```
|
|
158
169
|
|
|
159
|
-
|
|
170
|
+
**Selectively expandable** — only rows where the renderer returns content get a toggle:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
expandRowRenderer={(order) =>
|
|
174
|
+
order.lineItems.length > 0
|
|
175
|
+
? <OrderLineItems order={order} />
|
|
176
|
+
: null
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Using `rowIndex`** — the renderer receives both the row object and its current display-order index. Useful for position-based formatting, alternating detail styles, or correlating with a parallel index-aligned array:
|
|
160
181
|
|
|
161
182
|
```tsx
|
|
162
183
|
expandRowRenderer={(row, rowIndex) => (
|
|
163
|
-
<
|
|
184
|
+
<DetailPanel row={row} zebra={rowIndex % 2 === 0} />
|
|
164
185
|
)}
|
|
165
186
|
```
|
|
166
187
|
|
|
167
|
-
|
|
188
|
+
> `rowIndex` is the **display-order** index (post-sort, post-filter) — it changes when the user re-sorts. For stable data correlation across renders, use the row's own identifier field (`row.id`, etc.).
|
|
189
|
+
|
|
190
|
+
**Customising the chevron** — override color, size, or any other style via `expandChevronClassName`. Do not override `transform` or `transition` — these drive the rotation animation.
|
|
168
191
|
|
|
169
192
|
```tsx
|
|
170
|
-
|
|
171
|
-
|
|
193
|
+
// Accent color from your design system
|
|
194
|
+
<ResponsiveTable
|
|
195
|
+
expandChevronClassName="my-brand-chevron"
|
|
196
|
+
expandRowRenderer={(row) => <Detail row={row} />}
|
|
197
|
+
...
|
|
198
|
+
/>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```css
|
|
202
|
+
/* your stylesheet */
|
|
203
|
+
.my-brand-chevron {
|
|
204
|
+
color: #7c3aed; /* purple accent */
|
|
205
|
+
font-size: 2rem;
|
|
172
206
|
}
|
|
173
207
|
```
|
|
174
208
|
|
|
175
|
-
**
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
209
|
+
**Behaviour**
|
|
210
|
+
- Chevron sits in a dedicated 2rem left column — not as an overlay or pseudo-element — keeping the data columns aligned.
|
|
211
|
+
- **Idle:** chevron at 25% opacity, rotates right (`-90deg`). Quiet, non-intrusive.
|
|
212
|
+
- **Hover:** chevron smooths to 60% opacity, faint border accent on the row.
|
|
213
|
+
- **Expanded:** chevron rotates down (`0deg`), full opacity. A toggle bar slides in (0→2rem) at the top of the detail pane.
|
|
214
|
+
- **Greeting animation:** on mount, chevrons pop in with a staggered multi-pulse wave (2.2s), then settle to idle. Plays once per component lifecycle.
|
|
215
|
+
- Expand and `onRowClick` coexist safely — the chevron carries `data-rt-ignore-row-click`.
|
|
216
|
+
- Works identically in both desktop (table row) and mobile (card) layouts.
|
|
217
|
+
|
|
218
|
+
For the full feature reference — expansion state keying, lazy mounting, keyboard accessibility, `dataSource` compatibility, common patterns, CSS customization, and pitfalls — see the **[Row Expansion and Collapse Guide](./docs/expand-collapse.md)**.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Row Interaction & Feedback
|
|
223
|
+
|
|
224
|
+
When `onRowClick` or `selectionProps` is provided, the table delivers tactile interaction feedback at every phase of the click:
|
|
225
|
+
|
|
226
|
+
| Phase | Desktop | Mobile |
|
|
227
|
+
| :--- | :--- | :--- |
|
|
228
|
+
| **Hover** | Subtle background lightening | Card lifts 4px with enhanced shadow |
|
|
229
|
+
| **Press (`:active`)** | Background deepens — confirms the press registered | Card compresses back to 1px lift |
|
|
230
|
+
| **Release / Selected** | Background sweeps to the selection tint (150ms transition) | Same tint + primary-color left border |
|
|
231
|
+
| **Keyboard focus** | 2px primary-color outline (`:focus-visible` only — not shown on mouse click) | Same |
|
|
232
|
+
|
|
233
|
+
**Rationale** — each phase is distinct so users receive unambiguous confirmation that their input was received, without animations that feel slow or decorative. The `:active` state is the most critical: it fires in the 80–150ms window of the press itself, before any state change, so even users on slow networks feel an immediate response.
|
|
234
|
+
|
|
235
|
+
**Keyboard navigation** — all clickable rows and cards have `tabIndex=0` and a `:focus-visible` ring. Tab through rows; press Enter or Space to trigger `onRowClick`.
|
|
236
|
+
|
|
237
|
+
**Combining with `onRowClick` and selection:**
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
<ResponsiveTable
|
|
241
|
+
data={employees}
|
|
242
|
+
columnDefinitions={columns}
|
|
243
|
+
onRowClick={(employee) => navigate(`/employees/${employee.id}`)}
|
|
244
|
+
selectionProps={{
|
|
245
|
+
rowIdKey: 'id',
|
|
246
|
+
mode: 'multiple',
|
|
247
|
+
onSelectionChange: (selected) => setSelected(selected),
|
|
248
|
+
}}
|
|
249
|
+
/>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Best practices**
|
|
253
|
+
- Always pair `onRowClick` with a visible hover state cue (the default cursor change handles this automatically).
|
|
254
|
+
- If rows contain buttons or links, use `data-rt-ignore-row-click` on those elements so inner interactions don't also trigger the row handler.
|
|
255
|
+
- For selection, always provide `rowIdKey` pointing to a stable unique field — this ensures expand state and selection state both survive sort/filter changes.
|
|
179
256
|
|
|
180
257
|
---
|
|
181
258
|
|
|
@@ -208,6 +285,8 @@ The following technical documentation provides comprehensive implementation guid
|
|
|
208
285
|
4. **[Configuration Specification](./docs/configuration.md)** - Detailed guidance on performance tuning and UI customization.
|
|
209
286
|
5. **[Architecture and Contribution Guide](./docs/development.md)** - Internal system design and development environment setup.
|
|
210
287
|
6. **[Handling Interactive Elements](./docs/handling-interactive-elements.md)** - Guide on preventing row click bubbling for buttons and custom components.
|
|
288
|
+
7. **[Row Expansion and Collapse](./docs/expand-collapse.md)** - Comprehensive guide for expandable row detail panels.
|
|
289
|
+
8. **[Recommendations and Pitfalls](./docs/recommendations.md)** - Best practices, anti-patterns, and ESM/CJS module compatibility guide.
|
|
211
290
|
|
|
212
291
|
---
|
|
213
292
|
**Next Step:** [Review the Technical Implementation Guide](./docs/examples.md)
|
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
1
|
import { IResponsiveTablePlugin } from '../Plugins/IResponsiveTablePlugin';
|
|
3
2
|
import { IResponsiveTableColumnDefinition, SortDirection } from '../Data/IResponsiveTableColumnDefinition';
|
|
4
|
-
interface IInfiniteScrollProps<TData> {
|
|
5
|
-
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
6
|
-
hasMore?: boolean;
|
|
7
|
-
loadingMoreComponent?: ReactNode;
|
|
8
|
-
noMoreDataComponent?: ReactNode;
|
|
9
|
-
}
|
|
10
3
|
interface UseTablePluginsProps<TData> {
|
|
11
4
|
data: TData[];
|
|
12
5
|
plugins?: IResponsiveTablePlugin<TData>[];
|
|
@@ -28,7 +21,6 @@ interface UseTablePluginsProps<TData> {
|
|
|
28
21
|
};
|
|
29
22
|
columnDefinitions: (IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>))[];
|
|
30
23
|
getScrollableElement: () => HTMLElement | null;
|
|
31
|
-
infiniteScrollProps?: IInfiniteScrollProps<TData>;
|
|
32
24
|
onFilterChange?: (filterText: string) => void;
|
|
33
25
|
}
|
|
34
26
|
interface UseTablePluginsReturn<TData> {
|
|
@@ -18,12 +18,6 @@ export interface IPluginAPI<TData> {
|
|
|
18
18
|
forceUpdate: () => void;
|
|
19
19
|
columnDefinitions: ColumnDefinition<TData>[];
|
|
20
20
|
getScrollableElement?: () => HTMLElement | null;
|
|
21
|
-
infiniteScrollProps?: {
|
|
22
|
-
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
23
|
-
hasMore?: boolean;
|
|
24
|
-
loadingMoreComponent?: ReactNode;
|
|
25
|
-
noMoreDataComponent?: ReactNode;
|
|
26
|
-
};
|
|
27
21
|
filterProps?: {
|
|
28
22
|
showFilter?: boolean;
|
|
29
23
|
filterPlaceholder?: string;
|
package/dist/UI/DetailRow.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ interface DetailRowProps<TData> {
|
|
|
6
6
|
expandRowRenderer: (row: TData, rowIndex: number) => React.ReactNode;
|
|
7
7
|
isExpanded: boolean;
|
|
8
8
|
onToggle: () => void;
|
|
9
|
-
expandChevronClassName?: string;
|
|
10
9
|
}
|
|
11
|
-
export declare function DetailRow<TData>({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle
|
|
10
|
+
export declare function DetailRow<TData>({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle }: DetailRowProps<TData>): React.JSX.Element;
|
|
12
11
|
export {};
|
|
@@ -10,12 +10,6 @@ export interface ResponsiveTableHandle<TData> {
|
|
|
10
10
|
resetAndFetch: () => Promise<void>;
|
|
11
11
|
getState: () => DataSourceState<TData>;
|
|
12
12
|
}
|
|
13
|
-
interface IInfiniteScrollProps<TData> {
|
|
14
|
-
onLoadMore: (currentData: TData[]) => Promise<TData[] | null>;
|
|
15
|
-
hasMore?: boolean;
|
|
16
|
-
loadingMoreComponent?: ReactNode;
|
|
17
|
-
noMoreDataComponent?: ReactNode;
|
|
18
|
-
}
|
|
19
13
|
interface ISortProps {
|
|
20
14
|
initialSortColumn?: string;
|
|
21
15
|
initialSortDirection?: SortDirection;
|
|
@@ -62,11 +56,6 @@ interface IProps<TData> {
|
|
|
62
56
|
plugins?: IResponsiveTablePlugin<TData>[];
|
|
63
57
|
/** If true, the header will stick to the top of the page when scrolling. */
|
|
64
58
|
enablePageLevelStickyHeader?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Props for manual infinite scroll handling.
|
|
67
|
-
* NOTE: Prefer using `dataSource` for a more seamless experience.
|
|
68
|
-
*/
|
|
69
|
-
infiniteScrollProps?: IInfiniteScrollProps<TData>;
|
|
70
59
|
/** Configuration for the built-in filter plugin. */
|
|
71
60
|
filterProps?: {
|
|
72
61
|
showFilter?: boolean;
|
|
@@ -32,6 +32,12 @@ interface TableBodyRowProps<TData> {
|
|
|
32
32
|
isLoading?: boolean;
|
|
33
33
|
animateOnLoad?: boolean;
|
|
34
34
|
};
|
|
35
|
+
/** Optional expand chevron cell rendered as the first column */
|
|
36
|
+
expandCell?: React.ReactNode;
|
|
37
|
+
/** Mouse enter handler for hover tracking */
|
|
38
|
+
onMouseEnter?: () => void;
|
|
39
|
+
/** Mouse leave handler for hover tracking */
|
|
40
|
+
onMouseLeave?: () => void;
|
|
35
41
|
}
|
|
36
42
|
export declare function TableBodyRow<TData>(props: TableBodyRowProps<TData>): React.JSX.Element;
|
|
37
43
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,8 @@ import ResponsiveTable, { ResponsiveTableHandle } from './UI/ResponsiveTable';
|
|
|
5
5
|
import { ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, useTableContext } from './Context/TableContext';
|
|
6
6
|
import { DataSourceState } from './Hooks/useTableDataSource';
|
|
7
7
|
import { FilterPlugin } from './Plugins/FilterPlugin';
|
|
8
|
-
import { InfiniteScrollPlugin } from './Plugins/InfiniteScrollPlugin';
|
|
9
8
|
import { IResponsiveTablePlugin } from './Plugins/IResponsiveTablePlugin';
|
|
10
9
|
import { SortPlugin } from './Plugins/SortPlugin';
|
|
11
10
|
import { SelectionPlugin } from './Plugins/SelectionPlugin';
|
|
12
|
-
export { SortDirection, IResponsiveTableColumnDefinition, ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin,
|
|
11
|
+
export { SortDirection, IResponsiveTableColumnDefinition, ColumnDefinition, DataSource, IDataSourceParams, DataSourceResult, IFooterColumnDefinition, IFooterRowDefinition, FilterPlugin, IResponsiveTablePlugin, SortPlugin, SelectionPlugin, ResponsiveTableHandle, DataSourceState, useTableContext, };
|
|
13
12
|
export default ResponsiveTable;
|