@starasia/admin 14.9.0 → 14.11.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.
@@ -0,0 +1,34 @@
1
+ import { default as React } from 'react';
2
+ import { FilterFieldConfig } from '../types';
3
+ import { FilterBarControls } from '../hooks/useFilterBarControls';
4
+
5
+ /**
6
+ * Kontrol filter untuk dipasang di HEADER kolom TableLayout (Excel-style),
7
+ * dirakit otomatis dari `field.type` — sama seperti FilterBar merender tipe,
8
+ * dan memakai komponen date design system yang SAMA (`StarasiaDate` + `OpMenu`
9
+ * + `CompactBody` yang dipakai FilterBar). Menulis ke sumber filter yang SAMA
10
+ * (`useFilterBarControls`), jadi pill FilterBar + query ikut sinkron;
11
+ * TableLayout tetap filter-agnostic.
12
+ *
13
+ * ```tsx
14
+ * const filter = useFilterBarControls({ filterConfigs });
15
+ * const columns = baseColumns.map((col) => {
16
+ * const field = filterConfigs.find((f) => f.key === col.key);
17
+ * if (!field) return col;
18
+ * return {
19
+ * ...col,
20
+ * renderFilter: () => <ColumnHeaderFilter field={field} controls={filter} />,
21
+ * filterActive: isColumnFilterActive(field, filter),
22
+ * };
23
+ * });
24
+ * ```
25
+ */
26
+ export interface ColumnHeaderFilterProps {
27
+ /** Config filter — objek yang SAMA yang diberikan ke `<FilterBar>` via `filterConfigs`. */
28
+ field: FilterFieldConfig;
29
+ /** Controller dari `useFilterBarControls` (sumber filter yang sama dg FilterBar). */
30
+ controls: FilterBarControls;
31
+ }
32
+ /** Apakah field ini sedang punya filter aktif — untuk menyalakan funnel header. */
33
+ export declare const isColumnFilterActive: (field: FilterFieldConfig, controls: FilterBarControls) => boolean;
34
+ export declare const ColumnHeaderFilter: ({ field, controls }: ColumnHeaderFilterProps) => React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { default as React } from 'react';
2
- import { DateCompactFilterField, DateCompactValue, DateFilterField } from '../../types';
2
+ import { DateCompactFilterField, DateCompactOp, DateCompactValue, DateFilterField } from '../../types';
3
3
 
4
4
  interface DatePillProps {
5
5
  field: DateFilterField | DateCompactFilterField;
@@ -9,5 +9,18 @@ interface DatePillProps {
9
9
  /** Removes the whole pill. Omit for locked fields. */
10
10
  onRemove?: () => void;
11
11
  }
12
+ type DateMode = 'days' | 'months' | 'years';
13
+ export declare const ALL_OPS: DateCompactOp[];
12
14
  export declare const DatePill: React.FC<DatePillProps>;
15
+ export declare const OpMenu: React.FC<{
16
+ op: DateCompactOp;
17
+ ops: DateCompactOp[];
18
+ onChange: (next: DateCompactOp) => void;
19
+ }>;
20
+ export declare const CompactBody: React.FC<{
21
+ value: DateCompactValue | undefined;
22
+ op: DateCompactOp;
23
+ mode?: DateMode;
24
+ onChange: (v: unknown) => void;
25
+ }>;
13
26
  export {};
@@ -0,0 +1,19 @@
1
+ import { default as React } from 'react';
2
+ import { TextFilterField } from '../../types';
3
+
4
+ interface TextPillProps {
5
+ field: TextFilterField;
6
+ value: string;
7
+ /** Tulis nilai baru (string kosong = hapus nilai). */
8
+ onChange: (v: string) => void;
9
+ /** Kosongkan nilai tanpa menghapus pill. */
10
+ onClear: () => void;
11
+ /** Hapus pill sepenuhnya. Kosong untuk field `locked`. */
12
+ onRemove?: () => void;
13
+ }
14
+ /**
15
+ * Text pill — filter teks bebas ("contains"). Debounced (default 300ms) supaya
16
+ * tak refetch tiap ketikan; nilai kosong menghapus filter.
17
+ */
18
+ export declare const TextPill: React.FC<TextPillProps>;
19
+ export {};
@@ -22,6 +22,18 @@ export interface FilterBarControls {
22
22
  isActive: (key: string, value: string) => boolean;
23
23
  /** Nilai-nilai aktif sekarang pada filter `key`. */
24
24
  values: (key: string) => string[];
25
+ /**
26
+ * Baca nilai MENTAH filter apa pun — termasuk non-select. `date` → `Date`,
27
+ * `date-compact` → `DateCompactValue`, select-type → array `{ value, label }`.
28
+ * Untuk memfilter dari luar FilterBar pada tipe yang tak muat di `values`.
29
+ */
30
+ getRaw: (key: string) => unknown;
31
+ /**
32
+ * Tulis nilai MENTAH lewat jalur yang SAMA dengan FilterBar — mendukung
33
+ * `date` (kirim `Date`) & `date-compact` (kirim `DateCompactValue`) yang TIDAK
34
+ * didukung `set`. `null`/`undefined` → hapus filter. Pill + query ikut sinkron.
35
+ */
36
+ setRaw: (key: string, value: unknown) => void;
25
37
  /** Ada filter aktif (apa pun). */
26
38
  hasActiveFilter: boolean;
27
39
  }
@@ -1,6 +1,7 @@
1
1
  export { FilterBar } from './FilterBar';
2
2
  export { useFilterBarApiParams, type UseFilterBarApiParamsOptions, type FilterBarApiParams } from './hooks/useFilterBarApiParams';
3
3
  export { useFilterBarControls, type UseFilterBarControlsOptions, type FilterBarControls } from './hooks/useFilterBarControls';
4
+ export { ColumnHeaderFilter, isColumnFilterActive, type ColumnHeaderFilterProps } from './components/ColumnHeaderFilter';
4
5
  export { expandDateCompact, type ExpandDateCompactOptions } from './utils/expand-date-compact';
5
6
  export { localStorageAdapter, storageKeys } from './utils/storage-adapter';
6
7
  export type { FilterBarProps, FilterFieldConfig, FilterFieldType, SelectFilterField, CheckboxMultipleFilterField, DateFilterField, DateCompactFilterField, DateCompactOp, DateCompactValue, RelativeDirection, RelativePeriod, ColumnConfig, ColumnPrefState, SavedView, FilterStorageAdapter } from './types';
@@ -8,7 +8,7 @@ import { Pagination } from '../TableSection/types';
8
8
  * (`handleChangeFilter`, `getValuesFilter`, …) so the JSON-blob URL encoding
9
9
  * (`?filter={...}`) is reused as-is. `key` is the param name inside that blob.
10
10
  */
11
- export type FilterFieldType = 'date' | 'date-compact' | 'dropdown' | 'dropdown-multiple' | 'checkbox-multiple' | 'radio';
11
+ export type FilterFieldType = 'date' | 'date-compact' | 'dropdown' | 'dropdown-multiple' | 'checkbox-multiple' | 'radio' | 'text';
12
12
  interface BaseFilterField {
13
13
  /** Stable key — used as the field name inside the `?filter` blob. */
14
14
  key: string;
@@ -49,6 +49,18 @@ export interface CheckboxMultipleFilterField extends BaseFilterField {
49
49
  value: string;
50
50
  }[];
51
51
  }
52
+ /**
53
+ * Filter teks bebas ("contains") — untuk kolom high-cardinality/teks bebas
54
+ * (deskripsi, nama, no. seri) yang tak muat di select/date. Menghasilkan
55
+ * string; backend biasanya `LIKE %value%`. Nilai kosong = filter dihapus.
56
+ */
57
+ export interface TextFilterField extends BaseFilterField {
58
+ type: 'text';
59
+ /** Placeholder input. Default "Cari…". */
60
+ placeholder?: string;
61
+ /** Debounce sebelum tulis ke URL (ms). Default 300. */
62
+ debounceMs?: number;
63
+ }
52
64
  export interface DateFilterField extends BaseFilterField {
53
65
  type: 'date';
54
66
  mode?: 'days' | 'months' | 'years';
@@ -94,7 +106,7 @@ export interface DateCompactFilterField extends BaseFilterField {
94
106
  */
95
107
  mode?: 'days' | 'months' | 'years';
96
108
  }
97
- export type FilterFieldConfig = SelectFilterField | CheckboxMultipleFilterField | DateFilterField | DateCompactFilterField;
109
+ export type FilterFieldConfig = SelectFilterField | CheckboxMultipleFilterField | TextFilterField | DateFilterField | DateCompactFilterField;
98
110
  /** A single column entry fed to the Customize Column panel. */
99
111
  export interface ColumnConfig {
100
112
  key: string;
@@ -11,5 +11,16 @@ export interface ColumnMenuProps {
11
11
  onClearSort: () => void;
12
12
  onToggleFreeze: () => void;
13
13
  onHide: () => void;
14
+ /**
15
+ * Slot filter per-kolom (Excel-style). Di-render di ATAS menu (sebelum
16
+ * sort/freeze/hide) dalam section "Filter". Konten & state-nya milik consumer
17
+ * — ColumnMenu tak tahu tipe filter apa pun; teruskan kontrol yang menulis ke
18
+ * sumber filter yang sama dengan FilterBar (mis. `useFilterBarControls`),
19
+ * supaya pill FilterBar + query ikut sinkron. Klik di dalam slot TIDAK menutup
20
+ * menu (biar bisa pilih banyak nilai).
21
+ */
22
+ filterSlot?: React.ReactNode;
23
+ /** Ada filter aktif di kolom ini → funnel trigger menyala + tetap terlihat. */
24
+ filterActive?: boolean;
14
25
  }
15
- export declare const ColumnMenu: ({ active, canSort, canHide, sortDir, frozen, onSort, onClearSort, onToggleFreeze, onHide }: ColumnMenuProps) => React.JSX.Element;
26
+ export declare const ColumnMenu: ({ active, canSort, canHide, sortDir, frozen, onSort, onClearSort, onToggleFreeze, onHide, filterSlot, filterActive }: ColumnMenuProps) => React.JSX.Element;
@@ -111,6 +111,16 @@ export interface TableLayoutColumn<T> {
111
111
  sortKey?: keyof T;
112
112
  /** sembunyikan menu kolom (Ascending/Descending/Freeze/Hide) di kolom ini */
113
113
  disableMenu?: boolean;
114
+ /**
115
+ * Filter per-kolom (Excel-style) — di-render di ATAS menu kolom. Kembalikan
116
+ * kontrol filter (checklist/dropdown/dst) yang menulis ke sumber filter yang
117
+ * SAMA dengan FilterBar (mis. `useFilterBarControls` di-key by kolom), supaya
118
+ * pill FilterBar + query ikut sinkron. TableLayout tak tahu tipe filter — ia
119
+ * hanya me-render node ini. Butuh `columnMenu` aktif & `disableMenu` tak diset.
120
+ */
121
+ renderFilter?: () => ReactNode;
122
+ /** Ada filter aktif di kolom ini → funnel di header menyala + tetap terlihat. */
123
+ filterActive?: boolean;
114
124
  /** kolom terkunci — tidak bisa di-hide (item "Hide column" disembunyikan) */
115
125
  locked?: boolean;
116
126
  /**