@starasia/admin 8.2.8 → 8.3.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 (28) hide show
  1. package/dist/components/FilterBar/components/MobileFilterBar.d.ts +52 -0
  2. package/dist/components/FilterBar/components/MobileFilterDrawer.d.ts +25 -0
  3. package/dist/components/FilterBar/components/MobileMoreMenu.d.ts +16 -0
  4. package/dist/components/FilterBar/hooks/useColumnPrefs.d.ts +3 -1
  5. package/dist/components/FilterBar/hooks/useFilterBarApiParams.d.ts +52 -0
  6. package/dist/components/FilterBar/hooks/useFilterBarControls.d.ts +39 -0
  7. package/dist/components/FilterBar/hooks/useLastFilterState.d.ts +11 -8
  8. package/dist/components/FilterBar/hooks/usePerPagePref.d.ts +23 -0
  9. package/dist/components/FilterBar/hooks/useUrlHydration.d.ts +23 -0
  10. package/dist/components/FilterBar/index.d.ts +3 -0
  11. package/dist/components/FilterBar/types.d.ts +25 -4
  12. package/dist/components/FilterBar/utils/expand-date-compact.d.ts +33 -0
  13. package/dist/components/FilterBar/utils/relative-date.d.ts +17 -0
  14. package/dist/components/FilterBar/utils/storage-adapter.d.ts +2 -0
  15. package/dist/components/TableLayout/ColumnMenu.d.ts +15 -0
  16. package/dist/components/TableLayout/TableLayout.d.ts +4 -0
  17. package/dist/components/TableLayout/hooks/useTableSortApiParams.d.ts +64 -0
  18. package/dist/components/TableLayout/index.d.ts +4 -0
  19. package/dist/components/TableLayout/types.d.ts +182 -0
  20. package/dist/components/index.d.ts +1 -1
  21. package/dist/index.cjs.js +43 -1
  22. package/dist/index.es.js +4098 -2675
  23. package/dist/index.umd.js +43 -1
  24. package/dist/style.css +1 -1
  25. package/package.json +3 -3
  26. package/dist/components/DataGrid/DataGrid.d.ts +0 -4
  27. package/dist/components/DataGrid/index.d.ts +0 -2
  28. package/dist/components/DataGrid/types.d.ts +0 -66
@@ -0,0 +1,52 @@
1
+ import { default as React } from 'react';
2
+ import { FilterFieldConfig, SavedView } from '../types';
3
+ import { OrderedColumn } from '../hooks/useColumnPrefs';
4
+ import { Pagination as PaginationMeta } from '../../TableSection/types';
5
+
6
+ interface MobileFilterBarProps {
7
+ withPadding: boolean;
8
+ configs: FilterFieldConfig[];
9
+ activeKeys: string[];
10
+ configByKey: Record<string, FilterFieldConfig>;
11
+ hasActiveFilter: boolean;
12
+ toggleFilter: (key: string) => void;
13
+ removeFilter: (key: string) => void;
14
+ getValue: (field: FilterFieldConfig) => unknown;
15
+ setValue: (field: FilterFieldConfig, value: unknown) => void;
16
+ clearValue: (key: string) => void;
17
+ onReset: () => void;
18
+ searchable: boolean;
19
+ searchKey: string;
20
+ filterKey: string;
21
+ pageKey: string;
22
+ searchPlaceholder: string;
23
+ searchShortcut: string;
24
+ pagination?: PaginationMeta;
25
+ perPageKey: string;
26
+ pageSizeOptions: number[];
27
+ defaultPerPage: number;
28
+ showPagination: boolean;
29
+ showResultCount: boolean;
30
+ showPageSize: boolean;
31
+ hasColumns: boolean;
32
+ orderedColumns: OrderedColumn[];
33
+ allVisible: boolean;
34
+ onToggleVisibility: (key: string) => void;
35
+ onReorder: (from: number, to: number) => void;
36
+ onSetAllHidden: (hidden: boolean) => void;
37
+ showSavedViews: boolean;
38
+ savedViews: SavedView[];
39
+ onApplyView: (view: SavedView) => void;
40
+ onDeleteView: (id: string) => void;
41
+ onSaveView: (name: string) => void;
42
+ }
43
+ /**
44
+ * Mobile (<768px) variant of FilterBar. Replaces the horizontal toolbar with a
45
+ * two-row layout: a tight toolbar (search icon-toggle + "Filter (N)" trigger +
46
+ * saved views + columns + more) and a compact pagination row below.
47
+ *
48
+ * The filter pills + add-filter catalog move into a bottom `Drawer` opened by
49
+ * the Filter button. Page-size selection moves into the "More" overflow menu.
50
+ */
51
+ export declare const MobileFilterBar: React.FC<MobileFilterBarProps>;
52
+ export {};
@@ -0,0 +1,25 @@
1
+ import { default as React } from 'react';
2
+ import { FilterFieldConfig } from '../types';
3
+
4
+ interface MobileFilterDrawerProps {
5
+ isOpen: boolean;
6
+ onClose: () => void;
7
+ configs: FilterFieldConfig[];
8
+ activeKeys: string[];
9
+ configByKey: Record<string, FilterFieldConfig>;
10
+ hasActiveFilter: boolean;
11
+ onToggle: (key: string) => void;
12
+ onReset: () => void;
13
+ getValue: (field: FilterFieldConfig) => unknown;
14
+ setValue: (field: FilterFieldConfig, value: unknown) => void;
15
+ clearValue: (key: string) => void;
16
+ removeFilter: (key: string) => void;
17
+ }
18
+ /**
19
+ * Bottom drawer that consolidates the filter UX for mobile: active pills
20
+ * (stacked vertically) at the top, followed by the full filter catalog as a
21
+ * toggleable list. Reuses `FilterPills` so each pill keeps its native editor
22
+ * popover — the popover floats over the drawer when tapped.
23
+ */
24
+ export declare const MobileFilterDrawer: React.FC<MobileFilterDrawerProps>;
25
+ export {};
@@ -0,0 +1,16 @@
1
+ import { default as React } from 'react';
2
+
3
+ interface MobileMoreMenuProps {
4
+ perPageKey: string;
5
+ pageKey: string;
6
+ pageSizeOptions: number[];
7
+ defaultPerPage?: number;
8
+ showPageSize: boolean;
9
+ }
10
+ /**
11
+ * Mobile-only "More" menu — overflow surface for the secondary toolbar
12
+ * affordances that don't fit on a narrow screen. For now this is just the
13
+ * page-size selector; saved-views / columns stay as their own icon buttons.
14
+ */
15
+ export declare const MobileMoreMenu: React.FC<MobileMoreMenuProps>;
16
+ export {};
@@ -5,6 +5,8 @@ interface UseColumnPrefsOptions {
5
5
  scopeId?: string;
6
6
  storage: FilterStorageAdapter;
7
7
  onColumnsChange?: (state: ColumnPrefState) => void;
8
+ /** Controlled external state (mis. hide/freeze dari menu kolom tabel). */
9
+ value?: Partial<ColumnPrefState>;
8
10
  }
9
11
  export interface OrderedColumn extends ColumnConfig {
10
12
  visible: boolean;
@@ -15,7 +17,7 @@ export interface OrderedColumn extends ColumnConfig {
15
17
  * consumer via `onColumnsChange` so it can apply the result to its table.
16
18
  * Without a `scopeId` the state is session-only (still fully functional).
17
19
  */
18
- export declare function useColumnPrefs({ columns, scopeId, storage, onColumnsChange }: UseColumnPrefsOptions): {
20
+ export declare function useColumnPrefs({ columns, scopeId, storage, onColumnsChange, value }: UseColumnPrefsOptions): {
19
21
  state: ColumnPrefState;
20
22
  orderedColumns: OrderedColumn[];
21
23
  allVisible: boolean;
@@ -0,0 +1,52 @@
1
+ import { FilterFieldConfig } from '../types';
2
+
3
+ export interface UseFilterBarApiParamsOptions {
4
+ /** Same catalog passed to `<FilterBar>`. */
5
+ filterConfigs: FilterFieldConfig[];
6
+ /** Mirror FilterBar URL keys. */
7
+ filterKey?: string;
8
+ activeFilterKey?: string;
9
+ pageKey?: string;
10
+ perPageKey?: string;
11
+ searchKey?: string;
12
+ /** Fallback when `?page` is absent. Default 1. */
13
+ defaultPage?: number;
14
+ /** Fallback when `?perPage` is absent. Default 10. */
15
+ defaultPerPage?: number;
16
+ /**
17
+ * Rename output keys. Covers built-ins (`page`, `perPage`, `search`) and
18
+ * individual filter field keys. Example:
19
+ * `{ perPage: 'limit', status: 'statusId' }`
20
+ */
21
+ paramKeys?: Record<string, string>;
22
+ /**
23
+ * Per-field custom serializer. Receives the **decoded** value
24
+ * (`string | string[] | Date | DateCompactValue | undefined`) and returns
25
+ * whatever shape the API expects. Return `undefined` to omit the key.
26
+ * Keyed by the filter field key (before any `paramKeys` remap).
27
+ */
28
+ serialize?: Record<string, (value: unknown) => unknown>;
29
+ }
30
+ export interface FilterBarApiParams {
31
+ /** Memoized, flat object ready to spread into a service call. */
32
+ params: Record<string, unknown>;
33
+ /** True when any filter (incl. search) is set. */
34
+ hasActiveFilter: boolean;
35
+ /** Decoded but pre-flattening values, keyed by field key — useful if a
36
+ * consumer wants the `{label, value}` pairs back for display. */
37
+ raw: Record<string, unknown>;
38
+ }
39
+ /**
40
+ * Read FilterBar's URL state and produce a flat, API-ready params object that
41
+ * consumer service functions can accept directly. Drop-in for the
42
+ * `useQuery({ queryKey: [scope, params], queryFn: () => service.list(params) })`
43
+ * pattern documented in the `starasia-tanstack-query` skill.
44
+ *
45
+ * - `page` / `perPage` always present (coerced, with defaults)
46
+ * - `search` only when non-empty
47
+ * - Filter values flattened per type (single → value, multi → value[],
48
+ * date → ISO string, date-compact stays raw — pair with `expandDateCompact`)
49
+ * - Cleared filters are omitted (no `null`, no empty array)
50
+ * - `paramKeys` renames output keys; `serialize` overrides default flattening
51
+ */
52
+ export declare const useFilterBarApiParams: (options: UseFilterBarApiParamsOptions) => FilterBarApiParams;
@@ -0,0 +1,39 @@
1
+ import { FilterFieldConfig } from '../types';
2
+
3
+ export interface UseFilterBarControlsOptions {
4
+ /** Katalog filter yang SAMA dengan yang dipakai `<FilterBar>`. */
5
+ filterConfigs: FilterFieldConfig[];
6
+ /** Mirror key URL FilterBar (default sama dgn FilterBar). */
7
+ filterKey?: string;
8
+ activeFilterKey?: string;
9
+ pageKey?: string;
10
+ searchKey?: string;
11
+ }
12
+ export interface FilterBarControls {
13
+ /** Set nilai filter (replace). Array kosong / `[]` → hapus filter. */
14
+ set: (key: string, value: string | string[]) => void;
15
+ /** Tambah/lepas satu nilai (cocok untuk klik kartu shortcut). */
16
+ toggle: (key: string, value: string) => void;
17
+ /** Hapus filter ini sepenuhnya (nilai + pill). */
18
+ clear: (key: string) => void;
19
+ /** Reset semua filter + search. */
20
+ clearAll: () => void;
21
+ /** Apakah `value` sedang aktif pada filter `key` (untuk styling kartu aktif). */
22
+ isActive: (key: string, value: string) => boolean;
23
+ /** Nilai-nilai aktif sekarang pada filter `key`. */
24
+ values: (key: string) => string[];
25
+ /** Ada filter aktif (apa pun). */
26
+ hasActiveFilter: boolean;
27
+ }
28
+ /**
29
+ * Kontrol filter dari LUAR `<FilterBar>` — untuk shortcut/quick-filter
30
+ * (mis. summary card status yang saat diklik memfilter tabel).
31
+ *
32
+ * Sumber kebenaran sama dengan FilterBar: URL. Jadi begitu helper ini menulis,
33
+ * pill FilterBar, tabel, dan `useFilterBarApiParams` ikut otomatis — tanpa
34
+ * lifting state. Companion arah-tulis dari `useFilterBarApiParams` (arah-baca).
35
+ *
36
+ * Khusus untuk filter select-type (`dropdown` / `dropdown-multiple` /
37
+ * `checkbox-multiple` / `radio`). Field lain (date) diabaikan.
38
+ */
39
+ export declare const useFilterBarControls: ({ filterConfigs, filterKey, activeFilterKey, pageKey, searchKey }: UseFilterBarControlsOptions) => FilterBarControls;
@@ -3,7 +3,7 @@ import { FilterStorageAdapter } from '../types';
3
3
  interface UseLastFilterStateOptions {
4
4
  scopeId?: string;
5
5
  storage: FilterStorageAdapter;
6
- /** URL params to snapshot (e.g. [activeFilterKey, filterKey, perPageKey]). */
6
+ /** URL params to snapshot (e.g. [activeFilterKey, filterKey, pageKey]). */
7
7
  snapshotKeys: string[];
8
8
  /** Opt-out toggle (default true when scopeId is provided). */
9
9
  enabled?: boolean;
@@ -11,17 +11,20 @@ interface UseLastFilterStateOptions {
11
11
  /**
12
12
  * Persists the latest filter URL params per scope, so link-based back
13
13
  * navigation (which drops the query string) still restores the previous
14
- * filters on remount. URL always wins — restoration only kicks in when the
15
- * URL has none of the snapshot keys.
14
+ * filters. URL always wins.
16
15
  *
17
- * - **Autosave**: writes to `localStorage[filterbar:last:{scopeId}]` on every
18
- * `searchParams` change.
19
- * - **Autorestore**: on mount, hydrates the URL from storage if empty.
20
- * - **`clear()`**: removes the snapshot; call this from Reset so the user's
21
- * explicit reset isn't undone on the next navigation back.
16
+ * NOTE: restore-ke-URL TIDAK dilakukan di sini — dikoordinasikan oleh
17
+ * `useUrlHydration` (satu `setSearchParams` gabungan) supaya tidak bentrok
18
+ * dengan restore perPage. Hook ini hanya autosave + expose `read()` + `clear()`.
19
+ *
20
+ * - **Autosave**: writes to `filterbar:last:{scopeId}` on every URL change.
21
+ * Snapshot KOSONG tidak ditulis (agar tidak menghapus snapshot saat URL
22
+ * kosong transient / pindah route).
23
+ * - **`clear()`**: removes the snapshot (dipanggil dari Reset).
22
24
  */
23
25
  export declare function useLastFilterState({ scopeId, storage, snapshotKeys, enabled }: UseLastFilterStateOptions): {
24
26
  enabled: boolean;
27
+ read: () => Record<string, string> | null;
25
28
  clear: () => void;
26
29
  };
27
30
  export {};
@@ -0,0 +1,23 @@
1
+ import { FilterStorageAdapter } from '../types';
2
+
3
+ interface UsePerPagePrefOptions {
4
+ scopeId?: string;
5
+ storage: FilterStorageAdapter;
6
+ perPageKey: string;
7
+ /** When provided, the restored value is validated against this list. */
8
+ pageSizeOptions?: number[];
9
+ /** Opt-out toggle (default true when scopeId is provided). */
10
+ enabled?: boolean;
11
+ }
12
+ /**
13
+ * Persists the rows-per-page choice independently of the filter snapshot.
14
+ *
15
+ * UI preference — NOT wiped by Reset. Restore-ke-URL dikoordinasikan oleh
16
+ * `useUrlHydration`; hook ini hanya autosave + expose `read()` + `clear()`.
17
+ */
18
+ export declare function usePerPagePref({ scopeId, storage, perPageKey, pageSizeOptions, enabled }: UsePerPagePrefOptions): {
19
+ enabled: boolean;
20
+ read: () => string | null;
21
+ clear: () => void;
22
+ };
23
+ export {};
@@ -0,0 +1,23 @@
1
+ interface UseUrlHydrationOptions {
2
+ enabled: boolean;
3
+ /** Keys yang dianggap "filter snapshot" (mis. [filters, filter, page]). */
4
+ snapshotKeys: string[];
5
+ perPageKey: string;
6
+ /** Snapshot filter tersimpan (atau null). */
7
+ readSnapshot: () => Record<string, string> | null;
8
+ /** Page size tersimpan (string) atau null. */
9
+ readPerPage: () => string | null;
10
+ }
11
+ /**
12
+ * Hidrasi URL dari preferensi tersimpan. Restore filter-snapshot & perPage
13
+ * digabung lewat micro-batcher → tidak saling menimpa, dan tahan banting untuk
14
+ * >1 FilterBar dalam satu halaman.
15
+ *
16
+ * Jalan saat "tiba" di halaman: mount ATAU `location.pathname` berubah (navigasi
17
+ * balik), jadi halaman yang di-keep-alive router tetap ter-restore tanpa hard
18
+ * refresh. Di-gate ke perubahan pathname agar TIDAK loop saat user mengubah
19
+ * filter di halaman yang sama. URL selalu menang (key yang sudah ada di URL
20
+ * tidak ditimpa).
21
+ */
22
+ export declare function useUrlHydration({ enabled, snapshotKeys, perPageKey, readSnapshot, readPerPage }: UseUrlHydrationOptions): void;
23
+ export {};
@@ -1,3 +1,6 @@
1
1
  export { FilterBar } from './FilterBar';
2
+ export { useFilterBarApiParams, type UseFilterBarApiParamsOptions, type FilterBarApiParams } from './hooks/useFilterBarApiParams';
3
+ export { useFilterBarControls, type UseFilterBarControlsOptions, type FilterBarControls } from './hooks/useFilterBarControls';
4
+ export { expandDateCompact, type ExpandDateCompactOptions } from './utils/expand-date-compact';
2
5
  export { localStorageAdapter, storageKeys } from './utils/storage-adapter';
3
6
  export type { FilterBarProps, FilterFieldConfig, FilterFieldType, SelectFilterField, CheckboxMultipleFilterField, DateFilterField, DateCompactFilterField, DateCompactOp, DateCompactValue, RelativeDirection, RelativePeriod, ColumnConfig, ColumnPrefState, SavedView, FilterStorageAdapter } from './types';
@@ -132,6 +132,12 @@ export interface FilterBarProps {
132
132
  perPageKey?: string;
133
133
  /** Page-size choices. Default `[10, 25, 50, 100]`. */
134
134
  pageSizeOptions?: number[];
135
+ /**
136
+ * Initial page size used when the URL (and the persisted preference under
137
+ * `savedViews.scopeId`) is empty. Defaults to `pageSizeOptions[0]`, so
138
+ * `pageSizeOptions={[25, 50, 100]}` naturally defaults to 25.
139
+ */
140
+ defaultPerPage?: number;
135
141
  showPagination?: boolean;
136
142
  showResultCount?: boolean;
137
143
  /** Show the rows-per-page selector. Default `true`. */
@@ -140,15 +146,30 @@ export interface FilterBarProps {
140
146
  columns?: ColumnConfig[];
141
147
  /** Emitted when visibility/order changes — consumer applies to its table. */
142
148
  onColumnsChange?: (state: ColumnPrefState) => void;
143
- /** Enable named saved views. `scopeId` namespaces persisted data per table. */
149
+ /**
150
+ * Controlled column state. Saat diisi, panel Customize Column ikut state ini
151
+ * (mis. hide/freeze dari menu kolom TableLayout) — sinkron dua arah dgn
152
+ * `onColumnsChange`. `frozenKey` & field lain di luar order/hidden diabaikan.
153
+ */
154
+ columnsState?: Partial<ColumnPrefState>;
155
+ /**
156
+ * Namespace persistensi per tabel — dipakai untuk column prefs, last-filter
157
+ * snapshot, perPage, & saved views. WAJIB diisi agar fitur persist aktif.
158
+ * Boleh juga lewat `savedViews.scopeId` (kompatibilitas lama); kalau dua-duanya
159
+ * ada, prop top-level ini menang.
160
+ */
161
+ scopeId?: string;
162
+ /**
163
+ * Saved views. `enabled` mengontrol tampil/sembunyinya tombol Saved Views.
164
+ * `scopeId` di sini opsional & deprecated — pakai prop `scopeId` top-level.
165
+ */
144
166
  savedViews?: {
145
167
  enabled?: boolean;
146
- scopeId: string;
168
+ scopeId?: string;
147
169
  };
148
170
  /**
149
171
  * Auto-restore the last applied filter state when the URL has no filter
150
- * params (e.g. link-based back navigation). Requires `savedViews.scopeId`.
151
- * Default `true`.
172
+ * params (e.g. link-based back navigation). Requires `scopeId`. Default `true`.
152
173
  */
153
174
  persistLastState?: boolean;
154
175
  /** Persistence adapter (default: localStorage via @starasia/storage). */
@@ -0,0 +1,33 @@
1
+ import { DateCompactValue } from '../types';
2
+
3
+ export interface ExpandDateCompactOptions {
4
+ /** Param key for the start / single date. */
5
+ fromKey: string;
6
+ /** Param key for the end of a range (only used by `is-between` and
7
+ * `is-relative-to-today`). */
8
+ toKey: string;
9
+ /**
10
+ * Optional separate key carrying the operator. When provided:
11
+ * - is-empty / is-not-empty → `{ [opKey]: 'empty' | 'not-empty' }`
12
+ * - single-date ops (is / is-before / …) → also emits `{ [opKey]: op }`
13
+ * so the API can branch on direction.
14
+ * When omitted, those ops produce `{}` (single-date ops still emit
15
+ * `{ [fromKey]: ISO }`).
16
+ */
17
+ opKey?: string;
18
+ }
19
+ /**
20
+ * Expand a `DateCompactValue` (operator + payload, as stored by the
21
+ * `date-compact` filter type) into a flat `Record<string, string>` ready to
22
+ * spread into an API params object.
23
+ *
24
+ * - `is` / `is-before` / `is-after` / `is-on-or-before` / `is-on-or-after`
25
+ * → `{ [fromKey]: ISO }` (+ `{ [opKey]: op }` when `opKey` is set)
26
+ * - `is-between` → `{ [fromKey]: ISO, [toKey]: ISO }`
27
+ * - `is-relative-to-today` → resolved to absolute ISO via `computeRelativeRange`
28
+ * → `{ [fromKey]: ISO, [toKey]: ISO }`
29
+ * - `is-empty` / `is-not-empty` → `{ [opKey]: 'empty' | 'not-empty' }` when
30
+ * `opKey` is set, otherwise `{}` (caller's choice how to encode)
31
+ * - `undefined` value → `{}`
32
+ */
33
+ export declare const expandDateCompact: (value: DateCompactValue | undefined, options: ExpandDateCompactOptions) => Record<string, string>;
@@ -0,0 +1,17 @@
1
+ import { RelativeDirection, RelativePeriod } from '../types';
2
+
3
+ export declare const startOfDay: (d: Date) => Date;
4
+ export declare const shiftPeriod: (d: Date, n: number, p: RelativePeriod) => Date;
5
+ /**
6
+ * Resolve a relative spec (Past 2 weeks / Next 1 month / This year …) to a
7
+ * concrete date range anchored at today. Shared between DatePill (preview
8
+ * calendar) and expandDateCompact (API param expansion).
9
+ */
10
+ export declare const computeRelativeRange: (rel: {
11
+ direction: RelativeDirection;
12
+ count?: number;
13
+ period: RelativePeriod;
14
+ }) => {
15
+ from: Date;
16
+ to: Date;
17
+ };
@@ -13,4 +13,6 @@ export declare const storageKeys: {
13
13
  columns: (scopeId: string) => string;
14
14
  savedViews: (scopeId: string) => string;
15
15
  lastState: (scopeId: string) => string;
16
+ perPage: (scopeId: string) => string;
17
+ tableSort: (scopeId: string) => string;
16
18
  };
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+
3
+ export interface ColumnMenuProps {
4
+ /** trigger tetap terlihat (mis. sedang di-sort / di-freeze) walau tidak hover */
5
+ active: boolean;
6
+ canSort: boolean;
7
+ canHide: boolean;
8
+ sortDir: 'asc' | 'desc' | null;
9
+ frozen: boolean;
10
+ onSort: (dir: 'asc' | 'desc') => void;
11
+ onClearSort: () => void;
12
+ onToggleFreeze: () => void;
13
+ onHide: () => void;
14
+ }
15
+ export declare const ColumnMenu: ({ active, canSort, canHide, sortDir, frozen, onSort, onClearSort, onToggleFreeze, onHide }: ColumnMenuProps) => React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { default as React } from 'react';
2
+ import { TableLayoutProps } from './types';
3
+
4
+ export declare const TableLayout: <T>({ columns, data, getRowKey, size, resizable, widthStorageKey, columnState, onColumnStateChange, columnMenu, sort, defaultSort, onSortChange, height, mobileLayout, mobileBreakpoint, groupSeparator, summary, emptyState, rowActions, }: TableLayoutProps<T>) => React.JSX.Element;
@@ -0,0 +1,64 @@
1
+ import { FilterStorageAdapter } from '../../FilterBar/types';
2
+ import { TableLayoutSort } from '../types';
3
+
4
+ export interface UseTableSortApiParamsOptions {
5
+ /** URL param holding the sort key. Default `'sortBy'`. */
6
+ sortKeyParam?: string;
7
+ /** URL param holding the sort direction. Default `'sortOrder'`. */
8
+ sortOrderParam?: string;
9
+ /** URL param for pagination — auto-reset to 1 on sort change. Default `'page'`. */
10
+ pageKey?: string;
11
+ /** Sort used when URL has no sort (and no persisted snapshot). Default `null`. */
12
+ defaultSort?: TableLayoutSort | null;
13
+ /**
14
+ * Rename output param keys (in `params`) without changing URL keys.
15
+ * Example: `{ sortBy: 'orderBy', sortOrder: 'orderDir' }` for a backend
16
+ * with different names. Defaults to the same names as the URL.
17
+ */
18
+ paramKeys?: {
19
+ sortBy?: string;
20
+ sortOrder?: string;
21
+ };
22
+ /**
23
+ * Namespace for persistence. When provided, sort is saved to storage and
24
+ * auto-restored when the user navigates away and comes back to a URL with
25
+ * no sort params (URL always wins on direct visits). Conventionally matches
26
+ * `FilterBar.savedViews.scopeId` so list state stays consistent.
27
+ */
28
+ scopeId?: string;
29
+ /**
30
+ * Pluggable persistence (default `localStorageAdapter`). Only used when
31
+ * `scopeId` is set. Same shape as `FilterBar`'s `storage` prop.
32
+ */
33
+ storage?: FilterStorageAdapter;
34
+ }
35
+ export interface TableSortApiParams {
36
+ /** Current sort, decoded from URL (or `defaultSort` when URL is empty). */
37
+ sort: TableLayoutSort | null;
38
+ /** Update sort + write to URL. Pass `null` to clear. Resets `?page` to 1
39
+ * so the user lands on the first page of the newly-sorted result. */
40
+ setSort: (next: TableLayoutSort | null) => void;
41
+ /**
42
+ * Flat API params, ready to spread into a service call.
43
+ * `{ sortBy: 'createdAt', sortOrder: 'desc' }` when sort active, `{}`
44
+ * when not. Memoized — stable reference for tanstack `queryKey`.
45
+ */
46
+ params: Record<string, string>;
47
+ }
48
+ /**
49
+ * Persist `<TableLayout>` sort state in the URL (`?sortBy=…&sortOrder=…`) and
50
+ * surface a flat `{ sortBy, sortOrder }` object ready to spread into a service
51
+ * call — companion to `useFilterBarApiParams`.
52
+ *
53
+ * Passing the returned `onSortChange` to `<TableLayout>` flips it into
54
+ * **server mode** (it won't sort the data itself, it just emits — perfect
55
+ * when the API does the sorting). The hook resets `?page` to 1 on every
56
+ * sort change so the user always lands on the first page of the new order.
57
+ *
58
+ * **Persistence** (opt-in via `scopeId`): mirrors `FilterBar.useLastFilterState`.
59
+ * Sort is autosaved to storage on every change, and auto-restored on mount
60
+ * when the URL has no sort params. URL always wins on direct visits.
61
+ * `setSort(null)` clears both URL and storage so explicit resets aren't
62
+ * undone by the next back-navigation.
63
+ */
64
+ export declare const useTableSortApiParams: (options?: UseTableSortApiParamsOptions) => TableSortApiParams;
@@ -0,0 +1,4 @@
1
+ export { TableLayout } from './TableLayout';
2
+ export { ColumnMenu } from './ColumnMenu';
3
+ export { useTableSortApiParams, type UseTableSortApiParamsOptions, type TableSortApiParams } from './hooks/useTableSortApiParams';
4
+ export type { TableLayoutProps, TableLayoutColumn, TableLayoutAlign, TableLayoutColumnState, TableLayoutCellProps, TableLayoutSort, TableLayoutSortDirection, TableLayoutRowAction } from './types';