@jirawatpyk/aura-react 5.4.0 → 5.5.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
@@ -186,6 +186,19 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
186
186
  - **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
187
187
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
188
188
 
189
+ ## 5.5 — DataTable is generic over its rows
190
+
191
+ - The type of `rows` is the table's row type, and every `render`, `sortValue`, `getRowHref` and `onRowActivate` gets it — no annotations, and a typo inside a callback (`r.amuont`) or a callback written for another type is a compile error (column `key`s stay plain strings):
192
+
193
+ ```tsx
194
+ const columns: DataTableColumn<Order>[] = [{ key: 'amount', label: 'AMOUNT', align: 'end', render: (r) => baht(r.amount) }];
195
+ <DataTable label="Orders" rows={orders} columns={columns} onRowActivate={setDetail} getRowHref={(r) => '/orders/' + r.id} />
196
+ ```
197
+
198
+ - `DataTableColumn<Row>` types a column list declared on its own; `<DataTable<Order> …>` names the type explicitly. `rows={[]}` (nothing loaded yet) keeps the untyped default, and so do `any[]`, `Record<string, any>[]` and anything reading `typeof DataTable` (`ComponentProps`, `memo`, wrappers).
199
+ - Two type-level changes: rows that are a union of arrays (`cond ? orders : invoices`) need the type named, `<DataTable<Order | Invoice> …>`; rows typed `Record<string, unknown>[]` give `render` an `unknown` value, so convert it (`String(r.n)`).
200
+ - Types only; nothing changes at run time. `typeof DataTable` is now a generic function type rather than `ForwardRefExoticComponent` (it still takes `ref`).
201
+
189
202
  ## 5.4 — types, and TypeScript across the repo
190
203
 
191
204
  - **DataTable** takes rows of your own interface (`rows={orders}` with `interface Order {…}`; readonly arrays too), and `render`, `sortValue`, `getRowHref` and `onRowActivate` can be written with it: `render: (r: Order) => baht(r.amount)` — no cast from `Record<string, any>`.
@@ -68,7 +68,7 @@ window.Aura = (() => {
68
68
  Combobox: () => Combobox,
69
69
  Command: () => Command,
70
70
  Container: () => Container,
71
- DataTable: () => DataTable,
71
+ DataTable: () => DataTable2,
72
72
  DatePicker: () => DatePicker,
73
73
  DateRangePicker: () => DateRangePicker,
74
74
  Dialog: () => Dialog,
@@ -3982,7 +3982,7 @@ window.Aura = (() => {
3982
3982
  var ROW_H_DEFAULT = 48;
3983
3983
  var OVERSCAN = 8;
3984
3984
  var FLEX_MIN = 160;
3985
- var DataTable = React28.forwardRef(function DataTable2(props, ref) {
3985
+ var DataTableImpl = React28.forwardRef(function DataTable(props, ref) {
3986
3986
  const t = useStrings();
3987
3987
  const columns = props.columns || DEFAULT_COLUMNS;
3988
3988
  const byKey = {};
@@ -5217,6 +5217,7 @@ window.Aura = (() => {
5217
5217
  }
5218
5218
  return /* @__PURE__ */ React28.createElement("div", { ref, className: cx("aura-table-box", props.className) }, out);
5219
5219
  });
5220
+ var DataTable2 = DataTableImpl;
5220
5221
 
5221
5222
  // src/Card.tsx
5222
5223
  var React29 = __toESM(require_react(), 1);
@@ -49,7 +49,7 @@ __export(index_exports, {
49
49
  Combobox: () => Combobox,
50
50
  Command: () => Command,
51
51
  Container: () => Container,
52
- DataTable: () => DataTable,
52
+ DataTable: () => DataTable2,
53
53
  DatePicker: () => DatePicker,
54
54
  DateRangePicker: () => DateRangePicker,
55
55
  Dialog: () => Dialog,
@@ -3964,7 +3964,7 @@ function hidePx(c) {
3964
3964
  var ROW_H_DEFAULT = 48;
3965
3965
  var OVERSCAN = 8;
3966
3966
  var FLEX_MIN = 160;
3967
- var DataTable = React28.forwardRef(function DataTable2(props, ref) {
3967
+ var DataTableImpl = React28.forwardRef(function DataTable(props, ref) {
3968
3968
  const t = useStrings();
3969
3969
  const columns = props.columns || DEFAULT_COLUMNS;
3970
3970
  const byKey = {};
@@ -5199,6 +5199,7 @@ var DataTable = React28.forwardRef(function DataTable2(props, ref) {
5199
5199
  }
5200
5200
  return /* @__PURE__ */ React28.createElement("div", { ref, className: cx("aura-table-box", props.className) }, out);
5201
5201
  });
5202
+ var DataTable2 = DataTableImpl;
5202
5203
 
5203
5204
  // src/Card.tsx
5204
5205
  var React29 = __toESM(require("react"), 1);
@@ -27,7 +27,7 @@ function hidePx(c) {
27
27
  return px != null && px > 0 ? px : void 0;
28
28
  }
29
29
  const ROW_H_DEFAULT = 48, OVERSCAN = 8, FLEX_MIN = 160;
30
- const DataTable = React.forwardRef(function DataTable2(props, ref) {
30
+ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
31
31
  const t = useStrings();
32
32
  const columns = props.columns || DEFAULT_COLUMNS;
33
33
  const byKey = {};
@@ -1262,6 +1262,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1262
1262
  }
1263
1263
  return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-table-box", props.className) }, out);
1264
1264
  });
1265
+ const DataTable2 = DataTableImpl;
1265
1266
  export {
1266
- DataTable
1267
+ DataTable2 as DataTable
1267
1268
  };
package/dist/index.d.cts CHANGED
@@ -46,12 +46,18 @@ export interface DataTableState {
46
46
  sort: DataTableSort | null;
47
47
  page: number;
48
48
  }
49
- /** A callback that gets one row. Written with your own row type (`(r: Order) => …`) it still fits (5.4):
50
- * the row is checked the way method parameters are, so no cast from `Record<string, any>` is needed. */
51
- export type RowCallback<R> = {
52
- bivarianceHack(row: Record<string, any>): R;
49
+ /** Internal helper (exported only because the declarations reference it): `T` as written, but never inferred from
50
+ * this position (works before TypeScript 5.4's own `NoInfer`), so a table's row type comes from its `rows`. */
51
+ export type NoInferRow<T> = [
52
+ T
53
+ ][T extends any ? 0 : never];
54
+ /** A callback that gets one row of type `Row` and returns `T`. Checked the way method parameters are, so a callback
55
+ * written for a narrower or wider row type still fits; one written for an unrelated type is an error (5.5). */
56
+ export type RowCallback<T, Row = Record<string, any>> = {
57
+ bivarianceHack(row: NoInferRow<Row>): T;
53
58
  }["bivarianceHack"];
54
- export interface DataTableColumn {
59
+ /** One column. `Row` is the table's row type (5.5): `DataTableColumn<Order>` types `render` and `sortValue`. */
60
+ export interface DataTableColumn<Row extends Record<string, any> = Record<string, any>> {
55
61
  /** Key into each row object. */
56
62
  key: string;
57
63
  /** Header label (source style: UPPERCASE). */
@@ -67,9 +73,9 @@ export interface DataTableColumn {
67
73
  /** Header becomes a button cycling asc → desc → unsorted. */
68
74
  sortable?: boolean | undefined;
69
75
  /** Value to sort by, when not the cell value (dates, amounts). */
70
- sortValue?: RowCallback<string | number | null> | undefined;
76
+ sortValue?: RowCallback<string | number | null, Row> | undefined;
71
77
  /** Custom cell content. */
72
- render?: RowCallback<React$1.ReactNode> | undefined;
78
+ render?: RowCallback<React$1.ReactNode, Row> | undefined;
73
79
  /** Set false to keep a sized column fixed when the table is `resizable`. */
74
80
  resizable?: boolean | undefined;
75
81
  /** Resize limits in px. Defaults 64 / 480. For the flexible column, minWidth defaults to 160. */
@@ -99,13 +105,14 @@ export interface DataTableEmpty {
99
105
  /** One action, usually a secondary Button. */
100
106
  action?: React$1.ReactNode | undefined;
101
107
  }
102
- /** Enterprise data table: 48px rows, hairline dividers, mono header band. */
103
- export interface DataTableProps {
108
+ /** Enterprise data table: 48px rows, hairline dividers, mono header band. Generic over the row type (5.5): with
109
+ * `rows={orders}` every `render`, `sortValue`, `getRowHref` and `onRowActivate` gets an `Order`. */
110
+ export interface DataTableProps<Row extends Record<string, any> = Record<string, any>> {
104
111
  /** Defaults to ID · NAME · STATUS · OWNER (96 / 160 / 112 / auto px). */
105
- columns?: DataTableColumn[] | undefined;
106
- /** Row objects. Any typed interface works (5.4: before, `interface Order {…}` rows needed a cast); cells show
107
- * the value at each column's key unless the column has `render`. */
108
- rows: ReadonlyArray<Record<string, any>>;
112
+ columns?: DataTableColumn<Row>[] | undefined;
113
+ /** Row objects, of any interface; their type is the table's row type. Cells show the value at each column's key
114
+ * unless the column has `render`. */
115
+ rows: ReadonlyArray<Row>;
109
116
  /** Column key giving each row a unique React key. Default: the first column's key. */
110
117
  rowKey?: string | undefined;
111
118
  /** Accessible name for the table. */
@@ -152,7 +159,7 @@ export interface DataTableProps {
152
159
  totalRows?: number | undefined;
153
160
  /** Makes each row a link: the first column's content renders as the provider's linkComponent (or `<a>`), and a click
154
161
  * or Enter anywhere on the row follows it. Ctrl/⌘-click opens a new tab as usual. */
155
- getRowHref?: RowCallback<string> | undefined;
162
+ getRowHref?: RowCallback<string, Row> | undefined;
156
163
  /** Pager arrows become links to these URLs (search-param paging). Without onPageChange the link navigates. */
157
164
  getPageHref?: ((page: number) => string) | undefined;
158
165
  /** Router link for getRowHref / getPageHref. Default: AuraProvider's linkComponent, else `<a>`. */
@@ -160,7 +167,7 @@ export interface DataTableProps {
160
167
  /** Skeleton row count when there is no pageSize. Default 5. */
161
168
  skeletonRows?: number | undefined;
162
169
  /** Called on row click or Enter. */
163
- onRowActivate?: RowCallback<void> | undefined;
170
+ onRowActivate?: RowCallback<void, Row> | undefined;
164
171
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
165
172
  height?: number | undefined;
166
173
  /** Column menu on every header, drag-to-reorder, and the show/hide columns button. */
@@ -1290,8 +1297,15 @@ export declare const Tooltip: React$1.ForwardRefExoticComponent<TooltipProps & R
1290
1297
  export declare const Dialog: React$1.ForwardRefExoticComponent<DialogProps & React$1.RefAttributes<HTMLDivElement>>;
1291
1298
  /** Side panel over the page: record detail, filters, mobile navigation. Modal (focus trap, scroll lock, focus restore). */
1292
1299
  export declare const Drawer: React$1.ForwardRefExoticComponent<DrawerProps & React$1.RefAttributes<HTMLDivElement>>;
1293
- /** Enterprise data table: 48px rows, hairline dividers, mono header band. */
1294
- export declare const DataTable: React$1.ForwardRefExoticComponent<DataTableProps & React$1.RefAttributes<HTMLDivElement>>;
1300
+ /** Enterprise data table: 48px rows, hairline dividers, mono header band. Generic over the row type (5.5): the
1301
+ * type of `rows` types every `render`, `sortValue`, `getRowHref` and `onRowActivate`. */
1302
+ export declare const DataTable: {
1303
+ (props: DataTableProps & {
1304
+ rows: readonly never[];
1305
+ } & React$1.RefAttributes<HTMLDivElement>): React$1.ReactElement | null;
1306
+ <Row extends Record<string, any> = Record<string, any>>(props: DataTableProps<Row> & React$1.RefAttributes<HTMLDivElement>): React$1.ReactElement | null;
1307
+ displayName?: string | undefined;
1308
+ };
1295
1309
  export declare const Card: React$1.ForwardRefExoticComponent<CardProps & React$1.RefAttributes<HTMLElement>>;
1296
1310
  export declare const Tabs: React$1.ForwardRefExoticComponent<TabsProps & React$1.RefAttributes<HTMLDivElement>>;
1297
1311
  /** Side navigation: sections of links or buttons, collapsible groups, counts and badges. Arrow keys move between items. */
package/dist/index.d.ts CHANGED
@@ -46,12 +46,18 @@ export interface DataTableState {
46
46
  sort: DataTableSort | null;
47
47
  page: number;
48
48
  }
49
- /** A callback that gets one row. Written with your own row type (`(r: Order) => …`) it still fits (5.4):
50
- * the row is checked the way method parameters are, so no cast from `Record<string, any>` is needed. */
51
- export type RowCallback<R> = {
52
- bivarianceHack(row: Record<string, any>): R;
49
+ /** Internal helper (exported only because the declarations reference it): `T` as written, but never inferred from
50
+ * this position (works before TypeScript 5.4's own `NoInfer`), so a table's row type comes from its `rows`. */
51
+ export type NoInferRow<T> = [
52
+ T
53
+ ][T extends any ? 0 : never];
54
+ /** A callback that gets one row of type `Row` and returns `T`. Checked the way method parameters are, so a callback
55
+ * written for a narrower or wider row type still fits; one written for an unrelated type is an error (5.5). */
56
+ export type RowCallback<T, Row = Record<string, any>> = {
57
+ bivarianceHack(row: NoInferRow<Row>): T;
53
58
  }["bivarianceHack"];
54
- export interface DataTableColumn {
59
+ /** One column. `Row` is the table's row type (5.5): `DataTableColumn<Order>` types `render` and `sortValue`. */
60
+ export interface DataTableColumn<Row extends Record<string, any> = Record<string, any>> {
55
61
  /** Key into each row object. */
56
62
  key: string;
57
63
  /** Header label (source style: UPPERCASE). */
@@ -67,9 +73,9 @@ export interface DataTableColumn {
67
73
  /** Header becomes a button cycling asc → desc → unsorted. */
68
74
  sortable?: boolean | undefined;
69
75
  /** Value to sort by, when not the cell value (dates, amounts). */
70
- sortValue?: RowCallback<string | number | null> | undefined;
76
+ sortValue?: RowCallback<string | number | null, Row> | undefined;
71
77
  /** Custom cell content. */
72
- render?: RowCallback<React$1.ReactNode> | undefined;
78
+ render?: RowCallback<React$1.ReactNode, Row> | undefined;
73
79
  /** Set false to keep a sized column fixed when the table is `resizable`. */
74
80
  resizable?: boolean | undefined;
75
81
  /** Resize limits in px. Defaults 64 / 480. For the flexible column, minWidth defaults to 160. */
@@ -99,13 +105,14 @@ export interface DataTableEmpty {
99
105
  /** One action, usually a secondary Button. */
100
106
  action?: React$1.ReactNode | undefined;
101
107
  }
102
- /** Enterprise data table: 48px rows, hairline dividers, mono header band. */
103
- export interface DataTableProps {
108
+ /** Enterprise data table: 48px rows, hairline dividers, mono header band. Generic over the row type (5.5): with
109
+ * `rows={orders}` every `render`, `sortValue`, `getRowHref` and `onRowActivate` gets an `Order`. */
110
+ export interface DataTableProps<Row extends Record<string, any> = Record<string, any>> {
104
111
  /** Defaults to ID · NAME · STATUS · OWNER (96 / 160 / 112 / auto px). */
105
- columns?: DataTableColumn[] | undefined;
106
- /** Row objects. Any typed interface works (5.4: before, `interface Order {…}` rows needed a cast); cells show
107
- * the value at each column's key unless the column has `render`. */
108
- rows: ReadonlyArray<Record<string, any>>;
112
+ columns?: DataTableColumn<Row>[] | undefined;
113
+ /** Row objects, of any interface; their type is the table's row type. Cells show the value at each column's key
114
+ * unless the column has `render`. */
115
+ rows: ReadonlyArray<Row>;
109
116
  /** Column key giving each row a unique React key. Default: the first column's key. */
110
117
  rowKey?: string | undefined;
111
118
  /** Accessible name for the table. */
@@ -152,7 +159,7 @@ export interface DataTableProps {
152
159
  totalRows?: number | undefined;
153
160
  /** Makes each row a link: the first column's content renders as the provider's linkComponent (or `<a>`), and a click
154
161
  * or Enter anywhere on the row follows it. Ctrl/⌘-click opens a new tab as usual. */
155
- getRowHref?: RowCallback<string> | undefined;
162
+ getRowHref?: RowCallback<string, Row> | undefined;
156
163
  /** Pager arrows become links to these URLs (search-param paging). Without onPageChange the link navigates. */
157
164
  getPageHref?: ((page: number) => string) | undefined;
158
165
  /** Router link for getRowHref / getPageHref. Default: AuraProvider's linkComponent, else `<a>`. */
@@ -160,7 +167,7 @@ export interface DataTableProps {
160
167
  /** Skeleton row count when there is no pageSize. Default 5. */
161
168
  skeletonRows?: number | undefined;
162
169
  /** Called on row click or Enter. */
163
- onRowActivate?: RowCallback<void> | undefined;
170
+ onRowActivate?: RowCallback<void, Row> | undefined;
164
171
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
165
172
  height?: number | undefined;
166
173
  /** Column menu on every header, drag-to-reorder, and the show/hide columns button. */
@@ -1290,8 +1297,15 @@ export declare const Tooltip: React$1.ForwardRefExoticComponent<TooltipProps & R
1290
1297
  export declare const Dialog: React$1.ForwardRefExoticComponent<DialogProps & React$1.RefAttributes<HTMLDivElement>>;
1291
1298
  /** Side panel over the page: record detail, filters, mobile navigation. Modal (focus trap, scroll lock, focus restore). */
1292
1299
  export declare const Drawer: React$1.ForwardRefExoticComponent<DrawerProps & React$1.RefAttributes<HTMLDivElement>>;
1293
- /** Enterprise data table: 48px rows, hairline dividers, mono header band. */
1294
- export declare const DataTable: React$1.ForwardRefExoticComponent<DataTableProps & React$1.RefAttributes<HTMLDivElement>>;
1300
+ /** Enterprise data table: 48px rows, hairline dividers, mono header band. Generic over the row type (5.5): the
1301
+ * type of `rows` types every `render`, `sortValue`, `getRowHref` and `onRowActivate`. */
1302
+ export declare const DataTable: {
1303
+ (props: DataTableProps & {
1304
+ rows: readonly never[];
1305
+ } & React$1.RefAttributes<HTMLDivElement>): React$1.ReactElement | null;
1306
+ <Row extends Record<string, any> = Record<string, any>>(props: DataTableProps<Row> & React$1.RefAttributes<HTMLDivElement>): React$1.ReactElement | null;
1307
+ displayName?: string | undefined;
1308
+ };
1295
1309
  export declare const Card: React$1.ForwardRefExoticComponent<CardProps & React$1.RefAttributes<HTMLElement>>;
1296
1310
  export declare const Tabs: React$1.ForwardRefExoticComponent<TabsProps & React$1.RefAttributes<HTMLDivElement>>;
1297
1311
  /** Side navigation: sections of links or buttons, collapsible groups, counts and badges. Arrow keys move between items. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
5
5
  "license": "MIT",
6
6
  "type": "module",