@commercelayer/app-elements 7.12.0 → 7.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.
Files changed (31) hide show
  1. package/dist/{CodeEditorComponent-lf915EGg.js → CodeEditorComponent-aj99riRd.js} +2 -2
  2. package/dist/{InputDateComponent-DD_fCyi_.js → InputDateComponent-IsJB6qOP.js} +2 -2
  3. package/dist/{RuleEngineComponent-CVD0pObW.js → RuleEngineComponent-DZhv94I7.js} +3 -3
  4. package/dist/{en-CcBUYKzR.js → en-Ccxurm3G.js} +1 -0
  5. package/dist/{fetchCoreResourcesSuggestions-BS4pPkGo.js → fetchCoreResourcesSuggestions-DuyGOmZK.js} +1 -1
  6. package/dist/{it-y1Q1-MMT.js → it-C8-LXpKU.js} +1 -0
  7. package/dist/locales/en.d.ts +1 -0
  8. package/dist/{main-DIL89neT.js → main-DoRznkuw.js} +22022 -19254
  9. package/dist/main.d.ts +1 -0
  10. package/dist/main.js +9 -8
  11. package/dist/{parseISO-CeYGLBle.js → parseISO-Byyj1mNB.js} +1 -1
  12. package/dist/style.css +1 -1
  13. package/dist/ui/atoms/ButtonFilter.d.ts +17 -1
  14. package/dist/ui/atoms/Container.d.ts +10 -0
  15. package/dist/ui/composite/HomePageLayout.d.ts +3 -2
  16. package/dist/ui/composite/PageLayout.d.ts +52 -1
  17. package/dist/ui/resources/useResourceFilters/FieldOptionsSelect.d.ts +20 -0
  18. package/dist/ui/resources/useResourceFilters/FiltersBar.d.ts +64 -0
  19. package/dist/ui/resources/useResourceFilters/FiltersDrawer.d.ts +35 -0
  20. package/dist/ui/resources/useResourceFilters/FiltersSearchBar.d.ts +2 -2
  21. package/dist/ui/resources/useResourceFilters/activeFilters.d.ts +111 -0
  22. package/dist/ui/resources/useResourceFilters/activeFilters.test.d.ts +1 -0
  23. package/dist/ui/resources/useResourceFilters/types.d.ts +26 -0
  24. package/dist/ui/resources/useResourceFilters/useResourceFilters.d.ts +48 -0
  25. package/dist/ui/resources/useResourceList/adaptMetricsOrderToCore.d.ts +5 -0
  26. package/dist/ui/resources/useResourceList/listFetcher.d.ts +7 -1
  27. package/dist/ui/resources/useResourceList/useResourceList.d.ts +3 -1
  28. package/dist/ui/resources/useResourceTable/index.d.ts +2 -0
  29. package/dist/ui/resources/useResourceTable/types.d.ts +182 -0
  30. package/dist/ui/resources/useResourceTable/useResourceTable.d.ts +11 -0
  31. package/package.json +2 -1
@@ -1,7 +1,7 @@
1
1
  import { JSX } from 'react';
2
2
  import { SearchBarProps } from '../../composite/SearchBar';
3
3
  import { FiltersInstructions } from './types';
4
- export interface FilterSearchBarProps extends Pick<SearchBarProps, "placeholder" | "debounceMs"> {
4
+ export interface FilterSearchBarProps extends Pick<SearchBarProps, "placeholder" | "debounceMs" | "variant"> {
5
5
  /**
6
6
  * Array of instruction items to build the filters behaviors
7
7
  */
@@ -31,7 +31,7 @@ export interface FilterSearchBarProps extends Pick<SearchBarProps, "placeholder"
31
31
  */
32
32
  predicateWhitelist: string[];
33
33
  }
34
- declare function FiltersSearchBar({ instructions, placeholder, onUpdate, queryString, predicateWhitelist, debounceMs, }: FilterSearchBarProps): JSX.Element;
34
+ declare function FiltersSearchBar({ instructions, placeholder, onUpdate, queryString, predicateWhitelist, debounceMs, variant, }: FilterSearchBarProps): JSX.Element;
35
35
  declare namespace FiltersSearchBar {
36
36
  var displayName: string;
37
37
  }
@@ -0,0 +1,111 @@
1
+ import { ListableResourceType } from '@commercelayer/sdk';
2
+ import { formatDateRange } from '../../../helpers/date';
3
+ import { CurrencyRangeFieldValue, FiltersInstructionItem, FiltersInstructions, FormFullValues, UiFilterValue } from './types';
4
+ /**
5
+ * Shared helpers to read the active filters out of a url query string and turn
6
+ * them into human readable labels.
7
+ *
8
+ * Used by both `FiltersNav` (legacy `ButtonFilter` look) and `FiltersBar`
9
+ * (metrics-style pills), so label resolution only ever has one implementation.
10
+ */
11
+ export declare function getInstructionItemByFilterPredicate({ instructions, filterPredicate, }: {
12
+ instructions: FiltersInstructions;
13
+ filterPredicate: string;
14
+ }): FiltersInstructionItem | undefined;
15
+ /**
16
+ * Get label for user defined ButtonFilter component by reading the `instructionItem` object.
17
+ * If the filter has options and only one value is selected, the label will be the option label.
18
+ * Otherwise, the label will be the filter group label plus the number of selected values.
19
+ */
20
+ export declare function getButtonFilterLabel({ values, instructionItem, }: {
21
+ values: string | string[];
22
+ instructionItem: FiltersInstructionItem;
23
+ }): string;
24
+ export declare function extractCurrencyRangeFilterValues({ activeFilters, instructions, }: {
25
+ activeFilters: Array<[string, UiFilterValue]>;
26
+ instructions: FiltersInstructions;
27
+ }): Array<[string, CurrencyRangeFieldValue]>;
28
+ /**
29
+ * Checks if a filter predicate belongs to a currency range filter
30
+ * by checking the instructions
31
+ */
32
+ export declare function predicateBelongsToCurrencyRange({ filterPredicate, instructions, }: {
33
+ filterPredicate: string;
34
+ instructions: FiltersInstructions;
35
+ }): boolean;
36
+ export declare function makeCurrencyRangeFilterButtonLabel(value: CurrencyRangeFieldValue): string;
37
+ /**
38
+ * Resolves every selected value to its option label and joins them.
39
+ *
40
+ * Unlike {@link getButtonFilterLabel}, which collapses multiple values into a
41
+ * counter (`Markets · 2`), this spells them all out (`Europe, Italy`) because a
42
+ * pill already shows the filter name separately.
43
+ */
44
+ export declare function formatPillFilterValue({ values, instructionItem, }: {
45
+ values: string | string[];
46
+ instructionItem: FiltersInstructionItem;
47
+ }): string;
48
+ /**
49
+ * Compares two filter values ignoring array wrapping and ordering, so that
50
+ * `"placed"`, `["placed"]` and `["placed"]` in a different order all match.
51
+ * Range values (objects) are compared as-is.
52
+ */
53
+ export declare function isSameFilterValue(a: unknown, b: unknown): boolean;
54
+ export interface PillFilter {
55
+ /**
56
+ * Predicate of the filter, or `timePreset` for the time range.
57
+ * Used as react key and to know what to reset when removing the pill.
58
+ */
59
+ id: string;
60
+ /** Filter group label, e.g. `Payment status`. */
61
+ label: string;
62
+ /**
63
+ * Formatted value(s), e.g. `Paid, Authorized`.
64
+ * `undefined` when it has to be resolved by fetching the resource, see `fetch`.
65
+ */
66
+ value?: string;
67
+ /**
68
+ * Set for filters backed by a resource (`inputResourceGroup`, `inputSelect`),
69
+ * whose labels live on the resources themselves and have to be retrieved.
70
+ */
71
+ fetch?: {
72
+ resource: ListableResourceType;
73
+ ids: string[];
74
+ fieldForLabel: string;
75
+ fieldForValue: string;
76
+ };
77
+ /** Which reset strategy the remove button has to apply. */
78
+ kind: "group" | "timeRange";
79
+ }
80
+ /**
81
+ * Reads the url query string and returns one descriptor per active filter, ready
82
+ * to be rendered as a pill.
83
+ *
84
+ * Filters matching `defaultValues` are omitted: on a page where the current view
85
+ * (e.g. a tab) already implies a set of filters, only the user's additions are
86
+ * worth showing as removable pills.
87
+ *
88
+ * The free text filter is always omitted, since it is already visible in the
89
+ * search bar, and so are hidden filters and `viewTitle`.
90
+ */
91
+ export declare function getPillFilters({ instructions, queryString, predicateWhitelist, defaultValues, timezone, locale, }: {
92
+ instructions: FiltersInstructions;
93
+ queryString: string;
94
+ predicateWhitelist: string[];
95
+ defaultValues?: FormFullValues;
96
+ timezone?: string;
97
+ locale?: Parameters<typeof formatDateRange>[0]["locale"];
98
+ }): PillFilter[];
99
+ /**
100
+ * Form values to apply when clearing all the filters at once.
101
+ *
102
+ * Hidden filters, `viewTitle` and the free text search are preserved — they are
103
+ * not represented as pills, so wiping them would be an invisible side effect.
104
+ * Everything else goes back to `defaultValues` (empty when not provided).
105
+ */
106
+ export declare function getClearedFormValues({ instructions, queryString, predicateWhitelist, defaultValues, }: {
107
+ instructions: FiltersInstructions;
108
+ queryString: string;
109
+ predicateWhitelist: string[];
110
+ defaultValues?: FormFullValues;
111
+ }): FormFullValues;
@@ -138,6 +138,32 @@ export type FilterItemOptions = BaseFilterItem & {
138
138
  * props required for the UI component
139
139
  */
140
140
  props: Omit<InputResourceGroupProps, "onChange" | "defaultValues" | "title">;
141
+ } | {
142
+ /**
143
+ * UI component to render: a select dropdown, matching the style of the
144
+ * dashboard metrics filters. Prefer it over `inputResourceGroup` when the
145
+ * options are many, since it searches server-side instead of showing a
146
+ * checkbox list with a "see all" overlay.
147
+ */
148
+ component: "inputSelect";
149
+ /**
150
+ * props required for the UI component
151
+ */
152
+ props: Pick<InputResourceGroupProps, "resource" | "fieldForLabel" | "fieldForValue" | "searchBy" | "sortBy" | "filters" | "hideWhenSingleItem"> & {
153
+ /**
154
+ * How many options to load upfront. Capped at 25 by the Core API, which
155
+ * is why `searchBy` should be set when more options exist.
156
+ * @default 25
157
+ */
158
+ limit?: number;
159
+ placeholder?: string;
160
+ isClearable?: boolean;
161
+ /**
162
+ * Filter predicates are usually `_in`, so multiple values are expected.
163
+ * @default true
164
+ */
165
+ isMulti?: boolean;
166
+ };
141
167
  };
142
168
  };
143
169
  export interface FilterItemTextSearch extends Omit<BaseFilterItem, "sdk"> {
@@ -1,7 +1,11 @@
1
1
  import { ListableResourceType, QueryFilter } from '@commercelayer/sdk';
2
+ import { SearchBarProps } from '../../composite/SearchBar';
2
3
  import { UseResourceListConfig } from '../useResourceList';
3
4
  import { ResourceListProps } from '../useResourceList/useResourceList';
5
+ import { ResourceTableProps, UseResourceTableConfig } from '../useResourceTable/types';
4
6
  import { makeFilterAdapters } from './adapters';
7
+ import { FiltersBarProps } from './FiltersBar';
8
+ import { FiltersDrawerProps } from './FiltersDrawer';
5
9
  import { FiltersFormProps } from './FiltersForm';
6
10
  import { FiltersNavProps } from './FiltersNav';
7
11
  import { FiltersInstructions } from './types';
@@ -29,8 +33,34 @@ interface UseResourceFiltersHook {
29
33
  * Helper methods to transform filters from/to url query string, sdk and form values
30
34
  */
31
35
  adapters: ReturnType<typeof makeFilterAdapters>;
36
+ /**
37
+ * Search bar with the filters button on the right and the applied filters
38
+ * rendered as removable pills below.
39
+ *
40
+ * Clicking the filters button opens the drawer rendered by `FiltersDrawer`,
41
+ * unless an `onFilterClick` prop is provided.
42
+ *
43
+ * @example
44
+ * ```jsx
45
+ * const { FiltersBar, FiltersDrawer, FilteredTable } = useResourceFilters({ instructions })
46
+ *
47
+ * <FiltersBar queryString={queryString} onUpdate={onUpdate} />
48
+ * <FilteredTable type='orders' columns={columns} />
49
+ * <FiltersDrawer onUpdate={onUpdate} />
50
+ * ```
51
+ */
52
+ FiltersBar: (props: FiltersBarProps) => React.ReactNode;
53
+ /**
54
+ * Side drawer with the filters form, opened by the `FiltersBar` filters button.
55
+ * Render it once per page as a sibling of `FiltersBar`.
56
+ */
57
+ FiltersDrawer: (props: FiltersDrawerProps) => React.ReactNode;
32
58
  /**
33
59
  * Search bar component with filters navigation buttons
60
+ *
61
+ * @deprecated Use `FiltersBar` together with `FiltersDrawer` instead, they
62
+ * render the search bar and the filters as pills in the style used by the
63
+ * dashboard. This component will be removed in a future major release.
34
64
  */
35
65
  SearchWithNav: (props: Pick<FiltersNavProps, "onFilterClick" | "queryString"> & {
36
66
  /**
@@ -44,6 +74,11 @@ interface UseResourceFiltersHook {
44
74
  * @default 'Search...'
45
75
  */
46
76
  searchBarPlaceholder?: string;
77
+ /**
78
+ * Visual variant of the search bar. Use `outline` to match the style used
79
+ * in the dashboard (metrics) pages.
80
+ */
81
+ searchBarVariant?: SearchBarProps["variant"];
47
82
  /**
48
83
  * Milliseconds to wait before triggering the search bar callback
49
84
  * @default 500
@@ -65,6 +100,19 @@ interface UseResourceFiltersHook {
65
100
  };
66
101
  hideTitle?: boolean;
67
102
  }) => React.ReactNode;
103
+ /**
104
+ * Filtered ResourceTable component based on current active filters.
105
+ * Table sibling of `FilteredList`: renders a column-model data table wired
106
+ * to the active search/filters and pagination.
107
+ */
108
+ FilteredTable: <TResource extends ListableResourceType>(props: Omit<UseResourceTableConfig<TResource>, "query" | "metricsQuery"> & ResourceTableProps & {
109
+ query?: Omit<NonNullable<UseResourceTableConfig<TResource>["query"]>, "filters">;
110
+ metricsQuery?: Omit<NonNullable<UseResourceTableConfig<TResource>["metricsQuery"]>, "filter"> & {
111
+ /** Filters need to be configured within the `useResourceFilters` options. */
112
+ filter?: never;
113
+ };
114
+ hideTitle?: boolean;
115
+ }) => React.ReactNode;
68
116
  /**
69
117
  * SDK filters object to be used in the sdk query
70
118
  */
@@ -70,5 +70,10 @@ export interface MetricsResourceOrder {
70
70
  first_name?: string;
71
71
  last_name?: string;
72
72
  };
73
+ customer?: {
74
+ id?: string;
75
+ email?: string;
76
+ total_orders_count?: number;
77
+ };
73
78
  }
74
79
  export declare function adaptMetricsOrderToCore(metricsOrder: MetricsResourceOrder): Order;
@@ -12,11 +12,17 @@ export interface FetcherResponse<TResource> {
12
12
  cursor?: string | null;
13
13
  };
14
14
  }
15
- export declare function listFetcher<TResource extends ListableResourceType>({ currentData, resourceType, client, clientType, query, mode, pageNumber, }: {
15
+ export declare function listFetcher<TResource extends ListableResourceType>({ currentData, resourceType, client, clientType, query, mode, pageNumber, cursor, }: {
16
16
  currentData?: FetcherResponse<Resource<TResource>>;
17
17
  resourceType: TResource;
18
18
  mode?: "infinite" | "pagination";
19
19
  pageNumber?: number;
20
+ /**
21
+ * Metrics API only: the cursor that opens the requested page. Used in
22
+ * `pagination` mode, where the caller keeps track of one cursor per page
23
+ * (the metrics API can only move forward on its own).
24
+ */
25
+ cursor?: string | null;
20
26
  } & ({
21
27
  client: CommerceLayerBundle;
22
28
  clientType: "coreSdkClient";
@@ -79,7 +79,9 @@ export type UseResourceListConfig<TResource extends ListableResourceType> = {
79
79
  preProcess?: (list: Array<Resource<TResource>>) => Array<Resource<TResource>>;
80
80
  /**
81
81
  * Pagination type: 'infinite' for infinite scrolling (default), 'pagination' for classic prev/next pagination.
82
- * Note: 'pagination' mode is only supported for Core API (not Metrics API).
82
+ * Works with both the Core API and the Metrics API. Since the Metrics API is
83
+ * cursor-based, prev/next works by remembering the cursor that opens each
84
+ * visited page; arbitrary page jumps are not possible there.
83
85
  */
84
86
  paginationType?: "infinite" | "pagination";
85
87
  /**
@@ -0,0 +1,2 @@
1
+ export type { ResourceTableColumn, ResourceTableProps, ResourceTableSort, UseResourceTableConfig, UseResourceTableReturn, } from './types';
2
+ export { useResourceTable } from './useResourceTable';
@@ -0,0 +1,182 @@
1
+ import { ListableResourceType } from '@commercelayer/sdk';
2
+ import { FC, ReactNode } from 'react';
3
+ import { SectionProps } from '../../atoms/Section';
4
+ import { Resource } from '../useResourceList/listFetcher';
5
+ import { UseResourceListConfig } from '../useResourceList/useResourceList';
6
+ /**
7
+ * A single column definition for a `ResourceTable`.
8
+ *
9
+ * This is app-elements' own column type: TanStack Table is an implementation
10
+ * detail and its `ColumnDef` is intentionally not exposed here (see
11
+ * `docs/adr/0001-encapsulate-tanstack-table.md`).
12
+ */
13
+ export interface ResourceTableColumn<TResource extends ListableResourceType> {
14
+ /**
15
+ * Header content. A plain string or any node (icon, tooltip, …).
16
+ */
17
+ header: ReactNode;
18
+ /**
19
+ * Cell renderer for this column. Receives the fetched resource for the row
20
+ * and returns whatever should be displayed in the cell.
21
+ */
22
+ cell: (props: {
23
+ resource: Resource<TResource>;
24
+ }) => ReactNode;
25
+ /**
26
+ * Stable, unique column id.
27
+ * When omitted it falls back to `sortBy`, then to a positional `col-<index>`.
28
+ * Provide one explicitly when two columns would otherwise collide.
29
+ */
30
+ id?: string;
31
+ /**
32
+ * Horizontal alignment applied to both the header and the cells.
33
+ * @default 'left'
34
+ */
35
+ align?: "left" | "right" | "center";
36
+ /**
37
+ * Optional CSS class applied to the column header, typically for width
38
+ * control (e.g. `"w-1/2"`).
39
+ */
40
+ width?: string;
41
+ /**
42
+ * Hide this column below the given breakpoint; it is shown at that width and
43
+ * up. These are app-elements' own breakpoints (see `styles/global.css`, which
44
+ * resets Tailwind's defaults): `md` 768px, `lg` 992px, `xl` 1280px. There is
45
+ * deliberately no `sm`.
46
+ *
47
+ * Common cases: `"md"` hides on mobile (shown on tablet + desktop), `"lg"`
48
+ * shows on desktop only. The column's data is still fetched; only its
49
+ * rendering is suppressed via CSS, so there is no layout shift on resize.
50
+ */
51
+ hideBelow?: "md" | "lg" | "xl";
52
+ /**
53
+ * When set, the column becomes sortable and this value is the CommerceLayer
54
+ * SDK sort attribute it sorts by (e.g. `"created_at"`).
55
+ *
56
+ * Sorting is server-side: clicking the header drives the SDK `sort` query
57
+ * param and refetches. Rows are never reordered client-side.
58
+ */
59
+ sortBy?: string;
60
+ }
61
+ /**
62
+ * SDK sort expression, e.g. `"created_at"` (asc) or `"-created_at"` (desc).
63
+ * `undefined` means no explicit table sort is applied.
64
+ */
65
+ export type ResourceTableSort = string | undefined;
66
+ export type UseResourceTableConfig<TResource extends ListableResourceType> = Omit<UseResourceListConfig<TResource>, "metricsQuery" | "query"> & {
67
+ /** The columns to render, in display order. */
68
+ columns: Array<ResourceTableColumn<TResource>>;
69
+ /**
70
+ * SDK query object, excluding `pageNumber` (handled internally) and
71
+ * `sort` (owned by the table's sorting state — set the initial sort with
72
+ * `sort` instead).
73
+ */
74
+ query?: Omit<NonNullable<UseResourceListConfig<TResource>["query"]>, "sort">;
75
+ /**
76
+ * When set, data is fetched from the Metrics API instead of the Core API.
77
+ *
78
+ * Sorting still works: a column's `sortBy` is sent as the metrics
79
+ * `search.sort_by` (so use metrics attribute names, e.g. `"order.placed_at"`)
80
+ * together with the matching `search.sort` direction — omit `search.sort_by`
81
+ * here and let the table own it.
82
+ */
83
+ metricsQuery?: {
84
+ search: {
85
+ limit?: number;
86
+ fields?: string[];
87
+ };
88
+ /**
89
+ * Metrics filters. When the table is rendered through
90
+ * `useResourceFilters`' `FilteredTable`, this is injected from the active
91
+ * filters and must not be set here.
92
+ */
93
+ filter?: Record<string, unknown>;
94
+ };
95
+ /**
96
+ * Optional row-level click handler. When provided the whole row becomes
97
+ * interactive (hover affordance + click). Use it to navigate with your
98
+ * app's router.
99
+ *
100
+ * The click event is passed as second argument, so it can be forwarded to
101
+ * helpers that need it (e.g. `navigateTo(...).onClick`).
102
+ */
103
+ onRowClick?: (resource: Resource<TResource>, event: React.MouseEvent<HTMLElement>) => void;
104
+ /**
105
+ * Return an href to make each row a real link (rendered as a stretched
106
+ * anchor over the row). This enables native link behavior — cmd/ctrl/middle
107
+ * click opens the row in a new tab, and the URL shows on hover.
108
+ *
109
+ * Combine with `onRowClick` for client-side navigation: a plain click calls
110
+ * `onRowClick` (and suppresses the default navigation), while modified
111
+ * clicks fall through to the browser. Return `undefined` to leave a row
112
+ * non-navigable.
113
+ *
114
+ * Note: avoid interactive elements in the first column when using this — the
115
+ * stretched anchor sits over the row (in-cell controls would need their own
116
+ * `relative`/`z-10` to stay clickable).
117
+ */
118
+ getRowHref?: (resource: Resource<TResource>) => string | undefined;
119
+ /**
120
+ * Controlled sort value (SDK sort expression, e.g. `"-created_at"`).
121
+ * Pass together with `onSortChange` to own the sort state (e.g. persist it
122
+ * in the URL). When omitted the table manages sort internally.
123
+ */
124
+ sort?: ResourceTableSort;
125
+ /**
126
+ * Called when the user changes the sort. Provide together with `sort` for
127
+ * controlled mode; the callback receives the new SDK sort expression (or
128
+ * `undefined` when sorting is cleared).
129
+ */
130
+ onSortChange?: (sort: ResourceTableSort) => void;
131
+ /**
132
+ * Initial sort used only when the table manages sort internally
133
+ * (uncontrolled). Ignored when `sort`/`onSortChange` are provided.
134
+ */
135
+ defaultSort?: ResourceTableSort;
136
+ };
137
+ /** Props of the `ResourceTable` component returned by the hook. */
138
+ export interface ResourceTableProps {
139
+ /** Title. Can be a node or a function receiving the record count. */
140
+ title?: ((recordCount: number | undefined) => ReactNode) | ReactNode;
141
+ /** Action button rendered next to the title. */
142
+ actionButton?: SectionProps["actionButton"];
143
+ /**
144
+ * Rendered when the table has no rows.
145
+ * When omitted, a default message based on the resource name is shown.
146
+ */
147
+ emptyState?: ReactNode;
148
+ /** Force the title size. Defaults to `normal`. */
149
+ titleSize?: SectionProps["titleSize"];
150
+ /** `boxed` wraps the table in a bordered card. */
151
+ variant?: "boxed";
152
+ /**
153
+ * How the table behaves when its content is wider than the container.
154
+ * - `"fit"` (default): the table fills the container width; columns share the
155
+ * available space (and wrap/shrink). Pair with `hideBelow` on columns to
156
+ * drop low-value columns on small screens.
157
+ * - `"scroll"`: the table keeps its natural (unwrapped) width and scrolls
158
+ * horizontally inside its own container; the title/action button stay fixed.
159
+ * @default 'fit'
160
+ */
161
+ layout?: "fit" | "scroll";
162
+ }
163
+ export interface UseResourceTableReturn<TResource extends ListableResourceType> {
164
+ /** The component that renders the data table. */
165
+ ResourceTable: FC<ResourceTableProps>;
166
+ /** Prev/next pagination controls. Renders `null` unless in `pagination` mode with more than one page. */
167
+ Pagination: FC;
168
+ /** The rows currently displayed (current page, or accumulated in infinite mode). */
169
+ list?: Array<Resource<TResource>>;
170
+ /** SDK pagination metadata. */
171
+ meta?: import('../useResourceList/listFetcher').FetcherResponse<Resource<TResource>>["meta"];
172
+ isLoading: boolean;
173
+ isFirstLoading: boolean;
174
+ error?: string;
175
+ /** Removes a row from the UI only (call after a successful delete API call). */
176
+ removeItem: (resourceId: string) => void;
177
+ /** Clears fetched data and refetches from the first page. */
178
+ refresh: () => void;
179
+ hasMorePages?: boolean;
180
+ /** The active sort (SDK sort expression), whether controlled or internal. */
181
+ sort: ResourceTableSort;
182
+ }
@@ -0,0 +1,11 @@
1
+ import { ListableResourceType } from '@commercelayer/sdk';
2
+ import { UseResourceTableConfig, UseResourceTableReturn } from './types';
3
+ /**
4
+ * `useResourceTable` fetches a CommerceLayer resource type and renders it as a
5
+ * data table driven by a column model, backed by TanStack Table v9.
6
+ *
7
+ * It reuses `useResourceList`'s fetch/pagination layer verbatim and only
8
+ * replaces item rendering with a TanStack-driven table. Sorting, filtering,
9
+ * search and pagination are all resolved server-side.
10
+ */
11
+ export declare function useResourceTable<TResource extends ListableResourceType>(config: UseResourceTableConfig<TResource>): UseResourceTableReturn<TResource>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercelayer/app-elements",
3
- "version": "7.12.0",
3
+ "version": "7.13.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -38,6 +38,7 @@
38
38
  "@commercelayer/sdk": "8.0.0-beta.11",
39
39
  "@date-fns/tz": "^1.5.0",
40
40
  "@monaco-editor/react": "~4.7.0",
41
+ "@tanstack/react-table": "^9.0.0",
41
42
  "@types/lodash-es": "^4.17.12",
42
43
  "@types/react": "19.2.13",
43
44
  "@types/react-datepicker": "^7.0.0",