@starasia/admin 8.2.9 → 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.
- package/dist/components/FilterBar/components/MobileFilterBar.d.ts +1 -0
- package/dist/components/FilterBar/hooks/useFilterBarControls.d.ts +39 -0
- package/dist/components/FilterBar/hooks/useLastFilterState.d.ts +11 -8
- package/dist/components/FilterBar/hooks/usePerPagePref.d.ts +23 -0
- package/dist/components/FilterBar/hooks/useUrlHydration.d.ts +23 -0
- package/dist/components/FilterBar/index.d.ts +1 -0
- package/dist/components/FilterBar/types.d.ts +19 -4
- package/dist/components/FilterBar/utils/storage-adapter.d.ts +1 -0
- package/dist/components/TableLayout/TableLayout.d.ts +1 -1
- package/dist/components/TableLayout/index.d.ts +1 -1
- package/dist/components/TableLayout/types.d.ts +33 -0
- package/dist/index.cjs.js +25 -2
- package/dist/index.es.js +2935 -2632
- package/dist/index.umd.js +25 -2
- package/package.json +2 -2
|
@@ -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,
|
|
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
|
|
15
|
-
* URL has none of the snapshot keys.
|
|
14
|
+
* filters. URL always wins.
|
|
16
15
|
*
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
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,5 +1,6 @@
|
|
|
1
1
|
export { FilterBar } from './FilterBar';
|
|
2
2
|
export { useFilterBarApiParams, type UseFilterBarApiParamsOptions, type FilterBarApiParams } from './hooks/useFilterBarApiParams';
|
|
3
|
+
export { useFilterBarControls, type UseFilterBarControlsOptions, type FilterBarControls } from './hooks/useFilterBarControls';
|
|
3
4
|
export { expandDateCompact, type ExpandDateCompactOptions } from './utils/expand-date-compact';
|
|
4
5
|
export { localStorageAdapter, storageKeys } from './utils/storage-adapter';
|
|
5
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`. */
|
|
@@ -146,15 +152,24 @@ export interface FilterBarProps {
|
|
|
146
152
|
* `onColumnsChange`. `frozenKey` & field lain di luar order/hidden diabaikan.
|
|
147
153
|
*/
|
|
148
154
|
columnsState?: Partial<ColumnPrefState>;
|
|
149
|
-
/**
|
|
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
|
+
*/
|
|
150
166
|
savedViews?: {
|
|
151
167
|
enabled?: boolean;
|
|
152
|
-
scopeId
|
|
168
|
+
scopeId?: string;
|
|
153
169
|
};
|
|
154
170
|
/**
|
|
155
171
|
* Auto-restore the last applied filter state when the URL has no filter
|
|
156
|
-
* params (e.g. link-based back navigation). Requires `
|
|
157
|
-
* Default `true`.
|
|
172
|
+
* params (e.g. link-based back navigation). Requires `scopeId`. Default `true`.
|
|
158
173
|
*/
|
|
159
174
|
persistLastState?: boolean;
|
|
160
175
|
/** Persistence adapter (default: localStorage via @starasia/storage). */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { TableLayoutProps } from './types';
|
|
3
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 }: TableLayoutProps<T>) => React.JSX.Element;
|
|
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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { TableLayout } from './TableLayout';
|
|
2
2
|
export { ColumnMenu } from './ColumnMenu';
|
|
3
3
|
export { useTableSortApiParams, type UseTableSortApiParamsOptions, type TableSortApiParams } from './hooks/useTableSortApiParams';
|
|
4
|
-
export type { TableLayoutProps, TableLayoutColumn, TableLayoutAlign, TableLayoutColumnState, TableLayoutCellProps, TableLayoutSort, TableLayoutSortDirection } from './types';
|
|
4
|
+
export type { TableLayoutProps, TableLayoutColumn, TableLayoutAlign, TableLayoutColumnState, TableLayoutCellProps, TableLayoutSort, TableLayoutSortDirection, TableLayoutRowAction } from './types';
|
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { IconName } from '@starasia/icon';
|
|
3
3
|
|
|
4
|
+
export interface TableLayoutRowAction<T> {
|
|
5
|
+
key: string;
|
|
6
|
+
/** icon dari @starasia/icon (opsional) */
|
|
7
|
+
icon?: IconName;
|
|
8
|
+
/** teks tombol (mobile + kebab) + aria-label */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Tooltip saat hover tombol. Default tidak ada tooltip — harus diset eksplisit. */
|
|
11
|
+
tooltip?: string;
|
|
12
|
+
/** Tampilkan teks label di sebelah icon (default false = icon only) */
|
|
13
|
+
showLabel?: boolean;
|
|
14
|
+
onClick: (row: T, index: number) => void;
|
|
15
|
+
/** return true → action tidak tampil untuk row ini */
|
|
16
|
+
hidden?: (row: T) => boolean;
|
|
17
|
+
/** return true → tombol dinonaktifkan */
|
|
18
|
+
disabled?: (row: T) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Variant Button dari @starasia/button (default 'tertiary').
|
|
21
|
+
* Gunakan 'tertiary' untuk aksi normal, sesuaikan untuk aksi utama/destruktif.
|
|
22
|
+
*/
|
|
23
|
+
variant?: 'primary' | 'secondary' | 'tertiary' | 'outline' | 'link';
|
|
24
|
+
/**
|
|
25
|
+
* Tone/warna Button dari @starasia/button.
|
|
26
|
+
* Contoh: 'error' untuk hapus, 'success' untuk approve.
|
|
27
|
+
*/
|
|
28
|
+
tone?: 'brand' | 'error' | 'success' | 'info' | 'neutral' | 'warning';
|
|
29
|
+
}
|
|
4
30
|
export type TableLayoutAlign = 'left' | 'center' | 'right';
|
|
5
31
|
export type TableLayoutSortDirection = 'asc' | 'desc';
|
|
6
32
|
export interface TableLayoutSort {
|
|
@@ -88,6 +114,13 @@ export interface TableLayoutProps<T> {
|
|
|
88
114
|
columns: TableLayoutColumn<T>[];
|
|
89
115
|
/** baris data (wajib) */
|
|
90
116
|
data: T[];
|
|
117
|
+
/**
|
|
118
|
+
* Action buttons per baris — muncul sebagai overlay di atas row saat hover
|
|
119
|
+
* (Desktop/pointer: tersembunyi, fade-in saat hover · Touch: selalu terlihat).
|
|
120
|
+
* ≤ 5 visible action → icon buttons inline.
|
|
121
|
+
* > 5 visible action → kebab menu ⋮.
|
|
122
|
+
*/
|
|
123
|
+
rowActions?: TableLayoutRowAction<T>[];
|
|
91
124
|
/** key unik per row; default pakai index */
|
|
92
125
|
getRowKey?: (row: T, index: number) => string | number;
|
|
93
126
|
/** padding scale, diteruskan ke primitif Table (default 'md') */
|