import * as _angular_core from '@angular/core';
import { TemplateRef, Signal, EventEmitter, ChangeDetectorRef, InjectionToken, OnInit, AfterViewInit, OnDestroy } from '@angular/core';
import { SdBadge } from '@sdcorejs/angular/components/badge';
import { SdSearch } from '@sdcorejs/angular/forms';
import { Operator, NestedKeyOf, Order, PagingReq, Color } from '@sdcorejs/utils/models';
import { SdUnwrapSignal, MaterialIconFontSet } from '@sdcorejs/angular/utilities/models';
import { MatPaginatorIntl, MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { SdExcelColumn, SdLoadingService, SdExcelService, SdNotifyService, SdConfirmService } from '@sdcorejs/angular/services';
import { Observable } from 'rxjs';
import { SdButton } from '@sdcorejs/angular/components/button';
import { CdkDrag, CdkDropList, CdkDragDrop } from '@angular/cdk/drag-drop';
import { SdQuickAction } from '@sdcorejs/angular/components/quick-action';
import { SdScrollDirective } from '@sdcorejs/angular/directives';
import { FormGroup } from '@angular/forms';
import { SdSideDrawer } from '@sdcorejs/angular/components/side-drawer';
import { SdModal } from '@sdcorejs/angular/components/modal';
import { MatSelectionList } from '@angular/material/list';

type SdTableColumn<T = any> = SdTableColumnText<T> | SdTableColumnNumber<T> | SdTableColumnBool<T> | SdTableColumnDate<T> | SdTableColumnValues<T> | SdTableColumnLazyValues<T> | SdTableColumnChildren<T>;
type SdTableColumnTransformFunc<T = any> = (value: any, rowData: T, args?: {
    isExport?: boolean;
}) => string | Promise<string>;
interface Badge {
    type?: SdUnwrapSignal<SdBadge['type']>;
    color?: SdUnwrapSignal<SdBadge['color']>;
    icon?: SdUnwrapSignal<SdBadge['icon']>;
    title?: SdUnwrapSignal<SdBadge['title']>;
}
type UseBadgeFunc<T = any> = (value: any, rowData: T) => Badge;
type UseBadgeValuesFunc<T = any, K = any> = (value: any, rowData: T, items: K[]) => Badge;
interface ColumnTitleOption {
    title: string;
    templateRef?: TemplateRef<any>;
}
interface ColumnCellOption {
    templateRef?: TemplateRef<any>;
    copiable?: boolean;
    truncate?: {
        enable?: boolean;
        type?: 'more' | 'tooltip';
    };
}
interface SdTableColumnBase<T = any> {
    title: string | ColumnTitleOption;
    cell?: ColumnCellOption;
    width?: string;
    minWidth?: string;
    maxWidth?: string;
    hidden?: boolean;
    invisible?: boolean;
    fixed?: boolean;
    align?: 'right';
    htmlTemplate?: (value: any, rowData: T) => string;
    transform?: SdTableColumnTransformFunc<T>;
    tooltip?: (value: any, rowData: T) => string;
    click?: (value: any, rowData: T) => void;
    sortable?: boolean;
    filter?: {
        disabled?: boolean;
        default?: any;
        operator?: {
            default?: Operator;
            enable?: boolean;
            list?: Operator[];
        };
        filterDef?: TemplateRef<any>;
    };
    export?: {
        disabled?: boolean;
        description?: string;
    };
}
interface SdTableColumnText<T = any> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'string';
    useBadge?: UseBadgeFunc<T>;
}
interface SdTableColumnNumber<T = any> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'number';
    useBadge?: UseBadgeFunc<T>;
    filter?: SdTableColumnBase['filter'] & {
        type?: 'split-number';
    };
}
interface SdTableColumnBool<T = any> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'boolean';
    useBadge?: UseBadgeFunc<T>;
    option?: {
        displayOnTrue?: string;
        displayOnFalse?: string;
    };
}
interface SdTableColumnDate<T = any> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'date' | 'datetime' | 'time';
    useBadge?: UseBadgeFunc<T>;
    filter?: SdTableColumnBase['filter'] & {
        type?: 'daterange' | 'date' | 'split-date';
    };
}
interface SdTableColumnValues<T = any, K = Record<string, any>> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'values';
    useBadge?: UseBadgeValuesFunc<T, K>;
    option: {
        items: K[] | Signal<K[]> | (() => Promise<K[]>);
        valueField: NestedKeyOf<K>;
        displayField: NestedKeyOf<K>;
        selection?: 'MULTIPLE';
    };
}
interface SdTableColumnLazyValues<T = any, K = Record<string, any>> extends SdTableColumnBase<T> {
    field: NestedKeyOf<T>;
    type: 'lazy-values';
    useBadge?: UseBadgeFunc<T>;
    option: {
        items: SdSearch<K>;
        valueField: NestedKeyOf<K>;
        displayField: NestedKeyOf<K>;
        views?: (values: string[]) => Promise<K[]>;
        selection?: 'MULTIPLE';
    };
}
type SdTableColumnNormal<T = any> = Exclude<SdTableColumn<T>, SdTableColumnChildren<T>>;
interface SdTableColumnChildren<T = any> extends SdTableColumnBase<T> {
    field: string;
    type: 'children';
    children: SdTableColumnNormal<T>[];
}

interface Context$4<T = any> {
    item: T;
    column: SdTableColumn<T>;
    autoId: string;
}
declare class SdTableCellDefDirective<T = any> {
    static ngTemplateContextGuard<T>(_dir: SdTableCellDefDirective<T>, _ctx: unknown): _ctx is Context$4<T>;
    sdTableCellDef: _angular_core.InputSignal<string>;
    templateRef: TemplateRef<Context$4<T>>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableCellDefDirective<any>, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableCellDefDirective<any>, "[sdTableCellDef]", never, { "sdTableCellDef": { "alias": "sdTableCellDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
}

interface SdTableMetaSelector {
    selectable?: boolean;
    isSelected?: boolean;
    actions?: string[];
}
interface SdTableMetaExpand {
    isExpanded?: boolean;
    isExpanding?: boolean;
    data?: any;
}
interface SdTableMetaTree<T = any> {
    level: number;
    hasChildren: boolean;
    isExpanded: boolean;
    isExpanding?: boolean;
    parentId?: string;
    /** Cached formatted child SdTableItem[] — populated on first expand/format */
    childItems?: SdTableItem<T>[];
    /**
     * Hierarchical index path từ root tới row hiện tại — sibling-index (1-based) per level.
     * Vd root thứ nhất = [1], child thứ 2 của root đó = [1, 2], grandchild thứ 1 = [1, 2, 1].
     * Template STT join('.') → "1", "1.2", "1.2.1". Populate trong `flattenTree`.
     */
    indexPath?: number[];
}
interface SdTableDisplay {
    tooltip?: string;
    badge?: {
        type: SdUnwrapSignal<SdBadge['type']>;
        color: SdUnwrapSignal<SdBadge['color']>;
        icon?: SdUnwrapSignal<SdBadge['icon']>;
        title?: SdUnwrapSignal<SdBadge['title']>;
    };
    cellStyle?: Record<string, string>;
    data: string | number | undefined | null;
    isHtml: boolean;
    click?: () => void;
}
interface SdTableMetaGroup<T = any> {
    /** Children items thuộc group này (chỉ set trên group header row). */
    items?: SdTableItem<T>[];
    /** true = row này là synthetic group header (sinh bởi SdGroupPipe). */
    isGroupHeader?: boolean;
    /** Hash key của group (= Utilities.hash(values)). */
    key?: string;
    /** Resolved group-field values (vd `{ customerId: 1, customerName: 'A' }`). */
    values?: Record<string, any>;
    /** Trạng thái expand. Chỉ ý nghĩa khi `option.group.collapsible = true`. */
    isExpanded?: boolean;
}
interface SdTableMeta<T> {
    id: string;
    display: Record<string, SdTableDisplay>;
    selector?: SdTableMetaSelector;
    expand?: SdTableMetaExpand;
    group?: SdTableMetaGroup<T>;
    tree?: SdTableMetaTree<T>;
}
interface SdTableItem<T = any> {
    meta: SdTableMeta<T>;
    data: T;
}

interface Context$3<T = any> {
    item: SdTableItem<T>;
}
declare class SdTableExpandDefDirective<T = any> {
    static ngTemplateContextGuard<T>(_dir: SdTableExpandDefDirective<T>, _ctx: unknown): _ctx is Context$3<T>;
    templateRef: TemplateRef<Context$3<T>>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableExpandDefDirective<any>, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableExpandDefDirective<any>, "[sdTableExpandDef]", never, {}, {}, never, never, true, never>;
}

interface Context$2 {
    externalFilter?: Record<string, unknown>;
}
declare class SdTableFilterDefDirective {
    static ngTemplateContextGuard(_dir: SdTableFilterDefDirective, _ctx: unknown): _ctx is Context$2;
    sdTableFilterDef: _angular_core.InputSignal<string>;
    defaultShowing: _angular_core.InputSignalWithTransform<boolean, unknown>;
    templateRef: TemplateRef<Context$2> | null;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableFilterDefDirective, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableFilterDefDirective, "[sdTableFilterDef]", never, { "sdTableFilterDef": { "alias": "sdTableFilterDef"; "required": true; "isSignal": true; }; "defaultShowing": { "alias": "defaultShowing"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}

interface Context$1<T = any> {
    items: SdTableItem<T>[];
    column: SdTableColumn<T>;
}
declare class SdMaterialFooterDefDirective<T = any> {
    static ngTemplateContextGuard<T>(_dir: SdMaterialFooterDefDirective<T>, _ctx: unknown): _ctx is Context$1<T>;
    sdTableFooterDef: _angular_core.InputSignal<string>;
    templateRef: TemplateRef<Context$1<T>>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdMaterialFooterDefDirective<any>, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdMaterialFooterDefDirective<any>, "[sdTableFooterDef]", never, { "sdTableFooterDef": { "alias": "sdTableFooterDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
}

interface SdTableGroupDefContext<T = any> {
    /** Children items thuộc group hiện tại (kèm wrapper SdTableItem). */
    items: SdTableItem<T>[];
    /** Children raw data (đã unwrap khỏi SdTableItem) — tiện dùng trong template. */
    data: T[];
    /** Hash key của group (Utilities.hash(values)). */
    key: string;
    /** Resolved giá trị các field group — vd `{ customerId: 1, customerName: 'A' }`. */
    values: Record<string, any>;
    /** true nếu group đang expand, false nếu collapse (chỉ ý nghĩa khi option.group.collapsible). */
    isExpanded: boolean;
    /** true nếu mọi children selectable đều selected. */
    isSelected: boolean;
    /** true nếu một phần children selected (partial). */
    indeterminate: boolean;
    /** Toggle expand/collapse (chỉ chạy nếu collapsible). */
    toggleExpand: () => void;
    /** Toggle select-all cho cả group (chỉ chạy nếu selector visible). */
    toggleSelect: () => void;
}
/**
 * Directive cung cấp custom template render group header row trong sd-table.
 * Thay thế cho htmlTemplate callback cũ — cho phép Angular template binding,
 * pipes, components con (sd-badge, sd-button, …) bên trong.
 *
 * Ví dụ:
 * ```html
 * <sd-table [option]="opt">
 *   <ng-template sdTableGroupDef let-values="values" let-items="items" let-indeterminate="indeterminate">
 *     <b>Khách hàng: {{ values.customerName }}</b>
 *     <span>{{ items.length }} đơn hàng</span>
 *   </ng-template>
 * </sd-table>
 * ```
 */
declare class SdTableGroupDefDirective<T = any> {
    static ngTemplateContextGuard<T>(_dir: SdTableGroupDefDirective<T>, _ctx: unknown): _ctx is SdTableGroupDefContext<T>;
    templateRef: TemplateRef<SdTableGroupDefContext<T>>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableGroupDefDirective<any>, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableGroupDefDirective<any>, "[sdTableGroupDef]", never, {}, {}, never, never, true, never>;
}

interface Context<T = any> {
    column: SdTableColumn<T>;
}
declare class SdTableTitleDefDirective<T = any> {
    static ngTemplateContextGuard<T>(_dir: SdTableTitleDefDirective<T>, _ctx: unknown): _ctx is Context<T>;
    sdTableTitleDef: _angular_core.InputSignal<string>;
    templateRef: TemplateRef<Context<T>>;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTableTitleDefDirective<any>, never>;
    static ɵdir: _angular_core.ɵɵDirectiveDeclaration<SdTableTitleDefDirective<any>, "[sdTableTitleDef]", never, { "sdTableTitleDef": { "alias": "sdTableTitleDef"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
}

interface SdTableQuickFilter {
    code: string;
    columnFilter: Record<string, any>;
    externalFilter: Record<string, any>;
}
interface TableFilterConfiguration {
    inlineExternal: Record<string, boolean>;
}
interface TableFilterValue {
    columnOperator?: Record<string, Operator>;
    columnFilter?: Record<string, any>;
    externalFilter?: Record<string, any>;
    notReload?: boolean;
    filtered?: boolean;
}
interface SdTableFilterRequest<T = any> {
    columnOperator: Record<NestedKeyOf<T>, Operator>;
    rawColumnFilter: Record<NestedKeyOf<T>, any>;
    rawExternalFilter: Record<string, any>;
    pageNumber: number;
    pageSize: number;
    orderBy?: string;
    orderDirection?: Order['direction'];
    isExported?: boolean;
    visibledColumns?: SdTableColumn[];
}
interface SdTableOptionFilter<T = any> {
    /** Key định danh nếu muốn lưu cache */
    key?: string;
    /** Có bật cache giá trị filter hay không */
    cacheable?: boolean;
    /** Vô hiệu toàn bộ filter */
    disabled?: boolean;
    /** Ẩn tất cả inline filter (chỉ còn external), nếu chọn auto thì sẽ ẩn khi total row <= 10, phù hợp cho các màn detail có ít dữ liệu */
    hideInlineFilter?: boolean | 'auto';
    /** Hàm xử lý khi đổi Operator của filter column */
    operatorChange?: (column?: SdTableColumn, operator?: Operator) => void;
    /** Danh sách external filter */
    externalFilters?: SdTableExternalFilter[];
    /** Số lượng cột external filter trên mỗi hàng (mặc định: 6) */
    externalFilterPerRow?: 4 | 6;
    /** Chế độ thủ công: phải nhấn nút áp dụng mới gửi filter */
    manualFilter?: boolean;
    /** Có thể thu gọn bộ lọc hay không */
    collapsible?: boolean;
    /** @deprecated Use `collapsible` instead. */
    collapsable?: boolean;
    /** Ẩn toolbar (xóa bộ lọc, thiết lập) của external filter, khi có ít external filter user không cần chức năng này */
    hideExternalFilterToolbar?: boolean;
    /** Hàm xử lý khi trigger clear filter từ external filter */
    onClearFilter?: () => void;
}
declare const SdConvertToPagingReq: (filterRequest: SdTableFilterRequest, args: {
    columns?: SdTableColumn[];
    externalFilters?: SdTableExternalFilter[];
    fieldMapping?: Record<string, string>;
    orders?: Order[];
}) => PagingReq;
declare type SdTableExternalFilter<TData = any> = TextFilter<TData> | DateFilter<TData> | DateTimeFilter<TData> | DateRangeFilter<TData> | NumberFilter<TData> | ValuesFilter<TData> | LazyValuesFilter<TData> | BooleanFilter<TData> | CustomFilter<TData>;
interface BaseFilter<TData = any> {
    field: string;
    title: string;
    defaultShowing?: boolean;
    required?: boolean;
    hidden?: boolean;
    defaultOperator?: Operator;
    data?: TData;
    onChange?: (value: any) => void;
}
interface TextFilter<TData = any> extends BaseFilter<TData> {
    type: 'string';
    default?: string;
}
interface DateFilter<TData = any> extends BaseFilter<TData> {
    type: 'date';
    default?: Date | string;
    minDate?: string | number | Date;
    maxDate?: string | number | Date;
}
interface DateTimeFilter<TData = any> extends BaseFilter<TData> {
    type: 'datetime';
    default?: Date | string;
    minDate?: string | number | Date;
    maxDate?: string | number | Date;
}
interface DateRangeFilter<TData = any> extends BaseFilter<TData> {
    type: 'daterange';
    enableTime?: boolean;
    minDate?: string | number | Date;
    maxDate?: string | number | Date;
    default?: {
        from?: Date | string;
        to?: Date | string;
    };
}
interface NumberFilter<TData = any> extends BaseFilter<TData> {
    type: 'number';
    default?: number;
}
interface ValuesFilter<TData = any> extends BaseFilter<TData> {
    type: 'values';
    option: {
        valueField: string;
        displayField: string;
        items: any[] | (() => Promise<any[]>);
        selection?: 'AUTOCOMPLETE' | 'MULTIPLE' | 'MULTIPLEAUTOCOMPLETE';
    };
    default?: string | string[];
}
interface LazyValuesFilter<TData = any> extends BaseFilter<TData> {
    type: 'lazy-values';
    option: {
        valueField: string;
        displayField: string;
        items: SdSearch;
        selection?: 'MULTIPLE';
    };
    default?: string | string[];
}
interface BooleanFilter<TData = any> extends BaseFilter<TData> {
    type: 'boolean';
    option?: {
        displayOnTrue?: string;
        displayOnFalse?: string;
    };
    default?: boolean;
}
interface CustomFilter<TData = any> extends BaseFilter<TData> {
    type: 'custom';
    filterDef?: TemplateRef<any>;
    default?: any;
}
interface TableFilterRegister {
    configuration: {
        get: () => TableFilterConfiguration;
        set: (configuration: Partial<TableFilterConfiguration>) => TableFilterConfiguration;
        remove: () => void;
        observer: Observable<TableFilterConfiguration>;
    };
    value: {
        get: () => TableFilterValue;
        set: (value: Partial<TableFilterValue>) => TableFilterValue;
        remove: () => void;
        observer: Observable<TableFilterValue>;
    };
}

interface SdTableCommandOption<T = any> {
    align?: 'left' | 'right';
    commands?: SdTableCommand<T>[];
}
type SdTableCommand<T = any> = SdTableCommandNormal<T> | SdTableCommandChildren<T>;
interface SdTableCommandNormal<T = any> {
    color?: Color;
    icon?: string | ((rowData: T) => string);
    fontSet?: MaterialIconFontSet;
    title?: string | ((rowData: T) => string);
    disabled?: boolean | ((rowData: T) => boolean);
    hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
    click: (rowData: T) => void;
    htmlTemplate?: (rowData: T) => string;
}
interface SdTableCommandChildren<T = any> {
    icon?: string | ((rowData: T) => string);
    fontSet?: MaterialIconFontSet;
    title?: string | ((rowData: T) => string);
    disabled?: boolean | ((rowData: T) => boolean);
    hidden?: boolean | ((rowData: T) => boolean | Promise<boolean>);
    children: SdTableCommandNormal<T>[];
}

interface TableOptionConfig {
    visible?: boolean;
    resizable?: boolean;
    onResize?: (field: string, width: string, columnWidth: Record<string, string>) => void;
}
interface OriginColumn {
    field: string;
    title: string;
    width?: string;
    invisible?: boolean;
    fixed?: boolean;
    truncate?: boolean;
}
interface ConfiguredColumn {
    origin: OriginColumn;
    title?: string;
    width?: string;
    invisible?: boolean;
    fixed?: boolean;
    truncate?: boolean;
}
interface ConfiguredTable {
    columns?: ConfiguredColumn[];
}
interface ConfiguredTableResult {
    column: Record<string, {
        title?: string;
        width?: string;
    }>;
    fixedColumn: Record<string, {
        title?: string;
        width?: string;
    }>;
    firstColumns: SdTableColumn[];
    secondColumns: SdTableColumn[];
    firstHeaders: string[];
    secondHeaders: string[];
    displayedColumns: string[];
    displayedFooters: string[];
    multipleHeader: boolean;
}

interface SdTableOptionExpand<T = any> {
    disabled?: (rowData: T) => boolean;
    onExpand?: (rowData: T) => Promise<any> | any;
    multiple?: boolean;
    always?: boolean;
}

type SdTableOptionExport<T = any> = SdTableOptionExportDefault<T> | SdTableOptionExportCustom;
interface SdTableOptionExportDefault<T = any> {
    type?: 'default';
    key?: string;
    visible?: 'ALL' | 'EXCEL' | 'CSV';
    enableUpload?: boolean;
    fileName?: string;
    max?: number;
    maxItemsPerRequest?: number;
    batch?: number;
    items?: (filterRequest: SdTableFilterRequest) => T[] | Promise<T[]> | Promise<{
        items: any[];
        total: number;
    }>;
    mapping?: (items: T[], fileName?: string) => T[] | Promise<T[]>;
    columns?: SdTableOptionExportColumn<T>[];
    sheets?: SdTableOptionExportSheet[];
}
interface SdTableOptionExportCustom {
    type: 'custom';
    onExport: (filterRequest: SdTableFilterRequest) => Promise<void>;
}
interface SdTableOptionExportColumn<T = any> {
    field: NestedKeyOf<T>;
    title: string;
    description?: string;
    width?: string;
    transform?: (value: any, rowData: T) => string;
    export?: {
        disabled: boolean;
    };
}
interface SdTableOptionExportSheet<T = any> {
    name: string;
    items: T[] | (() => T[] | Promise<T[]>);
    headers: {
        value: NestedKeyOf<T>;
        display: string;
    }[];
}

interface SdTableOptionGroup<T = any> {
    /**
     * Danh sách field dùng để nhóm. Item có cùng giá trị tất cả `fields` sẽ vào cùng group.
     * Ví dụ `['customerId']` group orders theo khách hàng.
     * Type-safe qua `NestedKeyOf<T>` — hỗ trợ dot-notation cho nested object (vd `'customer.id'`).
     */
    fields: NestedKeyOf<T>[];
    /**
     * Mặc định group có collapse được không. true = render với UI có thể expand/collapse;
     * false = luôn show toàn bộ children (mặc định).
     */
    collapsible?: boolean;
    /** Nếu collapsible, mặc định trạng thái ban đầu: true = collapsed, false = expanded (default). */
    defaultCollapsed?: boolean;
    /**
     * Predicate tùy chọn cho selection. Khi check `selectable` của group header.
     * Mặc định: chỉ nhóm có >=1 child `selectable` mới hiển thị checkbox.
     */
    selectable?: (children: T[]) => boolean;
}

interface SdTableOptionPaginate {
    pageSize?: number;
    pages?: number[];
    showFirstLastButtons?: boolean;
    hidePageSize?: boolean;
    hidden?: boolean;
}

interface SdTableOptionReload<T = any> {
    visible?: boolean;
    onReload?: (items: SdTableItem<T>[], args?: {
        fromSource?: 'PAGING' | 'RELOAD';
    }) => Promise<void> | void;
}

interface SdTableOptionSelector<T = any> {
    /** Bật/tắt cột checkbox selector. Mặc định: true. */
    visible?: boolean;
    /** Chỉ cho chọn 1 dòng tại một thời điểm. */
    single?: boolean;
    /** Danh sách action hiển thị khi có item được chọn. */
    actions?: SdTableAction<T>[];
    /** Nội dung hiển thị bên cạnh selector/action bar. */
    message?: string | ((selectedItems?: T[]) => string);
    /** Callback khi user chọn/bỏ chọn một dòng. */
    onSelect?: (rowData?: T, selectedItems?: T[]) => void;
    /** Callback khi user chọn tất cả hoặc bỏ chọn tất cả. */
    onSelectAll?: (selectedItems: T[]) => void;
    /** Disable checkbox của từng dòng theo điều kiện. */
    disabled?: (rowData?: T, selectedItems?: T[]) => boolean;
    /**
     * Predicate để tự động pre-select item sau mỗi lần load.
     * Table sẽ gọi hàm này cho từng item và set isSelected = true nếu trả về true.
     * Dùng khi cần programmatically set selected items từ bên ngoài.
     */
    defaultSelected?: (rowData: T) => boolean;
    /**
     * Giữ lại selection khi user chuyển trang / filter / sort / reload.
     * Selection chỉ bị clear khi user bấm nút X (onClearSelection) hoặc bỏ chọn từng item.
     *
     * - Default (false): selection bị mất khi data items được re-fetch (server-side) hoặc
     *   item references thay đổi. Action bar chỉ hiển thị số item selected ở page hiện tại.
     * - Enabled (true): table giữ map nội bộ selectedItems theo `meta.id` (hash của data).
     *   Sau mỗi #render, restore `isSelected` cho item nào id đã có trong map.
     *   `selectedTableItems()` trả về TOÀN BỘ item đã chọn xuyên trang (kể cả off-page),
     *   nên action bar + callback `click(items)` nhận đầy đủ data đang được chọn.
     *
     * Lưu ý: matching dựa trên `Utilities.hash(data)` — hai item có cùng data shape sẽ
     * trùng id (mong muốn). Nếu data có timestamp/random field thay đổi giữa các lần fetch,
     * id sẽ khác và selection không restore được.
     */
    preserveSelection?: boolean;
}
type SdTableAction<T = any> = SdTableActionNormal<T> | SdTableActionChildren<T>;
interface SdTableActionNormal<T = any> {
    /**
     * Tên icon hiển thị trên action button.
     * Giá trị này được render qua `mat-icon`, vì vậy nên dùng đúng tên glyph của Material Icons.
     * Tra cứu icon tại: https://fonts.google.com/icons
     */
    icon?: string;
    /**
     * Font set của Material icon.
     * Kiểu thực tế lấy từ `SdButton['fontSet']` và chỉ hỗ trợ các giá trị thuộc `MaterialIconFontSet`,
     * ví dụ: `material-icons`, `material-icons-outlined`, `material-icons-round`,
     * `material-icons-sharp`.
     * Nếu không truyền, `SdButton` sẽ dùng font set mặc định của nó.
     */
    fontSet?: SdUnwrapSignal<SdButton['fontSet']>;
    /** Tooltip hiển thị khi hover action button. */
    tooltip?: SdUnwrapSignal<SdButton['tooltip']>;
    /** Text label hiển thị trên button action. */
    title?: SdUnwrapSignal<SdButton['title']>;
    /**
     * Màu của `SdButton`.
     * Kiểu thực tế map theo `SdButton['color']`, hiện dùng các token như
     * `primary`, `secondary`, `info`, `success`, `warning`, `error`.
     */
    color?: SdUnwrapSignal<SdButton['color']>;
    /**
     * Variant hiển thị của `SdButton`.
     * Kiểu thực tế là `fill | light | outline | link`.
     */
    type?: SdUnwrapSignal<SdButton['type']>;
    /** Ẩn action theo cờ tĩnh hoặc theo điều kiện của dữ liệu dòng. */
    hidden?: boolean | ((rowData?: T) => boolean);
    /** Gom action vào nhóm hiển thị compact nếu table hỗ trợ grouped actions. */
    isGrouped?: boolean;
    /** Hàm xử lý khi click action, nhận toàn bộ item đang được chọn. */
    click: (selectedItems?: T[]) => void;
}
interface SdTableActionChildren<T = any> {
    /**
     * Tên icon của action cha (group action).
     * Giá trị nên là tên glyph Material Icons: https://fonts.google.com/icons
     */
    icon?: string;
    /**
     * Font set của Material icon cho action cha.
     * Dùng cùng kiểu dữ liệu với `SdButton['fontSet']`.
     */
    fontSet?: SdUnwrapSignal<SdButton['fontSet']>;
    /** Tooltip của action cha. */
    tooltip?: SdUnwrapSignal<SdButton['tooltip']>;
    /** Label của action cha. */
    title?: SdUnwrapSignal<SdButton['title']>;
    /** Màu của action cha theo kiểu `SdButton['color']`. */
    color?: SdUnwrapSignal<SdButton['color']>;
    /** Variant hiển thị của action cha theo kiểu `SdButton['type']`. */
    type?: SdUnwrapSignal<SdButton['type']>;
    /** Ẩn action cha theo cờ tĩnh hoặc theo điều kiện của dữ liệu dòng. */
    hidden?: boolean | ((rowData?: T) => boolean);
    /** Gom action cha vào nhóm hiển thị compact nếu table hỗ trợ grouped actions. */
    isGrouped?: boolean;
    /** Danh sách action con hiển thị bên trong group action này. */
    children: SdTableActionNormal<T>[];
}

interface SdTableOptionSort {
    enable?: boolean;
}

interface SdTableRowCssContext {
    level: number;
    hasChildren: boolean;
    isExpanded: boolean;
}
interface SdTableOptionStyle<T = any> {
    shadow?: boolean;
    maxHeight?: string;
    minHeight?: string;
    rowCss?: (rowData: T, index?: number, ctx?: SdTableRowCssContext) => Record<string, string>;
}

/**
 * Cấu hình tree-rows cho `<sd-table>` — render dòng con inline dưới dòng cha
 * kèm expand/collapse.
 *
 * Đây là discriminated union theo `loadType`:
 * - `'static'` ({@link TableOptionTreeStatic}) — children đã nằm sẵn trong data
 *   (embedded array tại `childrenKey`). Không gọi API khi bung.
 * - `'lazy'`  ({@link TableOptionTreeLazy})  — children nạp theo yêu cầu qua
 *   `onExpandChildren` khi người dùng bung dòng lần đầu.
 *
 * `loadType` là discriminant: TypeScript dựa vào nó để narrow union (vd chỉ
 * `static` mới có `childrenKey`/`defaultExpanded`, chỉ `lazy` mới có
 * `onExpandChildren`). Dùng type-guard `isLazyTree()` trong `tree.util.ts` để
 * narrow an toàn thay vì truy cập field trực tiếp trên union.
 *
 * @example Static (children embedded)
 * ```ts
 * tree: { loadType: 'static', childrenKey: 'children', defaultExpanded: 1 }
 * ```
 * @example Lazy (nạp theo yêu cầu)
 * ```ts
 * tree: { loadType: 'lazy', onExpandChildren: row => api.getChildren(row.id) }
 * ```
 */
type SdTableOptionTree<T = any> = TableOptionTreeStatic<T> | TableOptionTreeLazy<T>;
/**
 * Tree với dữ liệu children **embedded** sẵn trong mỗi row.
 *
 * Table đọc mảng con tại `childrenKey` ngay trên object data; không có lời gọi
 * bất đồng bộ nào khi bung dòng. Đây cũng là chế độ hỗ trợ **search ở cấp con**
 * cho table `type: 'local'` (xem `tree.util.ts#subtreeMatches` /
 * `filterMatchingChildren`): khi lọc, một nhánh được giữ lại nếu chính nó hoặc
 * bất kỳ hậu duệ nào khớp từ khoá, và nhánh khớp sẽ tự bung.
 */
interface TableOptionTreeStatic<T = any> {
    /** Chế độ nạp children: dữ liệu đã embedded sẵn trong row. */
    loadType: 'static';
    /**
     * Key trên object row chứa mảng children.
     * Mặc định: `'children'`.
     */
    childrenKey?: NestedKeyOf<T> | 'children';
    /**
     * Giới hạn độ sâu cây (level gốc = 0).
     * `undefined` = không giới hạn.
     */
    maxDepth?: number;
    /**
     * Trạng thái bung mặc định khi load:
     * - `false` — thu gọn hết (mặc định)
     * - `true`  — bung toàn bộ
     * - `number N` — bung tới cấp `N` (row có `level < N` được bung)
     */
    defaultExpanded?: boolean | number;
    /**
     * Số pixel thụt lề (indent) cho mỗi cấp sâu.
     * Mặc định: `20`.
     */
    indentSize?: number;
}
/**
 * Tree với children **nạp lười (lazy)** theo yêu cầu.
 *
 * Khi người dùng bung một dòng lần đầu mà dòng đó chưa có children embedded,
 * table gọi `onExpandChildren(row)` để nạp; kết quả được cache lại trên row
 * (ghi vào key `'children'`) nên các lần bung sau không gọi lại.
 *
 * Lazy tree **không hỗ trợ** `childrenKey` tuỳ biến (luôn dùng `'children'` làm
 * nơi lưu kết quả) và **không hỗ trợ** `defaultExpanded` (không thể bung mặc
 * định nhánh chưa nạp).
 */
interface TableOptionTreeLazy<T = any> {
    /** Chế độ nạp children: nạp lười theo yêu cầu khi bung. */
    loadType: 'lazy';
    /**
     * Giới hạn độ sâu cây (level gốc = 0).
     * `undefined` = không giới hạn.
     */
    maxDepth?: number;
    /**
     * Hàm nạp children khi bung dòng chưa có children embedded.
     * Trả về `Promise<T[]>`; kết quả được ghi vào key `'children'` của row data
     * và cache cho các lần bung sau.
     */
    onExpandChildren: (rowData: T) => Promise<T[]>;
    /**
     * Xác định một row có con hay không — để quyết định có hiển thị icon expand.
     * - Không truyền: MỌI lazy node đều hiện icon expand (không biết trước được).
     * - Truyền: chỉ hiện icon khi trả `true`; trả `false` ⇒ row là lá (ẩn icon,
     *   không gọi `onExpandChildren`).
     * Lưu ý: nếu row đã có children embedded sẵn thì luôn coi là có con (bỏ qua hàm này).
     */
    hasChildren?: (rowData: T) => boolean;
    /**
     * Số pixel thụt lề (indent) cho mỗi cấp sâu.
     * Mặc định: `20`.
     */
    indentSize?: number;
}

type SdTableOption<T = any> = SdTableLocalOption<T> | SdTableServerOption<T>;
interface SdTableBaseOption<T = any> {
    /**
     * Key định danh của table option.
     * Thường dùng khi một số tính năng con cần lưu trạng thái riêng theo table,
     * ví dụ các option có hỗ trợ cache/config theo key.
     */
    key?: string;
    /**
     * Cấu hình hiển thị/phục hồi config của table.
     * Xem thêm kiểu chi tiết tại `TableOptionConfig`.
     */
    config?: TableOptionConfig;
    /**
     * Cấu hình chọn dòng (checkbox selector, action theo selection, pre-select...).
     * Xem thêm tại `SdTableOptionSelector`.
     */
    selector?: SdTableOptionSelector<T>;
    /**
     * Cấu hình expand row.
     * Xem thêm tại `SdTableOptionExpand` để biết cách disable, expand nhiều dòng,
     * hoặc luôn hiển thị vùng expand.
     */
    expand?: SdTableOptionExpand<T>;
    /**
     * Bật/tắt sorting ở cấp table.
     * Xem thêm tại `SdTableOptionSort`.
     */
    sort?: SdTableOptionSort;
    /**
     * Cấu hình phân trang.
     * Xem thêm tại `SdTableOptionPaginate`.
     */
    paginate?: SdTableOptionPaginate;
    /**
     * Cấu hình hành vi reload dữ liệu.
     * Xem thêm tại `SdTableOptionReload`.
     */
    reload?: SdTableOptionReload<T>;
    /**
     * Cấu hình export dữ liệu.
     * Xem thêm tại `SdTableOptionExport` để biết mode `default`/`custom`, mapping,
     * sheet export và giới hạn số dòng.
     */
    export?: SdTableOptionExport<T>;
    /**
     * Cấu hình group dữ liệu theo nhiều field.
     * Xem thêm tại `SdTableOptionGroup`.
     */
    group?: SdTableOptionGroup<T>;
    /**
     * Cấu hình tree rows — render children inline dưới parent.
     * Xem thêm tại `SdTableOptionTree`.
     */
    tree?: SdTableOptionTree<T>;
    /**
     * Cấu hình filter của table.
     * Xem thêm tại `SdTableOptionFilter` để biết filter inline, external filter,
     * manual filter, cacheable và callback clear filter.
     */
    filter?: SdTableOptionFilter;
    /**
     * Cấu hình cột đánh số thứ tự (STT) ở đầu mỗi dòng.
     * Khi enabled = true, table render thêm 1 cột STT (sticky đầu, sau selector).
     * Số thứ tự tính theo global index (pageIndex * pageSize + i + 1) để tương thích phân trang.
     */
    index?: {
        /** Bật/tắt cột STT. */
        enabled?: boolean;
        /** Tiêu đề header (mặc định '#'). */
        title?: string;
        /** Width của cột (mặc định '50px'). */
        width?: string;
    };
    /**
     * Bật cột filler ở cuối row để hấp thụ leftover width khi tổng width các cột data < container.
     * Khi enabled = true, các cột utility (selection / STT / command) không bị browser stretch trên màn rộng.
     * Mặc định off — table tự stretch cột data theo `width: 100%` như cũ.
     */
    filler?: {
        /** Bật/tắt cột filler. */
        enabled?: boolean;
    };
    /**
     * Cấu hình kéo-thả đổi thứ tự dòng.
     * Chỉ bật khi table cho phép reorder dữ liệu phía client.
     */
    rowReorder?: {
        /** Bật/tắt tính năng reorder row. */
        enabled?: boolean;
        /**
         * Callback sau khi reorder xong.
         * `newRows` là mảng sau khi đã đổi vị trí ở UI,
         * `movedItem` là item vừa được kéo,
         * `fromIndex` và `toIndex` là vị trí cũ/mới.
         */
        onChange?: (newRows: T[], movedItem: T, fromIndex: number, toIndex: number) => void;
        /**
         * Tên icon hiển thị cho drag handle.
         * Nếu không truyền thì table dùng icon reorder mặc định của Material.
         * Nếu truyền custom icon, nên dùng tên glyph của Material Icons:
         * https://fonts.google.com/icons
         */
        icon?: string;
        /**
         * Disable khả năng reorder theo từng dòng.
         * Trả về `true` để chặn kéo-thả dòng tương ứng.
         */
        disabled?: (row: T, index: number) => boolean;
    };
    /**
     * Danh sách command thao tác theo từng dòng.
     * Xem thêm tại `SdTableCommand`.
     */
    commands?: SdTableCommand<T>[];
    /**
     * Cấu hình vùng command tập trung.
     * Dùng khi cần set thêm alignment hoặc bọc danh sách command trong object option.
     * Xem thêm tại `SdTableCommandOption`.
     */
    command?: SdTableCommandOption<T>;
    /**
     * Danh sách cột hiển thị của table.
     * Đây là phần bắt buộc. Xem thêm tại `SdTableColumn` để cấu hình field, filter,
     * sort, transform, template và export của từng cột.
     */
    columns: SdTableColumn<T>[];
    /**
     * Cấu hình style/layout chung của table.
     * Xem thêm tại `SdTableOptionStyle`.
     */
    style?: SdTableOptionStyle<T>;
}
interface SdTableLocalOption<T = any> extends SdTableBaseOption<T> {
    /** Dùng dữ liệu local tại client. */
    type: 'local';
    /**
     * Hàm trả dữ liệu local cho table.
     * Table sẽ tự gọi hàm này để lấy mảng item nguồn.
     * Có thể trả về đồng bộ hoặc `Promise<T[]>`.
     */
    items: () => T[] | Promise<T[]>;
}
interface SdTableServerOption<T = any> extends SdTableBaseOption<T> {
    /** Dùng dữ liệu từ server, có paging/filter/sort theo request của table. */
    type: 'server';
    /**
     * Hàm lấy dữ liệu từ server.
     * `filterRequest` chứa trạng thái filter/sort/visible columns ở dạng của table.
     * `pagingReq` là dữ liệu paging đã được chuẩn hóa để dễ map sang API backend.
     * Hàm cần trả về `{ items, total }` để table render và tính phân trang.
     */
    items: (filterRequest: SdTableFilterRequest<T>, pagingReq: PagingReq<T>) => Promise<{
        items: T[];
        total: number;
    }>;
    /**
     * Hook chạy khi table phát sinh filter request.
     * Dùng để can thiệp thêm trước/sau khi gọi API, ví dụ sync external state,
     * theo dõi trạng thái valid của external filter, hoặc ghi log request filter hiện tại.
     */
    onFilter?: (filterRequest: SdTableFilterRequest<T>, args: {
        /** Cho biết toàn bộ external filter hiện tại có hợp lệ để trigger filter hay không. */
        externalFilterValid: boolean;
    }) => void;
}

declare class ExternalFilterComponent {
    #private;
    autoIdInput: _angular_core.InputSignal<string | null | undefined>;
    filter: _angular_core.InputSignal<SdTableOptionFilter<any> | undefined>;
    externalFilters: _angular_core.InputSignal<SdTableExternalFilter[] | null | undefined>;
    filterRegister: _angular_core.InputSignal<TableFilterRegister | undefined>;
    externalFilter: _angular_core.WritableSignal<Record<string, any>>;
    inlineExternal: _angular_core.WritableSignal<Record<string, boolean>>;
    filtered: _angular_core.WritableSignal<boolean>;
    isMobileOrTablet: boolean;
    readonly form: FormGroup<{}>;
    autoId: _angular_core.Signal<string>;
    col: _angular_core.Signal<2 | 3>;
    filterItems: _angular_core.Signal<SdTableExternalFilter[]>;
    constructor();
    onKeyupEnter: () => void;
    onFilter: (externalFilter: SdTableExternalFilter) => void;
    onSubmit: () => void;
    updateFilter: () => void;
    clearFilter: (event?: Event) => void;
    onCheckboxChange: (event: Event, externalFilter: SdTableExternalFilter) => void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<ExternalFilterComponent, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<ExternalFilterComponent, "external-filter", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "externalFilters": { "alias": "externalFilters"; "required": false; "isSignal": true; }; "filterRegister": { "alias": "filterRegister"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}

/**
 * Mobile-filter — side-drawer chiếm ~90% width thiết bị. Dùng cho table khi
 * render trên màn hình điện thoại (inline filter bị ẩn).
 *
 * Layout (mỗi filter 1 hàng, size='sm'):
 *  1. External filter (render inline — KHÔNG reuse external-filter component
 *     vì component đó dùng grid 2/3 cột + có chọn ẩn/hiện không phù hợp mobile).
 *  2. filterDefs — custom templates do app khai báo qua `[sdTableFilterDef]`.
 *  3. Column filter — 1 column-filter / column.
 *
 * State: local working copy. Cancel = đóng (không ghi). Apply = flush vào
 * filterRegister + đóng.
 */
declare class MobileFilterComponent {
    autoIdInput: _angular_core.InputSignal<string | null | undefined>;
    filter: _angular_core.InputSignal<SdTableOptionFilter<any> | undefined>;
    externalFilters: _angular_core.InputSignal<SdTableExternalFilter[] | null | undefined>;
    columns: _angular_core.InputSignal<SdTableColumn[] | null | undefined>;
    filterDefs: _angular_core.InputSignal<readonly SdTableFilterDefDirective[] | null | undefined>;
    filterRegister: _angular_core.InputSignal<TableFilterRegister | undefined>;
    cacheValues: _angular_core.InputSignal<Record<string, any[]> | undefined>;
    drawer: _angular_core.Signal<SdSideDrawer>;
    workingColumnFilter: _angular_core.WritableSignal<Record<string, any>>;
    workingColumnOperator: _angular_core.WritableSignal<Record<string, Operator>>;
    workingExternalFilter: _angular_core.WritableSignal<Record<string, any>>;
    autoId: _angular_core.Signal<string>;
    externalFilterItems: _angular_core.Signal<SdTableExternalFilter[]>;
    columnItems: _angular_core.Signal<SdTableColumn[]>;
    filterDefItems: _angular_core.Signal<readonly SdTableFilterDefDirective[]>;
    open: () => void;
    close: () => void;
    onApply: () => void;
    onCancel: () => void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobileFilterComponent, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<MobileFilterComponent, "mobile-filter", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "externalFilters": { "alias": "externalFilters"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "filterDefs": { "alias": "filterDefs"; "required": false; "isSignal": true; }; "filterRegister": { "alias": "filterRegister"; "required": false; "isSignal": true; }; "cacheValues": { "alias": "cacheValues"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
}

declare class ConfigComponent {
    #private;
    autoIdInput: _angular_core.InputSignal<string | null | undefined>;
    tableOption: _angular_core.InputSignal<SdTableOption | undefined>;
    changes: _angular_core.OutputEmitterRef<ConfiguredTableResult>;
    autoId: _angular_core.Signal<string>;
    modal: _angular_core.Signal<SdModal | undefined>;
    table: _angular_core.Signal<MatTable<SdTableColumn>>;
    configuration: _angular_core.WritableSignal<ConfiguredTable | undefined>;
    dragDisabled: boolean;
    constructor();
    open: () => Promise<void>;
    close: () => void;
    onSave: () => void;
    onReset: () => Promise<void>;
    dropTable(event: any): void;
    handleMouseDown(): void;
    handleMouseUp(): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<ConfigComponent, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<ConfigComponent, "config", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "tableOption": { "alias": "tableOption"; "required": false; "isSignal": true; }; }, { "changes": "changes"; }, never, never, true, never>;
}

declare class SdPopupExport {
    #private;
    private ref;
    private loadingService;
    private excelService;
    private notifyService;
    private confirmService;
    tableOption: SdTableOption;
    columns: SdExcelColumn[];
    templateName?: string | null;
    enableCreating: boolean;
    modal?: SdModal;
    listGroups?: MatSelectionList;
    selected: Record<string, boolean>;
    files: any[];
    export: EventEmitter<{
        file: any | null;
        columns: SdExcelColumn[];
        isCSV?: boolean;
    }>;
    form: FormGroup<{}>;
    exportOption?: SdTableOptionExportDefault;
    set _tableOption(option: SdTableOption);
    configuration?: ConfiguredTableResult;
    private get key();
    private get tableColumns();
    private get additionalColumns();
    constructor(ref: ChangeDetectorRef, loadingService: SdLoadingService, excelService: SdExcelService, notifyService: SdNotifyService, confirmService: SdConfirmService);
    open: () => Promise<void>;
    exportDefault: () => void;
    exportCSV: () => void;
    loadFiles: (group?: string | undefined) => Promise<void>;
    generateTemplate: () => Promise<void>;
    generateAndUploadTemplate: (fileName?: string) => Promise<void>;
    onExport: (file: any) => void;
    uploadTemplate: () => Promise<void>;
    removeFile: (file: any) => void;
    createTemplate: () => Promise<void>;
    templateNameValidator: (val: string) => string;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdPopupExport, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdPopupExport, "sd-popup-export", never, { "_tableOption": { "alias": "tableOption"; "required": false; }; "configuration": { "alias": "configuration"; "required": false; }; }, { "export": "export"; }, never, never, true, never>;
}

interface ISdTableConfiguration {
    paginate?: {
        /** Số dòng mỗi trang. */
        pageSize?: SdTableOptionPaginate['pageSize'];
        /** Danh sách các tuỳ chọn số dòng/trang mà người dùng có thể chọn. */
        pages?: SdTableOptionPaginate['pages'];
        showFirstLastButtons?: SdTableOptionPaginate['showFirstLastButtons'];
    };
    filter?: {
        /** Ẩn bộ lọc dưới cột, nếu không cấu hình thì giá trị mặc định là false */
        hideInlineFilter?: SdTableOptionFilter['hideInlineFilter'];
        /** Số lượng external filter mỗi dòng, mặc định là 6 */
        externalFilterPerRow?: SdTableOptionFilter['externalFilterPerRow'];
        /**  Kích hoạt chế độ lọc thủ công, hiển thị nút áp dụng, mặc định là false */
        manualFilter?: SdTableOptionFilter['manualFilter'];
        /** Ẩn toolbar (xóa bộ lọc, thiết lập) của external filter, khi có ít external filter user không cần chức năng này, mặc định là false */
        hideExternalFilterToolbar?: SdTableOptionFilter['hideExternalFilterToolbar'];
        operator?: {
            list?: Partial<Record<SdTableColumn['type'], Operator[]>>;
            default?: Partial<Record<SdTableColumn['type'], Operator>>;
        };
    };
    images?: {
        filterRequired?: string;
        dataEmpty?: string;
        filterEmpty?: string;
    };
}
declare const SD_TABLE_CONFIGURATION: InjectionToken<ISdTableConfiguration>;

declare class MatPaginatorIntlCro extends MatPaginatorIntl {
    #private;
    firstPageLabel: string;
    lastPageLabel: string;
    itemsPerPageLabel: string;
    nextPageLabel: string;
    previousPageLabel: string;
    getRangeLabel: (page: number, pageSize: number, length: number) => string;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<MatPaginatorIntlCro, never>;
    static ɵprov: _angular_core.ɵɵInjectableDeclaration<MatPaginatorIntlCro>;
}
declare class SdTable<T = unknown> implements OnInit, AfterViewInit, OnDestroy {
    #private;
    autoIdInput: _angular_core.InputSignal<string | null | undefined>;
    autoId: _angular_core.Signal<string | undefined>;
    option: _angular_core.InputSignal<SdTableOption<T>>;
    table: _angular_core.Signal<MatTable<any> | undefined>;
    configComponent: _angular_core.Signal<ConfigComponent | undefined>;
    sdPopupExport: _angular_core.Signal<SdPopupExport | undefined>;
    scroll: _angular_core.Signal<SdScrollDirective | undefined>;
    quickAction: _angular_core.Signal<SdQuickAction | undefined>;
    externalFilter: _angular_core.Signal<ExternalFilterComponent | undefined>;
    mobileFilter: _angular_core.Signal<MobileFilterComponent | undefined>;
    paginator: _angular_core.Signal<MatPaginator | undefined>;
    sort: _angular_core.Signal<MatSort | undefined>;
    sdSubInformation: _angular_core.Signal<SdTableExpandDefDirective<any> | undefined>;
    sdGroupDef: _angular_core.Signal<SdTableGroupDefDirective<any> | undefined>;
    sdCellDefs: _angular_core.Signal<readonly SdTableCellDefDirective<any>[]>;
    sdFooterDefs: _angular_core.Signal<readonly SdMaterialFooterDefDirective<any>[]>;
    sdFilterDefs: _angular_core.Signal<readonly SdTableFilterDefDirective[]>;
    sdTitleDefs: _angular_core.Signal<readonly SdTableTitleDefDirective<any>[]>;
    cellDef: _angular_core.Signal<Record<string, SdTableCellDefDirective<any>>>;
    footerDef: _angular_core.Signal<Record<string, SdMaterialFooterDefDirective<any>>>;
    hasFooter: _angular_core.Signal<boolean>;
    titleDef: _angular_core.Signal<Record<string, SdTableTitleDefDirective<any>>>;
    tableOption: _angular_core.WritableSignal<SdTableOption<T> | undefined>;
    configuration: _angular_core.WritableSignal<ConfiguredTableResult | undefined>;
    items: _angular_core.WritableSignal<SdTableItem<T>[]>;
    selectedTableItems: _angular_core.WritableSignal<SdTableItem<T>[]>;
    total: _angular_core.WritableSignal<number | undefined>;
    loading: _angular_core.WritableSignal<boolean>;
    isSelectAll: _angular_core.WritableSignal<boolean>;
    isFiltered: _angular_core.WritableSignal<boolean>;
    requireFiltered: _angular_core.WritableSignal<boolean>;
    filterRegister: TableFilterRegister;
    key: string;
    columnOperator: Record<string, Operator>;
    columnFilter?: Record<string, any>;
    cacheValues: Record<string, any[]>;
    treeRevision: _angular_core.WritableSignal<number>;
    exporting: _angular_core.WritableSignal<boolean>;
    exportTitle: _angular_core.WritableSignal<string>;
    tableConfiguration: ISdTableConfiguration | null;
    constructor();
    ngOnInit(): void;
    ngAfterViewInit(): void;
    ngOnDestroy(): void;
    getFilterRequest: () => SdTableFilterRequest;
    reload: (force?: boolean, scrollTop?: boolean) => Promise<void>;
    exportExcel: (columns?: SdExcelColumn[]) => void;
    exportCSV: (columns?: SdExcelColumn[]) => void;
    exportCustom: () => void;
    onTreeToggle: (row: SdTableItem<T>) => Promise<void>;
    onFilterChange: () => void;
    onFilterCommit: () => void;
    onExpand: (rowData: SdTableItem<T>) => Promise<void>;
    onSelect: (rowData: SdTableItem<T>) => void;
    onSelectAll: () => void;
    onClearSelection: (items?: SdTableItem<T>[]) => void;
    /** true nếu MỌI selectable child trong group đều selected. Group rỗng (không child) → false. */
    isGroupAllSelected: (header: SdTableItem<T>) => boolean;
    /** true nếu CÓ MỘT VÀI selectable child selected nhưng KHÔNG phải tất cả. */
    isGroupIndeterminate: (header: SdTableItem<T>) => boolean;
    /** Toggle select-all cho 1 group: set isSelected cho mọi selectable child, sync state. */
    onSelectGroup: (header: SdTableItem<T>, checked: boolean) => void;
    groupExpandState: Map<string, boolean>;
    /** Toggle expand/collapse cho 1 group (chỉ ý nghĩa khi option.group.collapsible). */
    toggleGroupExpand: (header: SdTableItem<T>) => void;
    /**
     * Predicate cho matRowDef.when — phân biệt group header row vs data row.
     * Group header row dùng matRowDef riêng với column list ['sdGroupHeader'] (1 cell duy nhất).
     * Data row dùng displayedColumns nguyên vẹn.
     */
    isGroupHeaderRow: (_idx: number, row: SdTableItem<T>) => boolean;
    isDataRow: (_idx: number, row: SdTableItem<T>) => boolean;
    /**
     * Colspan cho cell sdGroupHeader trên group row = displayedColumns.length.
     * Span TOÀN BỘ width data row vì group row chỉ có 1 cell.
     */
    sdGroupColspan: _angular_core.Signal<number>;
    /** Build context object truyền vào SdTableGroupDefDirective template. */
    groupContext: (header: SdTableItem<T>) => SdTableGroupDefContext<T>;
    rowStyle: (row: SdTableItem<T>, index?: number) => Record<string, string> | null;
    clearFilter: () => void;
    setFilter: (args: {
        columnFilter?: Record<string, any>;
        externalFilter?: Record<string, any>;
    }) => void;
    get dataItems(): T[];
    get selectedItems(): T[];
    detectChanges: () => void;
    onColumnResize: (field: string, width: string) => void;
    onOperatorChange: (column: SdTableColumn, operator: Operator | undefined) => void;
    trackBy: (index: number, item: SdTableItem) => string;
    pageOffset: _angular_core.Signal<number>;
    isReorderDisabled(item: SdTableItem<T>): boolean;
    reorderSortPredicate: (index: number, drag: CdkDrag<SdTableItem<T>>, drop: CdkDropList<SdTableItem<T>[]>) => boolean;
    onReorderDrop(event: CdkDragDrop<SdTableItem<T>[]>): void;
    static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdTable<any>, never>;
    static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdTable<any>, "sd-table", never, { "autoIdInput": { "alias": "autoId"; "required": false; "isSignal": true; }; "option": { "alias": "option"; "required": true; "isSignal": true; }; }, {}, ["sdSubInformation", "sdGroupDef", "sdCellDefs", "sdFooterDefs", "sdFilterDefs", "sdTitleDefs"], ["[sdTableTop]"], true, never>;
}

export { MatPaginatorIntlCro, SD_TABLE_CONFIGURATION, SdConvertToPagingReq, SdMaterialFooterDefDirective, SdTable, SdTableCellDefDirective, SdTableExpandDefDirective, SdTableFilterDefDirective, SdTableGroupDefDirective, SdTableTitleDefDirective };
export type { ISdTableConfiguration, SdTableColumn, SdTableColumnChildren, SdTableColumnLazyValues, SdTableColumnNormal, SdTableColumnTransformFunc, SdTableColumnValues, SdTableCommand, SdTableCommandChildren, SdTableCommandNormal, SdTableCommandOption, SdTableDisplay, SdTableExternalFilter, SdTableFilterRequest, SdTableGroupDefContext, SdTableItem, SdTableMeta, SdTableOption, SdTableOptionFilter, SdTableOptionTree, SdTableQuickFilter, TableFilterConfiguration, TableFilterRegister, TableFilterValue, TableOptionTreeLazy, TableOptionTreeStatic };
