import type { SparklineConfig } from '../chart/sparkline/sparkline.types'; import type { ColumnGroupResizeStrategy } from '../column-groups/column-group.types'; import type { ColumnRenderer, DisplayRendererParams } from './renderer.types'; import type { AnyBuiltInRendererOptions } from './built-in-renderer.types'; import type { ValueGetterFn, ValueSetterFn, ValueFormatterFn } from './value.types'; import type { CellEditorParamsSpec, CellEditorSpec, EditableSpec } from '../editing/types/cell-editor.types'; import type { ColumnValidation } from '../editing/types/validation.types'; export type ColumnPinPosition = 'left' | 'right' | null; /** * Supported data types for a column. * * The type drives sorting, filtering, editing and export. It also picks the * column's **default renderer** when {@link ColumnDef.renderer} is not set — * see `DEFAULT_RENDERER_BY_TYPE`, which is the authoritative mapping. * * | Value | Default renderer | Cell rendering | * |--------------|------------------|-----------------------------------------| * | `string` | `text` | Plain text | * | `number` | `number` | Locale-formatted number | * | `boolean` | `checkbox` | Interactive checkbox | * | `date` | `date` | Formatted date | * | `datetime` | `datetime` | Formatted date + time | * | `time` | `time` | Formatted time | * | `duration` | `duration` | Elapsed time, e.g. `2h 15m` | * | `dropdown` | `badge` | Badge from `dropdownOptions` | * | `object` | `badge` | Badge resolved via `objectValueKey` | * | `array` | `list` | Tag badges (up to 3 visible) | * | `image` | `image` | `` thumbnail | * | `currency` | `currency` | Currency-formatted number | * | `percentage` | `percentage` | Percentage-formatted number | * | `email` | `email` | `mailto:` link | * | `phone` | `phone` | `tel:` link | * | `url` | `link` | Anchor | * | `sparkline` | `sparkline` | Mini chart — requires `ColumnDef.sparkline` | * | `custom` | `text` | Delegated to `renderer` | */ export type ColumnDataType = 'string' | 'number' | 'boolean' | 'date' | 'datetime' | 'time' | 'duration' | 'dropdown' | 'object' | 'array' | 'image' | 'currency' | 'percentage' | 'email' | 'phone' | 'url' | 'color' | 'sparkline' | 'custom'; export type ColumnSummaryAggregation = 'sum' | 'avg' | 'min' | 'max' | 'count' | 'none'; /** * Aggregation function applied to a column's values when rows are grouped. * * | Value | Description | * |---------|------------------------------------------| * | `sum` | Sum of all leaf row values | * | `avg` | True weighted average across leaf rows | * | `min` | Minimum leaf row value | * | `max` | Maximum leaf row value | * | `count` | Count of leaf rows with a finite value | * * Only honoured on columns whose {@link ColumnDef.type} is `'currency'` or `'number'`. */ export type AggFunc = 'sum' | 'avg' | 'min' | 'max' | 'count'; /** * Visibility strategy for a header action icon — the filter funnel and the * column-menu "⋯" button. * * Applied grid-wide via {@link HeaderIconsConfig}, and overridable per column * through {@link ColumnDef.filterIconDisplay} / {@link ColumnDef.menuIconDisplay}. */ export declare enum HeaderIconDisplay { /** * Icon stays hidden until the pointer hovers the header cell (or the icon is * otherwise activated — e.g. a column with an active filter always shows its * funnel). This is the classic "reveal on hover" behaviour; opt in when a * denser, quieter header is preferred over discoverability. */ HOVER = "hover", /** * Icon is permanently rendered, regardless of hover state. This is the * default — header actions stay discoverable without requiring a hover, and * the header layout does not shift as the pointer moves across columns. */ ALWAYS = "always", /** * Icon is never rendered. The underlying feature remains available through * other affordances (e.g. the filter row, or right-clicking the header for * the column menu) — only the header button is suppressed. Use this to hide * the filter funnel and/or the "⋯" menu icon entirely. */ HIDDEN = "hidden" } export interface ColumnDropdownOption { /** The stored value — must be unique within the option list. */ value: string | number; /** Display label shown in the dropdown and cell. */ label: string; /** Optional hex/css colour; used for badge background tint. */ color?: string; /** * Optional SVG string or HTML markup rendered as an icon before the label. * For emoji flags or inline SVG. Use `image` for URL-based images instead. */ icon?: string; /** * Optional URL or data-URI for an image rendered before the label. * Takes precedence over `icon` when both are provided. */ image?: string; } export interface ColumnDef { colId: string; field: string; header: string; type: ColumnDataType; /** * Derives this column's logical value from the raw row `data`, instead of * reading `data[field]` directly. The returned value is what every downstream * feature sees — cell rendering, sorting, filtering, grouping, aggregation and * export — so a single getter keeps the derived value consistent everywhere. * * Leave unset to read the field directly (dot-notation paths such as * `"address.city"` are supported out of the box). * * @example * ```ts * // Combine first + last name into a single "Full Name" column. * { * colId: 'fullName', field: 'fullName', header: 'Full Name', type: 'string', * valueGetter: ({ data }) => `${data.firstName ?? ''} ${data.lastName ?? ''}`.trim(), * } * ``` * * @remarks * Invoked once per cell per read on the hot render/sort path — keep it pure and * cheap (no I/O, no allocations in tight loops) to preserve scroll performance. * * @see {@link ValueGetterParams} */ valueGetter?: ValueGetterFn; /** * Commits an edited value back into the row `data`, instead of the grid's * default `data[field] = newValue` assignment. Use it to write derived, * nested or multi-field targets — for example splitting an edited full name * back into `firstName`/`lastName`. * * Mutate the provided `data` object and (optionally) return `false` to signal * that nothing effectively changed, which suppresses the change event and * refresh. Returning `true`/`undefined` applies the edit normally. * * Leave unset to write the field directly (dot-notation paths supported). * * @example * ```ts * { * colId: 'fullName', field: 'fullName', header: 'Full Name', type: 'string', * editable: true, * valueSetter: ({ data, newValue }) => { * const [first, ...rest] = String(newValue).trim().split(' '); * data.firstName = first ?? ''; * data.lastName = rest.join(' '); * return true; * }, * } * ``` * * @see {@link ValueSetterParams} */ valueSetter?: ValueSetterFn; /** * Formats this column's value into the string shown to the user. Applied to * the logical value ({@link valueGetter} output, or the raw field value) and * takes precedence over the grid's built-in type formatting for display. * * Presentation only: the formatted string is never used for sorting, * filtering or editing — those always operate on the underlying value. * * @example * ```ts * { * colId: 'salary', field: 'salary', header: 'Salary', type: 'number', * valueFormatter: ({ value }) => * value == null ? '—' : `$${Number(value).toLocaleString('en-US')}`, * } * ``` * * @see {@link ValueFormatterParams} */ valueFormatter?: ValueFormatterFn; width?: number; minWidth?: number; maxWidth?: number; flex?: number; pinned?: ColumnPinPosition; sortable?: boolean; /** * Whether the column participates in filtering. * * Two distinct effects, deliberately separated: * - **Capability** — filtering works unless this is `false`. The inline * filter row, the Filters tool panel and Photon AI all treat an omitted * value as filterable. * - **Header affordance** — the funnel icon is rendered only when this is * explicitly `true`. Leaving it unset keeps the header clean while the * column remains filterable through the filter row and tool panel. * * So: omit for "filterable, no icon", set `true` for "filterable, show the * funnel", set `false` to opt out of filtering entirely. */ filterable?: boolean; /** * Whether the column exposes its configuration menu button. * * The "⋯" button in the header is rendered only when this is `true`, so a * grid does not sprout a menu affordance on every column by default. The * menu's *contents* are controlled by {@link ColumnDef.menu} and * `GridOptions.columnMenu`, and right-click access is governed independently * by `ColumnMenuConfig.enableRightClick` — a column can therefore stay * right-clickable without showing the button. * * @default false */ configurable?: boolean; resizable?: boolean; draggable?: boolean; /** * Whether this column's cells can be edited. * * A predicate is evaluated per cell, so editability can depend on the row — * the usual reason being a status or permission field. * * Editing also requires `GridOptions.editing.mode` to be something other than * `'none'`, and is refused outright when {@link ColumnDef.locked} is `true`. * * @default false * * @example * ```ts * { field: 'discount', editable: ({ data }) => data.status === 'draft' } * ``` */ editable?: EditableSpec; /** * Which editor opens for this column's cells. * * Everything is optional: a column that sets only `editable: true` gets the * right editor for its {@link ColumnDef.type} automatically. Reach for this * when the default is not what you want. * * Accepts a built-in name, a key registered through `GridApi.registerEditor`, * an editor class or factory, or — with the matching framework wrapper * installed — an Angular / React / Vue component. * * Resolution order is: `editable` → this → registered key → the * {@link ColumnDef.type} default → the text editor. * * @example * ```ts * { field: 'status', editable: true, cellEditor: 'select' } * { field: 'currency', editable: true, cellEditor: CurrencyEditor } * { field: 'owner', editable: true, cellEditor: OwnerPickerComponent } * ``` */ cellEditor?: CellEditorSpec; /** * Configuration handed to the editor as `params.params`. * * The function form is evaluated per cell, so an option list can depend on the * row being edited. * * @example * ```ts * { field: 'score', editable: true, cellEditorParams: { min: 0, max: 100, step: 5 } } * ``` */ cellEditorParams?: CellEditorParamsSpec; /** * Declarative validation applied when an edit is committed. * * Rules run in a fixed order (emptiness before range, so a blank required * cell says "is required" rather than "must be at least 10") and apply * identically to built-in, custom, and framework editors — the grid owns * validation, not the editor. * * Some rules are implied by {@link ColumnDef.type}: an `email` column * validates as an email address with no configuration at all. * * @example * ```ts * { * field: 'price', type: 'number', editable: true, * validation: { * required: true, * min: 10, * validate: ({ value, data }) => * Number(value) > Number(data.cost) * ? { valid: true } * : { valid: false, message: 'Price must exceed cost' }, * }, * } * ``` */ validation?: ColumnValidation; /** * When `true`, the column is "locked": its cells cannot be edited regardless * of {@link ColumnDef.editable}. Toggled by the column menu's "Lock Column". */ locked?: boolean; /** * Opts this column into the Formula Engine. When `true`, a cell value typed * with a leading `=` (e.g. `=SUM(A1:A10)`) is stored as a formula: the editor * shows the formula source, while the cell displays the evaluated result and * `data[field]` holds the computed value. Typed columns (date/dropdown/number) * that leave this unset keep their normal editors and treat a leading `=` as * literal text. Requires `GridOptions.formula.enabled`. * * @default false */ allowFormula?: boolean; /** * Declares a formula applied to **every row** of this column, so the column's * cells compute automatically without any `GridApi.setCellFormula` call. The * formula is row-relative: references resolve against the row each cell lives * in. Both field-name syntax (`'=quantity * unitPrice'`) and spreadsheet * column-letter syntax (`'=B * C'`) are accepted and normalized internally. * * Precedence: a `=`-prefixed value embedded in a row's data overrides this * column formula for that row, and a later `GridApi.setCellFormula` overrides * both. Declaring `formula` implicitly opts the column into the Formula Engine * (sets {@link ColumnDef.allowFormula} to `true` unless explicitly `false`). * Requires `GridOptions.formula.enabled`. * * @example * { field: 'total', type: 'currency', formula: '=quantity * unitPrice' } */ formula?: string; groupable?: boolean; rowDrag?: boolean; alwaysVisible?: boolean; visible?: boolean; /** * Excludes this column from every export (CSV / JSON / Excel / PDF), whatever * its visibility. * * For columns that exist to drive the UI rather than to carry data — a row * handle, an internal key, a column of buttons. An explicit * {@link ExportOptions.columns} list still wins: naming a column *is* the * decision to export it. * * Columns rendered with the built-in `actions` renderer are excluded * automatically and need no flag. * * @default false */ suppressExport?: boolean; /** * Controls when this column's filter funnel icon appears in the header. * Only relevant while the column is filterable ({@link ColumnDef.filterable} * is not `false`). Overrides the grid-level {@link HeaderIconsConfig.filter} * default. * * @default HeaderIconDisplay.ALWAYS */ filterIconDisplay?: HeaderIconDisplay; /** * Controls when this column's column-menu "⋯" icon appears in the header. * Only relevant while the column menu is enabled for the grid. Overrides the * grid-level {@link HeaderIconsConfig.menu} default. * * @default HeaderIconDisplay.ALWAYS */ menuIconDisplay?: HeaderIconDisplay; renderHtml?: boolean; /** * Per-column overrides for the column header context menu — which sections and * items appear, items to suppress, and custom items to inject. Layered over the * grid-wide `GridOptions.columnMenu`: `sections`/`enableRightClick` from the * column win, `suppressItems` sets are unioned, and `customItems` are * concatenated (grid first) and de-duplicated by `id`. * * @see {@link import('./column-menu.types').ColumnMenuConfig} */ menu?: import('./column-menu.types').ColumnMenuConfig; /** * How this column's cells are drawn. * * Four forms, all optional — a column that sets none gets a renderer inferred * from its {@link ColumnDef.type}: * * ```ts * renderer: 'country' // built-in, by name * renderer: { name: 'progress', options: { max: 10 } } // built-in, configured * renderer: ({ value }) => `${value}` // custom display fn * renderer: { display: fn, editor: fn, filter: fn } // per-slot overrides * ``` * * The last form is the original API and is unchanged: any slot left unset * falls back to Photon Grid's built-in rendering for that concern. * * A built-in selected by name is configured through * {@link ColumnDef.rendererParams}. * * @see {@link ColumnRenderer} * @see {@link ColumnRendererMap} * @see {@link BuiltInRenderer} */ renderer?: ColumnRenderer; /** * Options for whichever built-in renderer this column uses. * * The flat alternative to the `{ name, options }` spec, and the form to reach * for when the renderer is named as a string — or not named at all, since * these apply just as well to the renderer inferred from * {@link ColumnDef.type}: * * ```ts * { field: 'employee', renderer: 'profile', rendererParams: { * avatar: { field: 'avatar', shape: 'circle', size: 36 }, * title: { field: 'name' }, * subtitle: { field: 'department' }, * } } * ``` * * Ignored by a column whose `renderer` is a function or a slot map — those * render through the author's own code, which takes its configuration from * the closure it was written in. * * When a column declares both this and a `{ name, options }` spec, `options` * wins key by key; nothing is silently dropped. * * @see {@link BuiltInRendererOptionsMap} for the options each renderer takes. */ rendererParams?: AnyBuiltInRendererOptions; dropdownOptions?: ColumnDropdownOption[]; enumOptions?: string[]; /** * For `object` type columns: the property name on the value object used to match * against `dropdownOptions[].value`. Defaults to `"value"` when omitted. */ objectValueKey?: string; /** * @deprecated Use `validation: { required: true }`. Still honoured — the * validation engine normalises it into the equivalent rule — but the * `validation` object is the documented home for every rule, and only it * supports messages, codes, async and cross-field checks. */ required?: boolean; /** * @deprecated Use `validation: { min }`. Still honoured. Note that * `cellEditorParams.min` is a separate, complementary thing: it constrains the * *input control*, while validation constrains the *value*. */ min?: number | null; /** @deprecated Use `validation: { max }`. Still honoured. See {@link ColumnDef.min}. */ max?: number | null; /** * @deprecated Use `validation: { validate }`, which returns a structured * {@link ValidationResult} instead of a bare message string and receives the * whole row rather than only the value. Still honoured; the engine adapts the * old signature. */ validatorFn?: (value: unknown) => string | null; showSummary?: boolean; summaryAggregation?: ColumnSummaryAggregation; summaryLabel?: string; /** * Aggregation function to apply when this column appears inside a group row. * Only honoured when {@link ColumnDef.type} is `'currency'` or `'number'`. * * @example * ```ts * { colId: 'salary', field: 'salary', type: 'currency', aggFunc: 'sum' } * ``` */ aggFunc?: AggFunc; isCurrency?: boolean; dateFormat?: string; textAlign?: 'left' | 'center' | 'right'; headerCssClass?: string; cellCssClass?: string | ((params: DisplayRendererParams) => string); /** * Child column definitions. When present, this `ColumnDef` acts as a * **column group** in the header rather than a data column. * * Groups can be nested to any depth — children may themselves have children. * The grid builds an `IColumnGroupNode` for each `ColumnDef` that has this * property, and renders a multi-row grouped header automatically. */ children?: ColumnDef[]; /** * When `true`, the group renders in its expanded state on first load. * Has no effect on leaf columns. * @default true */ openByDefault?: boolean; /** * When `true`, child columns cannot be dragged out of this group * individually. Dragging any child moves the whole group instead. * @default false */ marryChildren?: boolean; /** * Pixel width of the group header cell when the group is collapsed. * @default 26 */ collapsedWidth?: number; /** * Strategy used to distribute resize-delta pixels among sibling leaf columns * when the user resizes a group header. * @default ColumnGroupResizeStrategy.PROPORTIONAL */ groupResizeStrategy?: ColumnGroupResizeStrategy; /** * Custom renderer function for the group header cell. * When supplied, the default label + collapse-button markup is skipped. * * @example * ```ts * groupHeaderRendererFn: ({ group, collapsed }) => * `${group.header}${collapsed ? ' ▶' : ''}`, * ``` */ groupHeaderRendererFn?: (params: import('../column-groups/column-group.types').GroupHeaderRendererParams) => HTMLElement | string; /** * Sparkline configuration. * Only used when `type` is `'sparkline'`. * * The cell value must be a `number[]` or an `object[]`. For object arrays, * use `yKey` to specify the numeric property and `xKey` for the tooltip label. * * @example * ```ts * { * field: 'history', * type: 'sparkline', * sparkline: { type: 'line', stroke: '#2563eb', showMarkers: true }, * } * ``` * * @see {@link SparklineConfig} */ sparkline?: SparklineConfig; sortOrder?: 'asc' | 'desc' | null; filterActive?: boolean; } /** * A fully-normalized column as held internally by the grid after * {@link ColumnDef} defaults are applied. `colId`, `header` and `type` are * always present (defaulted from `field` / `'string'` when omitted on input), * so internal code never has to null-check them. Consumers reading columns from * the store or `ColumnModel` receive this type. */ export interface Column extends ColumnDef { colId: string; header: string; type: ColumnDataType; /** * The column this one sat immediately after when it was pinned, so unpinning * can put it back there. * * Pinning is a move — the column leaves its block and joins a panel's — which * means the position it came from is lost unless something remembers it. * Without this, unpinning dropped the column at the end of the unpinned block: * a user who pinned the third of twenty columns to glance at it got it back * as the twentieth. * * Holds `null` when the column was first in the order (nothing to sit after), * and `undefined` while the column is unpinned. Internal: set and cleared by * `ColumnModel`, never authored, and deliberately absent from * {@link ColumnState} — it describes an in-flight pin, not saved layout. */ unpinAnchorColId?: string | null; } /** * The public, author-friendly column definition. Only {@link ColumnDef.field} * is required; `colId`, `header` and `type` (and everything else) are optional * and filled in with defaults during normalization: * * - `colId` → `col__` * - `header` → the `field` rendered in Title Case * - `type` → `'string'` * * This is what `GridOptions.columns` and {@link GridApi.setColumns} accept. * Internally the grid works with the fully-normalized {@link ColumnDef}. */ export interface ColumnDefInput extends Omit { colId?: string; header?: string; type?: ColumnDataType; /** Nested child columns (also author-friendly). Presence makes this a group. */ children?: ColumnDefInput[]; } export interface ColumnState { colId: string; width: number; visible: boolean; pinned: ColumnPinPosition; sortOrder: 'asc' | 'desc' | null; index: number; } export interface ColumnGroup { groupId: string; header: string; children: ColumnDef[]; pinned?: ColumnPinPosition; } //# sourceMappingURL=column.types.d.ts.map