jattac.libs.web.responsive-table 0.12.0-rc.3 → 0.12.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 CHANGED
@@ -144,38 +144,97 @@ For a deep dive into more complex scenarios, see the **[Handling Interactive Ele
144
144
 
145
145
  ## Expandable Rows
146
146
 
147
- Pass `expandRowRenderer` to reveal arbitrary content below any row. Return `null` or `undefined` for rows that should not be expandableonly those rows get a toggle.
147
+ Pass `expandRowRenderer` to reveal arbitrary content below any row. Each expandable row gets a solid chevron toggle (▶ collapsed, ▾ expanded) on a muted blue bar. Returning `null` or `undefined` for a row suppresses its toggle entirelythat row renders flat with no visual affordance.
148
148
 
149
149
  ```tsx
150
150
  <ResponsiveTable
151
151
  data={orders}
152
152
  columnDefinitions={columns}
153
- expandRowRenderer={(order) => (
154
- <OrderLineItems orderId={order.id} />
155
- )}
153
+ expandRowRenderer={(order) => <OrderLineItems orderId={order.id} />}
156
154
  />
157
155
  ```
158
156
 
159
- The renderer receives both the row and its display-order index:
157
+ **Selectively expandable** only rows where the renderer returns content get a toggle:
158
+
159
+ ```tsx
160
+ expandRowRenderer={(order) =>
161
+ order.lineItems.length > 0
162
+ ? <OrderLineItems order={order} />
163
+ : null
164
+ }
165
+ ```
166
+
167
+ **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
168
 
161
169
  ```tsx
162
170
  expandRowRenderer={(row, rowIndex) => (
163
- <div>Row {rowIndex}: <pre>{JSON.stringify(row, null, 2)}</pre></div>
171
+ <DetailPanel row={row} zebra={rowIndex % 2 === 0} />
164
172
  )}
165
173
  ```
166
174
 
167
- Selectively expandablerows where the renderer returns `null` render at zero height with no toggle:
175
+ > `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.).
176
+
177
+ **Customising the chevron** — override color, size, or any other style via `expandChevronClassName`:
168
178
 
169
179
  ```tsx
170
- expandRowRenderer={(row) =>
171
- row.hasDetails ? <DetailPanel row={row} /> : null
180
+ // Accent color from your design system
181
+ <ResponsiveTable
182
+ expandChevronClassName="my-brand-chevron"
183
+ expandRowRenderer={(row) => <Detail row={row} />}
184
+ ...
185
+ />
186
+ ```
187
+
188
+ ```css
189
+ /* your stylesheet */
190
+ .my-brand-chevron {
191
+ color: #7c3aed; /* purple accent */
192
+ font-size: 2rem;
172
193
  }
173
194
  ```
174
195
 
175
196
  **Recommendations**
176
- - Provide `selectionProps` with a `rowIdKey` when your data has a stable identifier. The expand state is keyed by row ID, so expand/collapse survives re-sorts and filter changes correctly.
177
- - `rowIndex` reflects the current **display order** (post-sort, post-filter). Use `row.id` or equivalent for stable cross-render correlation.
178
- - Detail content is lazy-mounted — the component only renders on first expand, then stays mounted so the collapse animation plays smoothly.
197
+ - Provide `selectionProps` with a `rowIdKey` when your data has a stable identifier. Expand state is keyed by row ID, so open panels survive re-sorts and filter changes.
198
+ - Detail content is **lazy-mounted** — the panel component is not created until first expand, then stays mounted so the collapse animation plays correctly. Heavy components are therefore only instantiated on demand.
199
+ - Expand and `onRowClick` coexist safely — the chevron bar carries `data-rt-ignore-row-click` so tapping the toggle never fires the row click handler.
200
+ - Works identically in both desktop (table row) and mobile (card) layouts.
201
+
202
+ ---
203
+
204
+ ## Row Interaction & Feedback
205
+
206
+ When `onRowClick` or `selectionProps` is provided, the table delivers tactile interaction feedback at every phase of the click:
207
+
208
+ | Phase | Desktop | Mobile |
209
+ | :--- | :--- | :--- |
210
+ | **Hover** | Subtle background lightening | Card lifts 4px with enhanced shadow |
211
+ | **Press (`:active`)** | Background deepens — confirms the press registered | Card compresses back to 1px lift |
212
+ | **Release / Selected** | Background sweeps to the selection tint (150ms transition) | Same tint + primary-color left border |
213
+ | **Keyboard focus** | 2px primary-color outline (`:focus-visible` only — not shown on mouse click) | Same |
214
+
215
+ **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.
216
+
217
+ **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`.
218
+
219
+ **Combining with `onRowClick` and selection:**
220
+
221
+ ```tsx
222
+ <ResponsiveTable
223
+ data={employees}
224
+ columnDefinitions={columns}
225
+ onRowClick={(employee) => navigate(`/employees/${employee.id}`)}
226
+ selectionProps={{
227
+ rowIdKey: 'id',
228
+ mode: 'multiple',
229
+ onSelectionChange: (selected) => setSelected(selected),
230
+ }}
231
+ />
232
+ ```
233
+
234
+ **Best practices**
235
+ - Always pair `onRowClick` with a visible hover state cue (the default cursor change handles this automatically).
236
+ - 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.
237
+ - For selection, always provide `rowIdKey` pointing to a stable unique field — this ensures expand state and selection state both survive sort/filter changes.
179
238
 
180
239
  ---
181
240
 
@@ -76,6 +76,8 @@ interface TableContextValue<TData> {
76
76
  mobileCardClassName?: string;
77
77
  /** Return a ReactNode for expandable content below a row, or null/undefined for no toggle on that row. */
78
78
  expandRowRenderer?: (row: TData, rowIndex: number) => React.ReactNode;
79
+ /** Custom CSS class applied to the chevron icon span. */
80
+ expandChevronClassName?: string;
79
81
  getRawColumnDefinition: (colDef: ColumnDefinition<TData>) => IResponsiveTableColumnDefinition<TData>;
80
82
  getColumnDefinition: (colDef: ColumnDefinition<TData>, rowIndex: number) => IResponsiveTableColumnDefinition<TData>;
81
83
  onHeaderClickCallback: (colDef: ColumnDefinition<TData>) => ((id: string) => void) | undefined;
@@ -6,6 +6,7 @@ interface DetailRowProps<TData> {
6
6
  expandRowRenderer: (row: TData, rowIndex: number) => React.ReactNode;
7
7
  isExpanded: boolean;
8
8
  onToggle: () => void;
9
+ expandChevronClassName?: string;
9
10
  }
10
- export declare function DetailRow<TData>({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle }: DetailRowProps<TData>): React.JSX.Element;
11
+ export declare function DetailRow<TData>({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle, expandChevronClassName }: DetailRowProps<TData>): React.JSX.Element;
11
12
  export {};
@@ -100,6 +100,8 @@ interface IProps<TData> {
100
100
  onDataSourceError?: (error: Error) => void;
101
101
  /** Return a ReactNode to render expandable content below a row, or null/undefined for no expand toggle on that row. */
102
102
  expandRowRenderer?: (row: TData, rowIndex: number) => React.ReactNode;
103
+ /** Custom CSS class applied to the expand/collapse chevron icon span. Use to override color, size, or add custom styling. */
104
+ expandChevronClassName?: string;
103
105
  }
104
106
  declare const ResponsiveTable: <TData>(props: IProps<TData> & {
105
107
  ref?: React.Ref<ResponsiveTableHandle<TData>>;
package/dist/index.es.js CHANGED
@@ -29,7 +29,7 @@ function styleInject(css, ref) {
29
29
  }
30
30
  }
31
31
 
32
- var css_248z$2 = ".ResponsiveTable-module_responsiveTable__4y-Od{--table-border-color:#e0e0e0;--table-header-bg:#f8f9fa;--table-row-hover-bg:#f1f3f5;--table-row-stripe-bg:#fafbfc;--card-bg:#fff;--card-border-color:#d1d5db;--card-shadow:0 2px 8px rgba(0,0,0,.06);--text-color:#212529;--text-color-muted:#6c757d;--interactive-color:#0056b3;--primary-color:#007bff;--rt-mobile-card-shadow:0 1px 2px rgba(0,0,0,.04),0 4px 12px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.04);--rt-mobile-card-radius:16px;--rt-mobile-bg-wash:#f1f5f9;--rt-mobile-label-color:#475569;--rt-mobile-value-color:#1e293b}.ResponsiveTable-module_tableContainer__VjWjH{border:1px solid var(--table-border-color);border-radius:8px;overflow-x:auto;width:100%}.ResponsiveTable-module_responsiveTable__4y-Od{background-color:var(--card-bg);border-collapse:collapse;color:var(--text-color);width:100%}.ResponsiveTable-module_responsiveTable__4y-Od thead th{background-color:var(--table-header-bg);border-bottom:2px solid var(--table-border-color);color:var(--text-color-muted);font-size:.75rem;font-weight:600;letter-spacing:.05em;padding:1rem;text-align:left;text-transform:uppercase;z-index:1}.ResponsiveTable-module_responsiveTable__4y-Od td{border-bottom:1px solid var(--table-border-color);font-size:.9rem;padding:1rem;text-align:left}.ResponsiveTable-module_responsiveTable__4y-Od tr:last-child td{border-bottom:none}.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(2n){background-color:var(--table-row-stripe-bg)}.ResponsiveTable-module_responsiveTable__4y-Od tr:hover{background-color:var(--table-row-hover-bg)}.ResponsiveTable-module_cardContainer__Het4h{background-color:var(--rt-mobile-bg-wash);border-radius:var(--rt-mobile-card-radius);display:flex;flex-direction:column;gap:1.25rem;padding:1rem}.ResponsiveTable-module_card__b-U2v{background-color:var(--card-bg);border:1px solid var(--card-border-color);border-bottom:3px solid var(--primary-color);border-radius:var(--rt-mobile-card-radius);box-shadow:var(--rt-mobile-card-shadow);overflow:hidden;padding:1rem;transition:box-shadow .2s ease-in-out,transform .2s ease-in-out}.ResponsiveTable-module_card__b-U2v:hover{box-shadow:0 2px 4px rgba(0,0,0,.06),0 8px 24px rgba(0,0,0,.08),0 16px 48px rgba(0,0,0,.06);transform:translateY(-4px)}.ResponsiveTable-module_card-header__Ttk51{border-bottom:1px solid var(--table-border-color);margin-bottom:1rem;padding-bottom:.5rem}.ResponsiveTable-module_card-row__qvIUJ{align-items:flex-start;display:flex;gap:1rem;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB{align-items:stretch;flex-direction:column;gap:.25rem;margin-bottom:1rem}.ResponsiveTable-module_card-row__qvIUJ:last-child{margin-bottom:0}.ResponsiveTable-module_card-label__v9L71{color:var(--rt-mobile-label-color);font-size:.75rem;font-weight:600;text-transform:uppercase;white-space:nowrap}.ResponsiveTable-module_card-value__BO-c-{color:var(--rt-mobile-value-color);font-size:.95rem;text-align:right}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB .ResponsiveTable-module_card-value__BO-c-{text-align:left}.ResponsiveTable-module_numberValue__-TLR1{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;text-align:right!important}.ResponsiveTable-module_dateValue__UMvqJ{color:var(--text-color-muted);font-size:.85rem}.ResponsiveTable-module_imageValue__wVb-p img{border-radius:8px;height:auto;max-width:100%;object-fit:cover}.ResponsiveTable-module_inputValue__CrGMx{margin-top:.5rem;width:100%}.ResponsiveTable-module_inputValue__CrGMx button,.ResponsiveTable-module_inputValue__CrGMx input[type=text],.ResponsiveTable-module_inputValue__CrGMx select,.ResponsiveTable-module_inputValue__CrGMx textarea{min-height:44px;width:100%!important}.ResponsiveTable-module_clickableRow__0kjWm{cursor:pointer}.ResponsiveTable-module_clickableHeader__xHQhF{cursor:pointer;transition:color .2s}.ResponsiveTable-module_clickableHeader__xHQhF:hover{color:var(--interactive-color)}.ResponsiveTable-module_sortable__yvA60{cursor:pointer}.ResponsiveTable-module_sorted-asc__jzOIa,.ResponsiveTable-module_sorted-desc__7WCFK{background-color:#f0f7ff!important;color:var(--interactive-color)!important}.ResponsiveTable-module_headerInnerWrapper__3VAhD{align-items:center;display:flex;justify-content:space-between;width:100%}.ResponsiveTable-module_headerContent__ODMzS{flex-grow:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ResponsiveTable-module_sortIcon__A9WtD{background-position:50%;background-repeat:no-repeat;background-size:contain;flex-shrink:0;height:1rem;margin-left:.5rem;opacity:.3;width:1rem}.ResponsiveTable-module_sortable__yvA60:hover .ResponsiveTable-module_sortIcon__A9WtD{opacity:.8}.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236c757d'%3E%3Cpath d='M10 18h4v-2h-4v2zm-6-8v2h16V8H4zm3-6h10v2H7V2z'/%3E%3C/svg%3E\")}.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 14 5-5 5 5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 10 5 5 5-5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_responsiveTable__4y-Od tfoot{background-color:var(--table-header-bg);border-top:2px solid var(--table-border-color)}.ResponsiveTable-module_footerCell__8H-uG{font-size:.9rem;font-weight:600;padding:1rem;text-align:right}.ResponsiveTable-module_clickableFooterCell__WB9Ss{color:var(--interactive-color);cursor:pointer}.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover{text-decoration:underline}.ResponsiveTable-module_footerCard__-NE2M{background-color:var(--table-header-bg);border:1px solid var(--card-border-color);border-radius:12px;margin-top:1rem;overflow:hidden;padding:1.25rem}.ResponsiveTable-module_footer-card-row__Vv6Ur{display:flex;font-size:.9rem;font-weight:600;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_selectedRow__-JyNW{background-color:#e7f1ff!important}.ResponsiveTable-module_card__b-U2v.ResponsiveTable-module_selectedRow__-JyNW{border-left:4px solid var(--primary-color)}.ResponsiveTable-module_animatedRow__SFjrJ{animation:ResponsiveTable-module_cardEntrance__6JjRV .5s cubic-bezier(.2,.8,.2,1) forwards;opacity:0}@keyframes ResponsiveTable-module_cardEntrance__6JjRV{0%{opacity:0;transform:translateY(15px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ResponsiveTable-module_fadeInUp__jMCS7{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.ResponsiveTable-module_skeleton__XxsXW{background-color:#f0f0f0;border-radius:4px;overflow:hidden;position:relative}.ResponsiveTable-module_skeleton__XxsXW:after{animation:ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.6),transparent);content:\"\";height:100%;left:-150%;position:absolute;top:0;width:150%}@keyframes ResponsiveTable-module_shimmer__H8PhC{0%{transform:translateX(0)}to{transform:translateX(100%)}}.ResponsiveTable-module_noDataWrapper__Rj-k3{align-items:center;background-color:var(--table-header-bg);border:2px dashed var(--table-border-color);border-radius:12px;color:var(--text-color-muted);display:flex;flex-direction:column;gap:1rem;justify-content:center;padding:4rem 2rem}.ResponsiveTable-module_noData__IpwNq{font-size:1.1rem;font-weight:500}.ResponsiveTable-module_spinner__Pn-3D{animation:ResponsiveTable-module_spin__i3NHn .8s linear infinite;border:3px solid rgba(0,0,0,.1);border-left:3px solid var(--primary-color);border-radius:50%;height:24px;width:24px}@keyframes ResponsiveTable-module_spin__i3NHn{to{transform:rotate(1turn)}}.ResponsiveTable-module_infoContainer__b9IF5{align-items:center;color:var(--text-color-muted);display:flex;font-size:.85rem;gap:.5rem;justify-content:center;padding:1.5rem}.ResponsiveTable-module_stickyHeader__-jjN- th{box-shadow:0 2px 4px rgba(0,0,0,.05);position:sticky;top:0}.ResponsiveTable-module_internalStickyHeader__idiJY th{position:sticky;top:0}.ResponsiveTable-module_detailCell__hb9C5{background:rgba(0,0,0,.012);border-top:none;padding:0;transition:border-left .2s ease}.ResponsiveTable-module_detailCellHasContent__F-DX5{padding-bottom:.5rem}.ResponsiveTable-module_detailCellExpanded__Zr6UF{border-left:2px solid var(--primary-color,#3b82f6)}.ResponsiveTable-module_detailToggleBar__F5Qrk{height:0;overflow:hidden;transition:height .2s ease}.ResponsiveTable-module_detailToggleBarVisible__q9b-3{align-items:center;box-shadow:inset 0 1px 0 rgba(0,0,0,.04);cursor:pointer;display:flex;height:2rem;padding:0 .75rem;user-select:none}.ResponsiveTable-module_detailToggleBarVisible__q9b-3:hover{background:rgba(0,0,0,.02)}.ResponsiveTable-module_detailChevron__mBs8j{align-items:center;color:var(--primary-color,#3b82f6);display:flex;font-size:1.5rem;transform:rotate(-90deg);transition:transform .25s ease}.ResponsiveTable-module_detailChevronExpanded__zGFTQ{transform:rotate(0deg)}.ResponsiveTable-module_detailContentWrapper__VzM29{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s ease}.ResponsiveTable-module_detailContentWrapperExpanded__bkiUb{grid-template-rows:1fr}.ResponsiveTable-module_detailContentInner__GWVaq{overflow:hidden;padding-left:1.5rem}.ResponsiveTable-module_mobileDetailOuter__gusle{background:rgba(0,0,0,.012);overflow:hidden}";
32
+ var css_248z$2 = ".ResponsiveTable-module_responsiveTable__4y-Od{--table-border-color:#e0e0e0;--table-header-bg:#f8f9fa;--table-row-hover-bg:#f1f3f5;--table-row-stripe-bg:#fafbfc;--card-bg:#fff;--card-border-color:#d1d5db;--card-shadow:0 2px 8px rgba(0,0,0,.06);--text-color:#212529;--text-color-muted:#6c757d;--interactive-color:#0056b3;--primary-color:#007bff;--rt-mobile-card-shadow:0 1px 2px rgba(0,0,0,.04),0 4px 12px rgba(0,0,0,.06),0 12px 32px rgba(0,0,0,.04);--rt-mobile-card-radius:16px;--rt-mobile-bg-wash:#f1f5f9;--rt-mobile-label-color:#475569;--rt-mobile-value-color:#1e293b}.ResponsiveTable-module_tableContainer__VjWjH{border:1px solid var(--table-border-color);border-radius:8px;overflow-x:auto;width:100%}.ResponsiveTable-module_responsiveTable__4y-Od{background-color:var(--card-bg);border-collapse:collapse;color:var(--text-color);width:100%}.ResponsiveTable-module_responsiveTable__4y-Od thead th{background-color:var(--table-header-bg);border-bottom:2px solid var(--table-border-color);color:var(--text-color-muted);font-size:.75rem;font-weight:600;letter-spacing:.05em;padding:1rem;text-align:left;text-transform:uppercase;z-index:1}.ResponsiveTable-module_responsiveTable__4y-Od td{border-bottom:1px solid var(--table-border-color);font-size:.9rem;padding:1rem;text-align:left}.ResponsiveTable-module_responsiveTable__4y-Od tr:last-child td{border-bottom:none}.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(2n){background-color:var(--table-row-stripe-bg)}.ResponsiveTable-module_responsiveTable__4y-Od tr:hover{background-color:var(--table-row-hover-bg)}.ResponsiveTable-module_cardContainer__Het4h{background-color:var(--rt-mobile-bg-wash);border-radius:var(--rt-mobile-card-radius);display:flex;flex-direction:column;gap:1.25rem;padding:1rem}.ResponsiveTable-module_card__b-U2v{background-color:var(--card-bg);border:1px solid var(--card-border-color);border-bottom:3px solid var(--primary-color);border-radius:var(--rt-mobile-card-radius);box-shadow:var(--rt-mobile-card-shadow);overflow:hidden;padding:1rem;transition:box-shadow .2s ease-in-out,transform .2s ease-in-out}.ResponsiveTable-module_card__b-U2v:hover{box-shadow:0 2px 4px rgba(0,0,0,.06),0 8px 24px rgba(0,0,0,.08),0 16px 48px rgba(0,0,0,.06);transform:translateY(-4px)}.ResponsiveTable-module_card-header__Ttk51{border-bottom:1px solid var(--table-border-color);margin-bottom:1rem;padding-bottom:.5rem}.ResponsiveTable-module_card-row__qvIUJ{align-items:flex-start;display:flex;gap:1rem;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB{align-items:stretch;flex-direction:column;gap:.25rem;margin-bottom:1rem}.ResponsiveTable-module_card-row__qvIUJ:last-child{margin-bottom:0}.ResponsiveTable-module_card-label__v9L71{color:var(--rt-mobile-label-color);font-size:.75rem;font-weight:600;text-transform:uppercase;white-space:nowrap}.ResponsiveTable-module_card-value__BO-c-{color:var(--rt-mobile-value-color);font-size:.95rem;text-align:right}.ResponsiveTable-module_card-row__qvIUJ.ResponsiveTable-module_stacked__FSaTB .ResponsiveTable-module_card-value__BO-c-{text-align:left}.ResponsiveTable-module_numberValue__-TLR1{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;text-align:right!important}.ResponsiveTable-module_dateValue__UMvqJ{color:var(--text-color-muted);font-size:.85rem}.ResponsiveTable-module_imageValue__wVb-p img{border-radius:8px;height:auto;max-width:100%;object-fit:cover}.ResponsiveTable-module_inputValue__CrGMx{margin-top:.5rem;width:100%}.ResponsiveTable-module_inputValue__CrGMx button,.ResponsiveTable-module_inputValue__CrGMx input[type=text],.ResponsiveTable-module_inputValue__CrGMx select,.ResponsiveTable-module_inputValue__CrGMx textarea{min-height:44px;width:100%!important}.ResponsiveTable-module_clickableRow__0kjWm{cursor:pointer}.ResponsiveTable-module_responsiveTable__4y-Od tbody tr{transition:background-color .12s ease}.ResponsiveTable-module_responsiveTable__4y-Od tbody tr.ResponsiveTable-module_clickableRow__0kjWm:active{background-color:var(--table-row-active-bg,#dde3ea);transition:background-color .08s ease}.ResponsiveTable-module_responsiveTable__4y-Od tbody tr.ResponsiveTable-module_clickableRow__0kjWm:focus-visible{outline:2px solid var(--primary-color,#3b82f6);outline-offset:-2px}.ResponsiveTable-module_card__b-U2v.ResponsiveTable-module_clickableRow__0kjWm:active{box-shadow:0 1px 3px rgba(0,0,0,.08);transform:translateY(-1px);transition:transform .08s ease,box-shadow .08s ease}.ResponsiveTable-module_card__b-U2v.ResponsiveTable-module_clickableRow__0kjWm:focus-visible{outline:2px solid var(--primary-color,#3b82f6);outline-offset:-2px}.ResponsiveTable-module_clickableHeader__xHQhF{cursor:pointer;transition:color .2s}.ResponsiveTable-module_clickableHeader__xHQhF:hover{color:var(--interactive-color)}.ResponsiveTable-module_sortable__yvA60{cursor:pointer}.ResponsiveTable-module_sorted-asc__jzOIa,.ResponsiveTable-module_sorted-desc__7WCFK{background-color:#f0f7ff!important;color:var(--interactive-color)!important}.ResponsiveTable-module_headerInnerWrapper__3VAhD{align-items:center;display:flex;justify-content:space-between;width:100%}.ResponsiveTable-module_headerContent__ODMzS{flex-grow:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ResponsiveTable-module_sortIcon__A9WtD{background-position:50%;background-repeat:no-repeat;background-size:contain;flex-shrink:0;height:1rem;margin-left:.5rem;opacity:.3;width:1rem}.ResponsiveTable-module_sortable__yvA60:hover .ResponsiveTable-module_sortIcon__A9WtD{opacity:.8}.ResponsiveTable-module_sortable__yvA60 .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236c757d'%3E%3Cpath d='M10 18h4v-2h-4v2zm-6-8v2h16V8H4zm3-6h10v2H7V2z'/%3E%3C/svg%3E\")}.ResponsiveTable-module_sorted-asc__jzOIa .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 14 5-5 5 5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_sorted-desc__7WCFK .ResponsiveTable-module_sortIcon__A9WtD{background-image:url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%230056b3'%3E%3Cpath d='m7 10 5 5 5-5z'/%3E%3C/svg%3E\");opacity:1}.ResponsiveTable-module_responsiveTable__4y-Od tfoot{background-color:var(--table-header-bg);border-top:2px solid var(--table-border-color)}.ResponsiveTable-module_footerCell__8H-uG{font-size:.9rem;font-weight:600;padding:1rem;text-align:right}.ResponsiveTable-module_clickableFooterCell__WB9Ss{color:var(--interactive-color);cursor:pointer}.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover{text-decoration:underline}.ResponsiveTable-module_footerCard__-NE2M{background-color:var(--table-header-bg);border:1px solid var(--card-border-color);border-radius:12px;margin-top:1rem;overflow:hidden;padding:1.25rem}.ResponsiveTable-module_footer-card-row__Vv6Ur{display:flex;font-size:.9rem;font-weight:600;justify-content:space-between;margin:0 0 .75rem}.ResponsiveTable-module_selectedRow__-JyNW{background-color:#e7f1ff!important;transition:background-color .15s ease}.ResponsiveTable-module_card__b-U2v.ResponsiveTable-module_selectedRow__-JyNW{background-color:#e7f1ff;border-left:4px solid var(--primary-color)}.ResponsiveTable-module_animatedRow__SFjrJ{animation:ResponsiveTable-module_cardEntrance__6JjRV .5s cubic-bezier(.2,.8,.2,1) forwards;opacity:0}@keyframes ResponsiveTable-module_cardEntrance__6JjRV{0%{opacity:0;transform:translateY(15px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes ResponsiveTable-module_fadeInUp__jMCS7{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.ResponsiveTable-module_skeleton__XxsXW{background-color:#f0f0f0;border-radius:4px;overflow:hidden;position:relative}.ResponsiveTable-module_skeleton__XxsXW:after{animation:ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.6),transparent);content:\"\";height:100%;left:-150%;position:absolute;top:0;width:150%}@keyframes ResponsiveTable-module_shimmer__H8PhC{0%{transform:translateX(0)}to{transform:translateX(100%)}}.ResponsiveTable-module_noDataWrapper__Rj-k3{align-items:center;background-color:var(--table-header-bg);border:2px dashed var(--table-border-color);border-radius:12px;color:var(--text-color-muted);display:flex;flex-direction:column;gap:1rem;justify-content:center;padding:4rem 2rem}.ResponsiveTable-module_noData__IpwNq{font-size:1.1rem;font-weight:500}.ResponsiveTable-module_spinner__Pn-3D{animation:ResponsiveTable-module_spin__i3NHn .8s linear infinite;border:3px solid rgba(0,0,0,.1);border-left:3px solid var(--primary-color);border-radius:50%;height:24px;width:24px}@keyframes ResponsiveTable-module_spin__i3NHn{to{transform:rotate(1turn)}}.ResponsiveTable-module_infoContainer__b9IF5{align-items:center;color:var(--text-color-muted);display:flex;font-size:.85rem;gap:.5rem;justify-content:center;padding:1.5rem}.ResponsiveTable-module_stickyHeader__-jjN- th{box-shadow:0 2px 4px rgba(0,0,0,.05);position:sticky;top:0}.ResponsiveTable-module_internalStickyHeader__idiJY th{position:sticky;top:0}.ResponsiveTable-module_detailCell__hb9C5{background:rgba(0,0,0,.012);border-top:none;padding:0;transition:border-left .2s ease}.ResponsiveTable-module_detailCellHasContent__F-DX5{padding-bottom:.5rem}.ResponsiveTable-module_detailCellExpanded__Zr6UF{border-left:2px solid var(--primary-color,#3b82f6)}.ResponsiveTable-module_detailToggleBar__F5Qrk{height:0;overflow:hidden;transition:height .2s ease}.ResponsiveTable-module_detailToggleBarVisible__q9b-3{align-items:center;background:rgba(59,130,246,.08);box-shadow:inset 0 1px 0 rgba(0,0,0,.04);cursor:pointer;display:flex;height:2.5rem;padding:0 .75rem;user-select:none}.ResponsiveTable-module_detailToggleBarVisible__q9b-3:hover{background:rgba(59,130,246,.14)}.ResponsiveTable-module_detailChevron__mBs8j{align-items:center;color:var(--primary-color,#3b82f6);display:flex;font-size:2.2rem;transform:rotate(-90deg);transition:transform .25s ease}.ResponsiveTable-module_detailChevronExpanded__zGFTQ{transform:rotate(0deg)}.ResponsiveTable-module_detailContentWrapper__VzM29{display:grid;grid-template-rows:0fr;transition:grid-template-rows .3s ease}.ResponsiveTable-module_detailContentWrapperExpanded__bkiUb{grid-template-rows:1fr}.ResponsiveTable-module_detailContentInner__GWVaq{overflow:hidden;padding-left:1.5rem}.ResponsiveTable-module_mobileDetailOuter__gusle{background:rgba(0,0,0,.012);overflow:hidden}";
33
33
  var styles$2 = {"responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","tableContainer":"ResponsiveTable-module_tableContainer__VjWjH","cardContainer":"ResponsiveTable-module_cardContainer__Het4h","card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-row":"ResponsiveTable-module_card-row__qvIUJ","stacked":"ResponsiveTable-module_stacked__FSaTB","card-label":"ResponsiveTable-module_card-label__v9L71","card-value":"ResponsiveTable-module_card-value__BO-c-","numberValue":"ResponsiveTable-module_numberValue__-TLR1","dateValue":"ResponsiveTable-module_dateValue__UMvqJ","imageValue":"ResponsiveTable-module_imageValue__wVb-p","inputValue":"ResponsiveTable-module_inputValue__CrGMx","clickableRow":"ResponsiveTable-module_clickableRow__0kjWm","clickableHeader":"ResponsiveTable-module_clickableHeader__xHQhF","sortable":"ResponsiveTable-module_sortable__yvA60","sorted-asc":"ResponsiveTable-module_sorted-asc__jzOIa","sorted-desc":"ResponsiveTable-module_sorted-desc__7WCFK","headerInnerWrapper":"ResponsiveTable-module_headerInnerWrapper__3VAhD","headerContent":"ResponsiveTable-module_headerContent__ODMzS","sortIcon":"ResponsiveTable-module_sortIcon__A9WtD","footerCell":"ResponsiveTable-module_footerCell__8H-uG","clickableFooterCell":"ResponsiveTable-module_clickableFooterCell__WB9Ss","footerCard":"ResponsiveTable-module_footerCard__-NE2M","footer-card-row":"ResponsiveTable-module_footer-card-row__Vv6Ur","selectedRow":"ResponsiveTable-module_selectedRow__-JyNW","animatedRow":"ResponsiveTable-module_animatedRow__SFjrJ","cardEntrance":"ResponsiveTable-module_cardEntrance__6JjRV","skeleton":"ResponsiveTable-module_skeleton__XxsXW","shimmer":"ResponsiveTable-module_shimmer__H8PhC","noDataWrapper":"ResponsiveTable-module_noDataWrapper__Rj-k3","noData":"ResponsiveTable-module_noData__IpwNq","spinner":"ResponsiveTable-module_spinner__Pn-3D","spin":"ResponsiveTable-module_spin__i3NHn","infoContainer":"ResponsiveTable-module_infoContainer__b9IF5","stickyHeader":"ResponsiveTable-module_stickyHeader__-jjN-","internalStickyHeader":"ResponsiveTable-module_internalStickyHeader__idiJY","detailCell":"ResponsiveTable-module_detailCell__hb9C5","detailCellHasContent":"ResponsiveTable-module_detailCellHasContent__F-DX5","detailCellExpanded":"ResponsiveTable-module_detailCellExpanded__Zr6UF","detailToggleBar":"ResponsiveTable-module_detailToggleBar__F5Qrk","detailToggleBarVisible":"ResponsiveTable-module_detailToggleBarVisible__q9b-3","detailChevron":"ResponsiveTable-module_detailChevron__mBs8j","detailChevronExpanded":"ResponsiveTable-module_detailChevronExpanded__zGFTQ","detailContentWrapper":"ResponsiveTable-module_detailContentWrapper__VzM29","detailContentWrapperExpanded":"ResponsiveTable-module_detailContentWrapperExpanded__bkiUb","detailContentInner":"ResponsiveTable-module_detailContentInner__GWVaq","mobileDetailOuter":"ResponsiveTable-module_mobileDetailOuter__gusle","fadeInUp":"ResponsiveTable-module_fadeInUp__jMCS7"};
34
34
  styleInject(css_248z$2);
35
35
 
@@ -215,7 +215,7 @@ function TableBodyRow(props) {
215
215
  const rowProps = getRowProps(row);
216
216
  const isClickable = onRowClick || selectionProps;
217
217
  const pluginOnClick = rowProps.onClick;
218
- return (React.createElement("tr", { className: `${isClickable ? styles$2.clickableRow : ''} ${(animationProps === null || animationProps === void 0 ? void 0 : animationProps.animateOnLoad) ? styles$2.animatedRow : ''} ${rowProps.className || ''}`.trim(), style: { animationDelay: `${rowIndex * 0.05}s` }, "aria-selected": rowProps['aria-selected'], onClickCapture: (e) => {
218
+ return (React.createElement("tr", { className: `${isClickable ? styles$2.clickableRow : ''} ${(animationProps === null || animationProps === void 0 ? void 0 : animationProps.animateOnLoad) ? styles$2.animatedRow : ''} ${rowProps.className || ''}`.trim(), style: { animationDelay: `${rowIndex * 0.05}s` }, tabIndex: isClickable ? 0 : undefined, "aria-selected": rowProps['aria-selected'], onClickCapture: (e) => {
219
219
  // Capture Phase: Check for the ignore attribute BEFORE child handlers run.
220
220
  // This prevents issues where child handlers trigger a re-render/unmount
221
221
  // that detaches the target from the DOM before the bubbling phase.
@@ -238,7 +238,7 @@ function TableBodyRow(props) {
238
238
  React.createElement(TableBodyCell, { row: row, rowIndex: rowIndex, columnDefinition: columnDefinition }))))));
239
239
  }
240
240
 
241
- function DetailRow({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle }) {
241
+ function DetailRow({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onToggle, expandChevronClassName }) {
242
242
  const content = expandRowRenderer(row, rowIndex);
243
243
  const hasContent = content != null;
244
244
  const [everExpanded, setEverExpanded] = useState(false);
@@ -252,6 +252,7 @@ function DetailRow({ row, rowIndex, colSpan, expandRowRenderer, isExpanded, onTo
252
252
  const chevronClass = [
253
253
  styles$2.detailChevron,
254
254
  isExpanded ? styles$2.detailChevronExpanded : '',
255
+ expandChevronClassName !== null && expandChevronClassName !== void 0 ? expandChevronClassName : '',
255
256
  ].join(' ').trim();
256
257
  return (React.createElement("tr", null,
257
258
  React.createElement("td", { colSpan: colSpan, className: tdClass },
@@ -300,7 +301,7 @@ const TableSentinel = ({ onIntersect, isLoading }) => {
300
301
 
301
302
  function DesktopView(props) {
302
303
  const { maxHeight, isHeaderSticky, tableContainerRef, headerRef, footerRows, renderPluginFooters, onScroll, } = props;
303
- const { visibleColumns, originalColumnDefinitions, currentData, getRawColumnDefinition, onRowClick, selectionProps, animationProps, pagination, expandRowRenderer, getRowId, } = useTableContext();
304
+ const { visibleColumns, originalColumnDefinitions, currentData, getRawColumnDefinition, onRowClick, selectionProps, animationProps, pagination, expandRowRenderer, expandChevronClassName, getRowId, } = useTableContext();
304
305
  const [expandedIds, setExpandedIds] = useState(new Set());
305
306
  const toggleExpanded = useCallback((id) => {
306
307
  setExpandedIds(prev => {
@@ -356,7 +357,7 @@ function DesktopView(props) {
356
357
  const rowId = getRowId(row, rowIndex);
357
358
  return (React.createElement(React.Fragment, { key: rowId },
358
359
  React.createElement(TableBodyRow, { row: row, rowIndex: rowIndex, columnDefinitions: visibleColumns, onRowClick: onRowClick, selectionProps: selectionProps, animationProps: animationProps }),
359
- expandRowRenderer && (React.createElement(DetailRow, { row: row, rowIndex: rowIndex, colSpan: visibleColumns.length, expandRowRenderer: expandRowRenderer, isExpanded: expandedIds.has(rowId), onToggle: () => toggleExpanded(rowId) }))));
360
+ expandRowRenderer && (React.createElement(DetailRow, { row: row, rowIndex: rowIndex, colSpan: visibleColumns.length, expandRowRenderer: expandRowRenderer, isExpanded: expandedIds.has(rowId), onToggle: () => toggleExpanded(rowId), expandChevronClassName: expandChevronClassName }))));
360
361
  })),
361
362
  tableFooter),
362
363
  (pagination === null || pagination === void 0 ? void 0 : pagination.hasMore) && (React.createElement(TableSentinel, { onIntersect: () => pagination.loadNextPage(), isLoading: pagination.isFetchingMore })),
@@ -366,7 +367,7 @@ function DesktopView(props) {
366
367
  renderPluginFooters()));
367
368
  }
368
369
 
369
- function MobileDetailSection({ row, rowIndex, expandRowRenderer, isExpanded, onToggle }) {
370
+ function MobileDetailSection({ row, rowIndex, expandRowRenderer, isExpanded, onToggle, expandChevronClassName }) {
370
371
  const content = expandRowRenderer(row, rowIndex);
371
372
  const hasContent = content != null;
372
373
  const [everExpanded, setEverExpanded] = useState(false);
@@ -377,6 +378,7 @@ function MobileDetailSection({ row, rowIndex, expandRowRenderer, isExpanded, onT
377
378
  const chevronClass = [
378
379
  styles$2.detailChevron,
379
380
  isExpanded ? styles$2.detailChevronExpanded : '',
381
+ expandChevronClassName !== null && expandChevronClassName !== void 0 ? expandChevronClassName : '',
380
382
  ].join(' ').trim();
381
383
  const outerClass = [
382
384
  styles$2.mobileDetailOuter,
@@ -395,7 +397,7 @@ function MobileDetailSection({ row, rowIndex, expandRowRenderer, isExpanded, onT
395
397
  }
396
398
  function MobileView(props) {
397
399
  const { mobileFooter } = props;
398
- const { currentData, visibleColumns, onRowClick, selectionProps, animationProps, getRowProps, getRowId, getColumnDefinition, onHeaderClickCallback, getClickableHeaderClassName, pagination, mobileCardClassName, expandRowRenderer, } = useTableContext();
400
+ const { currentData, visibleColumns, onRowClick, selectionProps, animationProps, getRowProps, getRowId, getColumnDefinition, onHeaderClickCallback, getClickableHeaderClassName, pagination, mobileCardClassName, expandRowRenderer, expandChevronClassName, } = useTableContext();
399
401
  const isClickable = onRowClick || selectionProps;
400
402
  const [expandedIds, setExpandedIds] = useState(new Set());
401
403
  const toggleExpanded = useCallback((id) => {
@@ -450,7 +452,7 @@ function MobileView(props) {
450
452
  const rowProps = getRowProps(row);
451
453
  const pluginOnClick = rowProps.onClick;
452
454
  return (React.createElement(React.Fragment, { key: getRowId(row, rowIndex) },
453
- React.createElement("div", { className: `${styles$2.card} ${isClickable ? styles$2.clickableRow : ''} ${(animationProps === null || animationProps === void 0 ? void 0 : animationProps.animateOnLoad) ? styles$2.animatedRow : ''} ${rowProps.className || ''} ${mobileCardClassName || ''}`.trim(), style: { animationDelay: `${rowIndex * 0.05}s` }, "aria-selected": rowProps['aria-selected'], onClickCapture: (e) => {
455
+ React.createElement("div", { className: `${styles$2.card} ${isClickable ? styles$2.clickableRow : ''} ${(animationProps === null || animationProps === void 0 ? void 0 : animationProps.animateOnLoad) ? styles$2.animatedRow : ''} ${rowProps.className || ''} ${mobileCardClassName || ''}`.trim(), style: { animationDelay: `${rowIndex * 0.05}s` }, tabIndex: isClickable ? 0 : undefined, "aria-selected": rowProps['aria-selected'], onClickCapture: (e) => {
454
456
  const target = e.target;
455
457
  if (target.closest('[data-rt-ignore-row-click]')) {
456
458
  e.nativeEvent._rtIgnoreRowClick = true;
@@ -483,7 +485,7 @@ function MobileView(props) {
483
485
  React.createElement("span", { className: `${styles$2['card-value']} ${typeClassName} ${colDef.cellClassName || ''}`, style: colDef.cellStyle },
484
486
  React.createElement(TableBodyCell, { row: row, rowIndex: rowIndex, columnDefinition: columnDefinition }))));
485
487
  }))),
486
- expandRowRenderer && (React.createElement(MobileDetailSection, { row: row, rowIndex: rowIndex, expandRowRenderer: expandRowRenderer, isExpanded: expandedIds.has(getRowId(row, rowIndex)), onToggle: () => toggleExpanded(getRowId(row, rowIndex)) }))));
488
+ expandRowRenderer && (React.createElement(MobileDetailSection, { row: row, rowIndex: rowIndex, expandRowRenderer: expandRowRenderer, isExpanded: expandedIds.has(getRowId(row, rowIndex)), onToggle: () => toggleExpanded(getRowId(row, rowIndex)), expandChevronClassName: expandChevronClassName }))));
487
489
  }),
488
490
  (pagination === null || pagination === void 0 ? void 0 : pagination.hasMore) && (React.createElement(TableSentinel, { onIntersect: () => pagination.loadNextPage(), isLoading: pagination.isFetchingMore })),
489
491
  (pagination === null || pagination === void 0 ? void 0 : pagination.isFetchingMore) && (React.createElement("div", { className: styles$2.infoContainer },
@@ -1249,7 +1251,7 @@ const useTableDataSource = (props) => {
1249
1251
  * Supports static data or async data sources with built-in infinite scroll.
1250
1252
  */
1251
1253
  function ResponsiveTableInner(props, ref) {
1252
- const { columnDefinitions, data: initialData, dataSource, pageSize, noDataComponent, maxHeight, onRowClick, footerRows, mobileBreakpoint, plugins, enablePageLevelStickyHeader, infiniteScrollProps, filterProps, selectionProps, animationProps, sortProps, mobileCardClassName, onDataSourceStateChange, onPageChange, onDataSourceError, expandRowRenderer, } = props;
1254
+ const { columnDefinitions, data: initialData, dataSource, pageSize, noDataComponent, maxHeight, onRowClick, footerRows, mobileBreakpoint, plugins, enablePageLevelStickyHeader, infiniteScrollProps, filterProps, selectionProps, animationProps, sortProps, mobileCardClassName, onDataSourceStateChange, onPageChange, onDataSourceError, expandRowRenderer, expandChevronClassName, } = props;
1253
1255
  const tableContainerRef = useRef(null);
1254
1256
  const headerRef = useRef(null);
1255
1257
  const { isMobile, isHeaderSticky } = useResponsiveTable({
@@ -1455,6 +1457,7 @@ function ResponsiveTableInner(props, ref) {
1455
1457
  } : undefined,
1456
1458
  mobileCardClassName,
1457
1459
  expandRowRenderer,
1460
+ expandChevronClassName,
1458
1461
  } },
1459
1462
  React.createElement("div", null,
1460
1463
  React.createElement("div", { style: { display: 'flex', justifyContent: 'flex-end' } }, renderPluginHeaders()),