@ai-matrx/design-system 0.49.28 → 0.49.32

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.
@@ -75,6 +75,245 @@ declare function resolveTableSearchScopes<T>(rows: readonly T[], columns: readon
75
75
  * must implement the same contract at their source, never on a partial page. */
76
76
  declare function rankTableSearchRows<T>(rows: readonly T[], columns: readonly MatrxColumnDef<T>[], query: string, options?: TableRankedSearchOptions, extraText?: (row: T) => string): T[];
77
77
 
78
+ /**
79
+ * DRILL — the table primitive's four analytic abilities, as pure data (lane D3 of
80
+ * common-docs/projects/data-doctrine-adoption/v5/DRILL-DOWN-DESIGN.md).
81
+ *
82
+ * 1. GROUP BY A DIMENSION, answered by the SERVER — every group's count and measure subtotals
83
+ * are worked out over the whole table, never over the page the browser happens to hold.
84
+ * 2. PIVOT a second Dimension across the top (`across`).
85
+ * 3. WHAT TO DISPLAY — the Measures shown (`show`).
86
+ * 4. DRILL — a click on a group adds its value as a filter and regroups by the next Dimension
87
+ * of the drill path; the trail of filters is the breadcrumb, and every state is a URL.
88
+ *
89
+ * Vocabulary (Arman, 2026-09-29): "Dimension" and "Measure" are platform words; a saved
90
+ * exploration is a Saved view.
91
+ *
92
+ * THE TABLE ASKS, THE HOST ANSWERS. This file never reads a database. `drillRequests(question)`
93
+ * names every grouping the screen needs (one per level, one per level × the pivot, the pivot's
94
+ * own totals and the grand total); the host runs each through its door — today
95
+ * `custom.record_aggregate` for a custom Table, tomorrow the shared read door lanes D1/D2 build —
96
+ * and hands the rows back keyed by `request.key`. Because every number on the screen comes from
97
+ * one of those answers, a subtotal and the total can never disagree, and the rows a group holds
98
+ * beyond the door's group limit are said as ONE honest "N more" row (`otherOf`), never dropped.
99
+ */
100
+ /** A Dimension's kind — what it is made of, which decides what a click on one of its values means. */
101
+ type MatrxDrillDimensionKind = "choice" | "boolean" | "text" | "time" | "relation";
102
+ /** The periods a time Dimension is cut into. The store's own list (`custom.agg_buckets()`). */
103
+ type MatrxDrillGrain = "day" | "week" | "month" | "quarter" | "year";
104
+ declare const MATRX_DRILL_GRAINS: readonly MatrxDrillGrain[];
105
+ /** One axis a table can be cut by. */
106
+ interface MatrxDrillDimension {
107
+ /** The column or Field key. A time Dimension is referenced as `<key>:<grain>`. */
108
+ key: string;
109
+ label: string;
110
+ kind: MatrxDrillDimensionKind;
111
+ /** Time only: the grains offered. Default all five. */
112
+ grains?: readonly MatrxDrillGrain[] | undefined;
113
+ /** `high` → never offered as a pivot, because its columns would not fit a screen. */
114
+ cardinality?: "low" | "medium" | "high" | undefined;
115
+ /** How one of its values reads to a person (a choice's words, a person's name). Default: the value. */
116
+ labelFor?: ((value: string | null) => string) | undefined;
117
+ }
118
+ /** One number a table can show. */
119
+ interface MatrxDrillMeasure {
120
+ /** The key the host's answer carries it under (`count`, `sum_quantity`). */
121
+ key: string;
122
+ label: string;
123
+ /**
124
+ * May it be added up across groups? `count` and `sum` may; an average, a median, a min and a
125
+ * max may not — the "N more" row leaves those blank rather than inventing them.
126
+ */
127
+ additive: boolean;
128
+ /** How the cell prints. Default: a plain number. */
129
+ format?: ((value: number | null) => string) | undefined;
130
+ }
131
+ /** One step of the breadcrumb: a Dimension reference and the value it was narrowed to. */
132
+ interface MatrxDrillFilter {
133
+ /** A Dimension reference (`status`, `last_serviced:month`). */
134
+ dim: string;
135
+ /** The value, as the answer carried it. `null` is "no value". */
136
+ value: string | null;
137
+ }
138
+ /** THE QUESTION — what a Saved view stores and the address encodes. */
139
+ interface MatrxDrillQuestion {
140
+ /** Row groups, outermost first (at most three, the store's own limit). Empty = the records. */
141
+ by: string[];
142
+ /** One pivot Dimension drawn across the top. */
143
+ across?: string | null | undefined;
144
+ /** The Measures shown, in column order. */
145
+ show: string[];
146
+ /** The drill trail, in order. Each crumb removes the filters after it. */
147
+ where: MatrxDrillFilter[];
148
+ /** The drill path a click follows (Dimension references). Default: the Dimensions in order. */
149
+ path?: string[] | null | undefined;
150
+ /** A Measure key (or `label`) and a direction; default the answer's own order (largest first). */
151
+ sort?: {
152
+ key: string;
153
+ direction: "asc" | "desc";
154
+ } | null | undefined;
155
+ }
156
+ /** One grouped row of an answer, exactly as the store's aggregate door returns it. */
157
+ interface MatrxDrillAnswerRow {
158
+ /** Keyed by Dimension reference. */
159
+ groups: Record<string, string | null>;
160
+ measures: Record<string, number | null>;
161
+ row_count: number;
162
+ }
163
+ /** One grouping the table needs answered. */
164
+ interface MatrxDrillRequest {
165
+ /** Stable key the host answers under. */
166
+ key: string;
167
+ /** Dimension references to group by, outermost first; empty = the grand total. */
168
+ by: string[];
169
+ }
170
+ /** What the host hands back: rows per request key; a key not yet present is still loading. */
171
+ type MatrxDrillAnswers = Readonly<Record<string, readonly MatrxDrillAnswerRow[] | undefined>>;
172
+ /** The store's own ceiling on levels (`custom.view_declare`). */
173
+ declare const MATRX_DRILL_MAX_LEVELS = 3;
174
+ /** Pivot columns before an "Other" column (knob default in the design). */
175
+ declare const MATRX_DRILL_PIVOT_COLUMNS = 24;
176
+ /** `last_serviced:month` → `{ key: "last_serviced", grain: "month" }`. */
177
+ declare function parseDimensionRef(ref: string): {
178
+ key: string;
179
+ grain: MatrxDrillGrain | null;
180
+ };
181
+ declare function dimensionFor(dimensions: readonly MatrxDrillDimension[], ref: string): MatrxDrillDimension | undefined;
182
+ /** "Last serviced by month", "Condition". */
183
+ declare function dimensionRefLabel(dimensions: readonly MatrxDrillDimension[], ref: string): string;
184
+ /** The references a person may group by: each Dimension, and each time Dimension at each grain. */
185
+ declare function dimensionRefs(dimensions: readonly MatrxDrillDimension[]): string[];
186
+ /** How one group value reads. A blank is said, never shown as an empty cell. */
187
+ declare function drillValueLabel(dimensions: readonly MatrxDrillDimension[], ref: string, value: string | null, emptyLabel?: string): string;
188
+ /** A bucket start printed for its grain: "Sep 2026", "Q3 2026", "2026", "Week of Sep 7, 2026". */
189
+ declare function bucketLabel(value: string, grain: MatrxDrillGrain): string;
190
+ /**
191
+ * THE HALF-OPEN WINDOW a bucket value stands for — what a click on "Sep 2026" filters to. The
192
+ * start keeps whatever offset the store cut it with; the end is the next bucket's start in the
193
+ * same offset, so the window and the bucket are one period.
194
+ */
195
+ declare function bucketWindow(value: string, grain: MatrxDrillGrain): {
196
+ from: string;
197
+ to: string;
198
+ };
199
+ declare function emptyDrillQuestion(show?: string[]): MatrxDrillQuestion;
200
+ /** Is the table answering a grouped question (summary rows) rather than listing records? */
201
+ declare function drillIsGrouped(question: MatrxDrillQuestion): boolean;
202
+ /** The drill path: the question's own, else every Dimension reference in the order declared (time at month). */
203
+ declare function drillPath(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[]): string[];
204
+ /**
205
+ * The Dimension a drill on the deepest level regroups by: the next step of the path after the
206
+ * deepest level, skipping anything already filtered or grouped. `null` = the path is spent, so
207
+ * the drill shows the records themselves.
208
+ */
209
+ declare function nextDrillLevel(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[]): string | null;
210
+ /**
211
+ * DRILL INTO A GROUP (Metabase's default click). Every level of the clicked row becomes a
212
+ * filter, in order, and the table regroups by `into` — the next Dimension of the path when not
213
+ * named ("Drill into"), any Dimension when named ("Break out by"). `into === null` with nothing
214
+ * left in the path lists the group's records.
215
+ */
216
+ declare function drillInto(question: MatrxDrillQuestion, groups: Record<string, string | null>, dimensions: readonly MatrxDrillDimension[], into?: string | null): MatrxDrillQuestion;
217
+ /** "See these records": the group's filters, and no grouping — the records themselves. */
218
+ declare function drillToRecords(question: MatrxDrillQuestion, groups: Record<string, string | null>): MatrxDrillQuestion;
219
+ /** One crumb of the trail. `index` -1 is the root ("All records"). */
220
+ interface MatrxDrillCrumb {
221
+ index: number;
222
+ label: string;
223
+ /** The Dimension that was filtered at this step, and its value's words. */
224
+ dimLabel?: string;
225
+ valueLabel?: string;
226
+ }
227
+ declare function drillCrumbs(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[], rootLabel: string, emptyLabel?: string): MatrxDrillCrumb[];
228
+ /**
229
+ * ZOOM BACK OUT to a crumb: the filters up to and including it stay; the table regroups by the
230
+ * Dimension that was filtered NEXT, so the person sees the level they drilled out of — Power BI's
231
+ * drill-up, one crumb at a time or straight to any crumb.
232
+ */
233
+ declare function zoomOutTo(question: MatrxDrillQuestion, index: number): MatrxDrillQuestion;
234
+ declare function drillRequestKey(by: readonly string[]): string;
235
+ /**
236
+ * EVERY GROUPING THE SCREEN NEEDS, and nothing it does not: the grand total; each level's
237
+ * prefix of `by` (so an outer group's average is the store's average, never an average of
238
+ * averages); and, with a pivot, each of those crossed with `across` plus `across` alone for the
239
+ * column totals. At most eight calls for the deepest pivot.
240
+ */
241
+ declare function drillRequests(question: MatrxDrillQuestion): MatrxDrillRequest[];
242
+ interface MatrxDrillNode {
243
+ /** Stable across re-reads: the path of values from the outermost level. */
244
+ key: string;
245
+ level: number;
246
+ /** Dimension reference → value, for this level and every level above it. */
247
+ groups: Record<string, string | null>;
248
+ row: MatrxDrillAnswerRow;
249
+ children: MatrxDrillNode[];
250
+ /** What the store's group limit left out under this node (or at the top), said as one row. */
251
+ other: MatrxDrillOther | null;
252
+ }
253
+ /** THE REST — what a group limit left out, so the page always adds up to its total. */
254
+ interface MatrxDrillOther {
255
+ row_count: number;
256
+ /** Only additive measures; a non-additive one is `null` (left blank, not invented). */
257
+ measures: Record<string, number | null>;
258
+ }
259
+ /**
260
+ * THE REST, worked out from the parent's own total: the parent's rows minus the rows its shown
261
+ * children hold. Non-additive measures cannot be subtracted and stay blank. `null` when nothing
262
+ * is left over — the common case, and then no row is drawn.
263
+ */
264
+ declare function otherOf(parent: MatrxDrillAnswerRow | undefined, children: readonly MatrxDrillAnswerRow[], measures: readonly MatrxDrillMeasure[]): MatrxDrillOther | null;
265
+ /**
266
+ * THE TREE a grouped answer draws: level 0 from the request for `by[0]`, each deeper level from
267
+ * the request for its prefix, children matched to their parent by the parent's values. `null`
268
+ * while any level is still unanswered.
269
+ */
270
+ declare function buildDrillTree(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, measures: readonly MatrxDrillMeasure[]): {
271
+ nodes: MatrxDrillNode[];
272
+ total: MatrxDrillAnswerRow | null;
273
+ other: MatrxDrillOther | null;
274
+ } | null;
275
+ interface MatrxDrillPivotColumn {
276
+ /** `null` is the "no value" column; `OTHER` is everything past the cap. */
277
+ value: string | null;
278
+ other?: boolean;
279
+ label: string;
280
+ total: MatrxDrillAnswerRow;
281
+ }
282
+ declare const MATRX_DRILL_OTHER_COLUMN = "\0other";
283
+ /**
284
+ * THE COLUMNS a pivot draws: the `across` values largest first (the store's order), capped, and
285
+ * ONE "Other" column holding the rest, so the columns always add up to the row total. `null`
286
+ * while the pivot's own totals are unanswered.
287
+ */
288
+ declare function pivotColumns(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, dimensions: readonly MatrxDrillDimension[], measures: readonly MatrxDrillMeasure[], cap?: number): MatrxDrillPivotColumn[] | null;
289
+ /**
290
+ * One pivot cell: the row's values crossed with one column. The "Other" column is the rest of the
291
+ * row — the row's own total minus the capped columns — for additive measures only.
292
+ */
293
+ declare function pivotCell(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, node: Pick<MatrxDrillNode, "level" | "groups" | "row">, column: MatrxDrillPivotColumn, columns: readonly MatrxDrillPivotColumn[], measure: MatrxDrillMeasure): number | null;
294
+ /** "(none)" is the address's word for a blank value (the design's URL grammar, f.4). */
295
+ declare const MATRX_DRILL_NONE = "(none)";
296
+ /**
297
+ * Does the address carry a drill QUESTION? `sort` and `path` only refine one — and other screens
298
+ * write a bare `sort` of their own (`?sort=title.asc`) — so they never, alone, override a Saved
299
+ * view's question.
300
+ */
301
+ declare function addressHasDrill(params: URLSearchParams, prefix?: string): boolean;
302
+ /**
303
+ * THE ADDRESS → THE QUESTION. `?by=condition,room&across=last_serviced:month&show=count,sum_quantity
304
+ * &f.condition=Needs%20repair&sort=-sum_quantity&path=condition,room`. The `f.` filters are read
305
+ * in the order the address holds them — that order IS the breadcrumb.
306
+ */
307
+ declare function drillQuestionFromParams(params: URLSearchParams, fallback: MatrxDrillQuestion, prefix?: string): MatrxDrillQuestion;
308
+ /**
309
+ * THE QUESTION → AN ADDRESS PATCH for `commitUrlParams`: every drill key set or cleared, and every
310
+ * `f.` filter the address holds today cleared unless the question keeps it. `f.` keys are written
311
+ * in the trail's order.
312
+ */
313
+ declare function drillQuestionToParams(question: MatrxDrillQuestion, current: URLSearchParams, prefix?: string): Record<string, string | null>;
314
+ /** Two questions ask the same thing (the address and a Saved view agree). */
315
+ declare function sameDrillQuestion(a: MatrxDrillQuestion, b: MatrxDrillQuestion): boolean;
316
+
78
317
  /** How a column's filter UI behaves. `auto` infers from sample values. */
79
318
  type ColumnFilterKind = "auto" | "text" | "select" | "boolean" | "number" | "date" | false;
80
319
  type SortDirection = "asc" | "desc";
@@ -1221,6 +1460,35 @@ interface MatrxDataTableGroupingConfig<T> {
1221
1460
  */
1222
1461
  readCell?: ((row: T, columnId: string) => unknown) | undefined;
1223
1462
  }
1463
+ /**
1464
+ * DRILL — group by a Dimension with SERVER-computed groups, pivot a second Dimension across the
1465
+ * top, pick the Measures shown, and drill on a group (lane D3; `./drill.ts` is the whole model).
1466
+ *
1467
+ * CONTROLLED like `grouping`: the question is the consumer's (it lives in the address and saves
1468
+ * as a Saved view), the table only asks for it to change. THE TABLE ASKS, THE HOST ANSWERS:
1469
+ * `drillRequests(question)` names each grouping the screen needs and the host puts each door's
1470
+ * rows into `answers` under the request's key. While `question.by` is empty the table lists its
1471
+ * records as always (narrowed by the host to `question.where`), and the trail stays in the
1472
+ * toolbar so a person can zoom back out.
1473
+ *
1474
+ * With `drill` the toolbar's group-by control groups by Dimensions on the server; the
1475
+ * page-scoped `grouping` is not drawn at the same time.
1476
+ */
1477
+ interface MatrxDataTableDrillConfig {
1478
+ dimensions: readonly MatrxDrillDimension[];
1479
+ measures: readonly MatrxDrillMeasure[];
1480
+ question: MatrxDrillQuestion;
1481
+ onQuestionChange: (next: MatrxDrillQuestion) => void;
1482
+ answers: MatrxDrillAnswers;
1483
+ /** A read that failed, in words the person can act on. */
1484
+ error?: string | null | undefined;
1485
+ /** The trail's first crumb. Default "All records". */
1486
+ rootLabel?: string | undefined;
1487
+ /** Singular noun ("record" → "12 records"). */
1488
+ rowNoun?: string | undefined;
1489
+ /** How a blank group reads. Default "No value". */
1490
+ emptyLabel?: string | undefined;
1491
+ }
1224
1492
  /**
1225
1493
  * VIRTUALIZATION — render the rows a person can actually see.
1226
1494
  *
@@ -1608,6 +1876,11 @@ interface MatrxDataTableProps<T> {
1608
1876
  * subtotals on each header. Opt-in and controlled; see the config's own doc.
1609
1877
  */
1610
1878
  grouping?: MatrxDataTableGroupingConfig<T>;
1879
+ /**
1880
+ * DRILL — server-computed groups, a pivot, a measure picker and drill-on-a-group, with the
1881
+ * breadcrumb in the toolbar. Controlled; see the config's own doc.
1882
+ */
1883
+ drill?: MatrxDataTableDrillConfig | undefined;
1611
1884
  /** Render only the rows in view. Opt-in; engages past its own threshold. */
1612
1885
  virtualize?: boolean | MatrxDataTableVirtualizeConfig;
1613
1886
  /**
@@ -1769,4 +2042,4 @@ declare function columnFiltersToLayeredRules(filters: ColumnFiltersState, fieldI
1769
2042
  declare function layeredFilterMatchesValue(value: unknown, rule: LayeredFilterRule): boolean;
1770
2043
  declare function layeredFilterRuleSummary(rule: LayeredFilterRule, fields: readonly LayeredFilterField[]): string;
1771
2044
 
1772
- export { type TableSearchScope as $, type AnyOfColumnSearch as A, type MatrxDataTableQueryControl as B, type ColumnFiltersState as C, type MatrxDataTableReadStatus as D, type MatrxDataTableSelectionConfig as E, type MatrxDataTableSingleExpandedDetailConfig as F, type MatrxDataTableSourceProcessing as G, type MatrxDataTableSpreadsheetConfig as H, type MatrxDataTableStyleConfig as I, type MatrxDataTableSummaryConfig as J, type MatrxDataTableSummaryContext as K, type LayeredFilterRule as L, type MatrxColumnDef as M, type MatrxDataTableSummaryMetric as N, type MatrxDataTableToolbar as O, type MatrxDataTableUrlStateConfig as P, type MatrxDataTableVirtualizeConfig as Q, type MatrxDataTableWindowConfig as R, type SortState as S, type TableSearchMatchMode as T, type MatrxTablePagination as U, type NumberFilterOp as V, type SavedTableViewTab as W, type SortDirection as X, type SpreadsheetSelection as Y, type TableRankedSearchOptions as Z, type TableSearchRole as _, type ColumnFilterValue as a, type TableViewQuery as a0, type TableViewTab as a1, TableViewTabs as a2, type TableViewTabsProps as a3, type TableViewTabsStore as a4, type TextFilterMode as a5, type ToolbarFacet as a6, inferTableSearchRole as a7, rankTableSearchRows as a8, resolveTableSearchScopes as a9, LAYERED_FILTER_OPERATORS as aa, LAYERED_FILTER_OPERATOR_LABELS as ab, type LayeredFilterField as ac, type LayeredFilterOperator as ad, columnFiltersToLayeredRules as ae, completeLayeredFilterRules as af, decodeLayeredFilterRules as ag, encodeLayeredFilterRules as ah, isCompleteLayeredFilterRule as ai, isLayeredFilterOperator as aj, layeredFilterMatchesValue as ak, layeredFilterNeedsValue as al, layeredFilterRuleSummary as am, operatorsForLayeredField as an, type TableSavedViewsProps as b, type MatrxDataTableDensity as c, type MatrxDataTableRecordControls as d, type MatrxDataTableQueryState as e, type ColumnFilterKind as f, type MatrxDataTableCopyConfig as g, type MatrxDataTableProps as h, type TableViewSnapshot as i, type MatrxDataTableRead as j, type ColumnMarker as k, type CellEditType as l, type CellEditsMap as m, type MatrxDataTableContextMenuConfig as n, type MatrxDataTableCoverageConfig as o, type MatrxDataTableDetailConfig as p, type MatrxDataTableEditConfig as q, type MatrxDataTableEmptyState as r, type MatrxDataTableExpandedDetailConfig as s, type MatrxDataTableFacetsConfig as t, type MatrxDataTableFilterUi as u, type MatrxDataTableGroupingConfig as v, type MatrxDataTableHierarchyConfig as w, type MatrxDataTableHierarchyMove as x, type MatrxDataTableMobileCardControls as y, type MatrxDataTableMultiExpandedDetailConfig as z };
2045
+ export { type MatrxDataTableUrlStateConfig as $, type AnyOfColumnSearch as A, type MatrxDataTableEditConfig as B, type ColumnFiltersState as C, type MatrxDataTableEmptyState as D, type MatrxDataTableExpandedDetailConfig as E, type MatrxDataTableFacetsConfig as F, type MatrxDataTableFilterUi as G, type MatrxDataTableGroupingConfig as H, type MatrxDataTableHierarchyConfig as I, type MatrxDataTableHierarchyMove as J, type MatrxDataTableMobileCardControls as K, type LayeredFilterRule as L, type MatrxColumnDef as M, type MatrxDataTableMultiExpandedDetailConfig as N, type MatrxDataTableQueryControl as O, type MatrxDataTableReadStatus as P, type MatrxDataTableSelectionConfig as Q, type MatrxDataTableSingleExpandedDetailConfig as R, type SortState as S, type TableSearchMatchMode as T, type MatrxDataTableSourceProcessing as U, type MatrxDataTableSpreadsheetConfig as V, type MatrxDataTableStyleConfig as W, type MatrxDataTableSummaryConfig as X, type MatrxDataTableSummaryContext as Y, type MatrxDataTableSummaryMetric as Z, type MatrxDataTableToolbar as _, type ColumnFilterValue as a, isLayeredFilterOperator as a$, type MatrxDataTableVirtualizeConfig as a0, type MatrxDataTableWindowConfig as a1, type MatrxDrillAnswerRow as a2, type MatrxDrillCrumb as a3, type MatrxDrillDimensionKind as a4, type MatrxDrillFilter as a5, type MatrxDrillGrain as a6, type MatrxDrillNode as a7, type MatrxDrillOther as a8, type MatrxDrillPivotColumn as a9, drillPath as aA, drillQuestionFromParams as aB, drillQuestionToParams as aC, drillRequestKey as aD, drillRequests as aE, drillToRecords as aF, drillValueLabel as aG, emptyDrillQuestion as aH, inferTableSearchRole as aI, nextDrillLevel as aJ, otherOf as aK, parseDimensionRef as aL, pivotCell as aM, pivotColumns as aN, rankTableSearchRows as aO, resolveTableSearchScopes as aP, sameDrillQuestion as aQ, zoomOutTo as aR, LAYERED_FILTER_OPERATORS as aS, LAYERED_FILTER_OPERATOR_LABELS as aT, type LayeredFilterField as aU, type LayeredFilterOperator as aV, columnFiltersToLayeredRules as aW, completeLayeredFilterRules as aX, decodeLayeredFilterRules as aY, encodeLayeredFilterRules as aZ, isCompleteLayeredFilterRule as a_, type MatrxDrillRequest as aa, type MatrxTablePagination as ab, type NumberFilterOp as ac, type SavedTableViewTab as ad, type SortDirection as ae, type SpreadsheetSelection as af, type TableRankedSearchOptions as ag, type TableSearchRole as ah, type TableSearchScope as ai, type TableViewQuery as aj, type TableViewTab as ak, TableViewTabs as al, type TableViewTabsProps as am, type TableViewTabsStore as an, type TextFilterMode as ao, type ToolbarFacet as ap, addressHasDrill as aq, bucketLabel as ar, bucketWindow as as, buildDrillTree as at, dimensionFor as au, dimensionRefLabel as av, dimensionRefs as aw, drillCrumbs as ax, drillInto as ay, drillIsGrouped as az, type TableSavedViewsProps as b, layeredFilterMatchesValue as b0, layeredFilterNeedsValue as b1, layeredFilterRuleSummary as b2, operatorsForLayeredField as b3, type MatrxDataTableDensity as c, type MatrxDataTableRecordControls as d, type MatrxDataTableQueryState as e, type ColumnFilterKind as f, type MatrxDataTableCopyConfig as g, type MatrxDataTableProps as h, type TableViewSnapshot as i, type MatrxDataTableRead as j, type ColumnMarker as k, type MatrxDrillDimension as l, type MatrxDrillMeasure as m, type MatrxDrillQuestion as n, type MatrxDrillAnswers as o, type CellEditType as p, type CellEditsMap as q, MATRX_DRILL_GRAINS as r, MATRX_DRILL_MAX_LEVELS as s, MATRX_DRILL_NONE as t, MATRX_DRILL_OTHER_COLUMN as u, MATRX_DRILL_PIVOT_COLUMNS as v, type MatrxDataTableContextMenuConfig as w, type MatrxDataTableCoverageConfig as x, type MatrxDataTableDetailConfig as y, type MatrxDataTableDrillConfig as z };
@@ -75,6 +75,245 @@ declare function resolveTableSearchScopes<T>(rows: readonly T[], columns: readon
75
75
  * must implement the same contract at their source, never on a partial page. */
76
76
  declare function rankTableSearchRows<T>(rows: readonly T[], columns: readonly MatrxColumnDef<T>[], query: string, options?: TableRankedSearchOptions, extraText?: (row: T) => string): T[];
77
77
 
78
+ /**
79
+ * DRILL — the table primitive's four analytic abilities, as pure data (lane D3 of
80
+ * common-docs/projects/data-doctrine-adoption/v5/DRILL-DOWN-DESIGN.md).
81
+ *
82
+ * 1. GROUP BY A DIMENSION, answered by the SERVER — every group's count and measure subtotals
83
+ * are worked out over the whole table, never over the page the browser happens to hold.
84
+ * 2. PIVOT a second Dimension across the top (`across`).
85
+ * 3. WHAT TO DISPLAY — the Measures shown (`show`).
86
+ * 4. DRILL — a click on a group adds its value as a filter and regroups by the next Dimension
87
+ * of the drill path; the trail of filters is the breadcrumb, and every state is a URL.
88
+ *
89
+ * Vocabulary (Arman, 2026-09-29): "Dimension" and "Measure" are platform words; a saved
90
+ * exploration is a Saved view.
91
+ *
92
+ * THE TABLE ASKS, THE HOST ANSWERS. This file never reads a database. `drillRequests(question)`
93
+ * names every grouping the screen needs (one per level, one per level × the pivot, the pivot's
94
+ * own totals and the grand total); the host runs each through its door — today
95
+ * `custom.record_aggregate` for a custom Table, tomorrow the shared read door lanes D1/D2 build —
96
+ * and hands the rows back keyed by `request.key`. Because every number on the screen comes from
97
+ * one of those answers, a subtotal and the total can never disagree, and the rows a group holds
98
+ * beyond the door's group limit are said as ONE honest "N more" row (`otherOf`), never dropped.
99
+ */
100
+ /** A Dimension's kind — what it is made of, which decides what a click on one of its values means. */
101
+ type MatrxDrillDimensionKind = "choice" | "boolean" | "text" | "time" | "relation";
102
+ /** The periods a time Dimension is cut into. The store's own list (`custom.agg_buckets()`). */
103
+ type MatrxDrillGrain = "day" | "week" | "month" | "quarter" | "year";
104
+ declare const MATRX_DRILL_GRAINS: readonly MatrxDrillGrain[];
105
+ /** One axis a table can be cut by. */
106
+ interface MatrxDrillDimension {
107
+ /** The column or Field key. A time Dimension is referenced as `<key>:<grain>`. */
108
+ key: string;
109
+ label: string;
110
+ kind: MatrxDrillDimensionKind;
111
+ /** Time only: the grains offered. Default all five. */
112
+ grains?: readonly MatrxDrillGrain[] | undefined;
113
+ /** `high` → never offered as a pivot, because its columns would not fit a screen. */
114
+ cardinality?: "low" | "medium" | "high" | undefined;
115
+ /** How one of its values reads to a person (a choice's words, a person's name). Default: the value. */
116
+ labelFor?: ((value: string | null) => string) | undefined;
117
+ }
118
+ /** One number a table can show. */
119
+ interface MatrxDrillMeasure {
120
+ /** The key the host's answer carries it under (`count`, `sum_quantity`). */
121
+ key: string;
122
+ label: string;
123
+ /**
124
+ * May it be added up across groups? `count` and `sum` may; an average, a median, a min and a
125
+ * max may not — the "N more" row leaves those blank rather than inventing them.
126
+ */
127
+ additive: boolean;
128
+ /** How the cell prints. Default: a plain number. */
129
+ format?: ((value: number | null) => string) | undefined;
130
+ }
131
+ /** One step of the breadcrumb: a Dimension reference and the value it was narrowed to. */
132
+ interface MatrxDrillFilter {
133
+ /** A Dimension reference (`status`, `last_serviced:month`). */
134
+ dim: string;
135
+ /** The value, as the answer carried it. `null` is "no value". */
136
+ value: string | null;
137
+ }
138
+ /** THE QUESTION — what a Saved view stores and the address encodes. */
139
+ interface MatrxDrillQuestion {
140
+ /** Row groups, outermost first (at most three, the store's own limit). Empty = the records. */
141
+ by: string[];
142
+ /** One pivot Dimension drawn across the top. */
143
+ across?: string | null | undefined;
144
+ /** The Measures shown, in column order. */
145
+ show: string[];
146
+ /** The drill trail, in order. Each crumb removes the filters after it. */
147
+ where: MatrxDrillFilter[];
148
+ /** The drill path a click follows (Dimension references). Default: the Dimensions in order. */
149
+ path?: string[] | null | undefined;
150
+ /** A Measure key (or `label`) and a direction; default the answer's own order (largest first). */
151
+ sort?: {
152
+ key: string;
153
+ direction: "asc" | "desc";
154
+ } | null | undefined;
155
+ }
156
+ /** One grouped row of an answer, exactly as the store's aggregate door returns it. */
157
+ interface MatrxDrillAnswerRow {
158
+ /** Keyed by Dimension reference. */
159
+ groups: Record<string, string | null>;
160
+ measures: Record<string, number | null>;
161
+ row_count: number;
162
+ }
163
+ /** One grouping the table needs answered. */
164
+ interface MatrxDrillRequest {
165
+ /** Stable key the host answers under. */
166
+ key: string;
167
+ /** Dimension references to group by, outermost first; empty = the grand total. */
168
+ by: string[];
169
+ }
170
+ /** What the host hands back: rows per request key; a key not yet present is still loading. */
171
+ type MatrxDrillAnswers = Readonly<Record<string, readonly MatrxDrillAnswerRow[] | undefined>>;
172
+ /** The store's own ceiling on levels (`custom.view_declare`). */
173
+ declare const MATRX_DRILL_MAX_LEVELS = 3;
174
+ /** Pivot columns before an "Other" column (knob default in the design). */
175
+ declare const MATRX_DRILL_PIVOT_COLUMNS = 24;
176
+ /** `last_serviced:month` → `{ key: "last_serviced", grain: "month" }`. */
177
+ declare function parseDimensionRef(ref: string): {
178
+ key: string;
179
+ grain: MatrxDrillGrain | null;
180
+ };
181
+ declare function dimensionFor(dimensions: readonly MatrxDrillDimension[], ref: string): MatrxDrillDimension | undefined;
182
+ /** "Last serviced by month", "Condition". */
183
+ declare function dimensionRefLabel(dimensions: readonly MatrxDrillDimension[], ref: string): string;
184
+ /** The references a person may group by: each Dimension, and each time Dimension at each grain. */
185
+ declare function dimensionRefs(dimensions: readonly MatrxDrillDimension[]): string[];
186
+ /** How one group value reads. A blank is said, never shown as an empty cell. */
187
+ declare function drillValueLabel(dimensions: readonly MatrxDrillDimension[], ref: string, value: string | null, emptyLabel?: string): string;
188
+ /** A bucket start printed for its grain: "Sep 2026", "Q3 2026", "2026", "Week of Sep 7, 2026". */
189
+ declare function bucketLabel(value: string, grain: MatrxDrillGrain): string;
190
+ /**
191
+ * THE HALF-OPEN WINDOW a bucket value stands for — what a click on "Sep 2026" filters to. The
192
+ * start keeps whatever offset the store cut it with; the end is the next bucket's start in the
193
+ * same offset, so the window and the bucket are one period.
194
+ */
195
+ declare function bucketWindow(value: string, grain: MatrxDrillGrain): {
196
+ from: string;
197
+ to: string;
198
+ };
199
+ declare function emptyDrillQuestion(show?: string[]): MatrxDrillQuestion;
200
+ /** Is the table answering a grouped question (summary rows) rather than listing records? */
201
+ declare function drillIsGrouped(question: MatrxDrillQuestion): boolean;
202
+ /** The drill path: the question's own, else every Dimension reference in the order declared (time at month). */
203
+ declare function drillPath(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[]): string[];
204
+ /**
205
+ * The Dimension a drill on the deepest level regroups by: the next step of the path after the
206
+ * deepest level, skipping anything already filtered or grouped. `null` = the path is spent, so
207
+ * the drill shows the records themselves.
208
+ */
209
+ declare function nextDrillLevel(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[]): string | null;
210
+ /**
211
+ * DRILL INTO A GROUP (Metabase's default click). Every level of the clicked row becomes a
212
+ * filter, in order, and the table regroups by `into` — the next Dimension of the path when not
213
+ * named ("Drill into"), any Dimension when named ("Break out by"). `into === null` with nothing
214
+ * left in the path lists the group's records.
215
+ */
216
+ declare function drillInto(question: MatrxDrillQuestion, groups: Record<string, string | null>, dimensions: readonly MatrxDrillDimension[], into?: string | null): MatrxDrillQuestion;
217
+ /** "See these records": the group's filters, and no grouping — the records themselves. */
218
+ declare function drillToRecords(question: MatrxDrillQuestion, groups: Record<string, string | null>): MatrxDrillQuestion;
219
+ /** One crumb of the trail. `index` -1 is the root ("All records"). */
220
+ interface MatrxDrillCrumb {
221
+ index: number;
222
+ label: string;
223
+ /** The Dimension that was filtered at this step, and its value's words. */
224
+ dimLabel?: string;
225
+ valueLabel?: string;
226
+ }
227
+ declare function drillCrumbs(question: MatrxDrillQuestion, dimensions: readonly MatrxDrillDimension[], rootLabel: string, emptyLabel?: string): MatrxDrillCrumb[];
228
+ /**
229
+ * ZOOM BACK OUT to a crumb: the filters up to and including it stay; the table regroups by the
230
+ * Dimension that was filtered NEXT, so the person sees the level they drilled out of — Power BI's
231
+ * drill-up, one crumb at a time or straight to any crumb.
232
+ */
233
+ declare function zoomOutTo(question: MatrxDrillQuestion, index: number): MatrxDrillQuestion;
234
+ declare function drillRequestKey(by: readonly string[]): string;
235
+ /**
236
+ * EVERY GROUPING THE SCREEN NEEDS, and nothing it does not: the grand total; each level's
237
+ * prefix of `by` (so an outer group's average is the store's average, never an average of
238
+ * averages); and, with a pivot, each of those crossed with `across` plus `across` alone for the
239
+ * column totals. At most eight calls for the deepest pivot.
240
+ */
241
+ declare function drillRequests(question: MatrxDrillQuestion): MatrxDrillRequest[];
242
+ interface MatrxDrillNode {
243
+ /** Stable across re-reads: the path of values from the outermost level. */
244
+ key: string;
245
+ level: number;
246
+ /** Dimension reference → value, for this level and every level above it. */
247
+ groups: Record<string, string | null>;
248
+ row: MatrxDrillAnswerRow;
249
+ children: MatrxDrillNode[];
250
+ /** What the store's group limit left out under this node (or at the top), said as one row. */
251
+ other: MatrxDrillOther | null;
252
+ }
253
+ /** THE REST — what a group limit left out, so the page always adds up to its total. */
254
+ interface MatrxDrillOther {
255
+ row_count: number;
256
+ /** Only additive measures; a non-additive one is `null` (left blank, not invented). */
257
+ measures: Record<string, number | null>;
258
+ }
259
+ /**
260
+ * THE REST, worked out from the parent's own total: the parent's rows minus the rows its shown
261
+ * children hold. Non-additive measures cannot be subtracted and stay blank. `null` when nothing
262
+ * is left over — the common case, and then no row is drawn.
263
+ */
264
+ declare function otherOf(parent: MatrxDrillAnswerRow | undefined, children: readonly MatrxDrillAnswerRow[], measures: readonly MatrxDrillMeasure[]): MatrxDrillOther | null;
265
+ /**
266
+ * THE TREE a grouped answer draws: level 0 from the request for `by[0]`, each deeper level from
267
+ * the request for its prefix, children matched to their parent by the parent's values. `null`
268
+ * while any level is still unanswered.
269
+ */
270
+ declare function buildDrillTree(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, measures: readonly MatrxDrillMeasure[]): {
271
+ nodes: MatrxDrillNode[];
272
+ total: MatrxDrillAnswerRow | null;
273
+ other: MatrxDrillOther | null;
274
+ } | null;
275
+ interface MatrxDrillPivotColumn {
276
+ /** `null` is the "no value" column; `OTHER` is everything past the cap. */
277
+ value: string | null;
278
+ other?: boolean;
279
+ label: string;
280
+ total: MatrxDrillAnswerRow;
281
+ }
282
+ declare const MATRX_DRILL_OTHER_COLUMN = "\0other";
283
+ /**
284
+ * THE COLUMNS a pivot draws: the `across` values largest first (the store's order), capped, and
285
+ * ONE "Other" column holding the rest, so the columns always add up to the row total. `null`
286
+ * while the pivot's own totals are unanswered.
287
+ */
288
+ declare function pivotColumns(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, dimensions: readonly MatrxDrillDimension[], measures: readonly MatrxDrillMeasure[], cap?: number): MatrxDrillPivotColumn[] | null;
289
+ /**
290
+ * One pivot cell: the row's values crossed with one column. The "Other" column is the rest of the
291
+ * row — the row's own total minus the capped columns — for additive measures only.
292
+ */
293
+ declare function pivotCell(question: MatrxDrillQuestion, answers: MatrxDrillAnswers, node: Pick<MatrxDrillNode, "level" | "groups" | "row">, column: MatrxDrillPivotColumn, columns: readonly MatrxDrillPivotColumn[], measure: MatrxDrillMeasure): number | null;
294
+ /** "(none)" is the address's word for a blank value (the design's URL grammar, f.4). */
295
+ declare const MATRX_DRILL_NONE = "(none)";
296
+ /**
297
+ * Does the address carry a drill QUESTION? `sort` and `path` only refine one — and other screens
298
+ * write a bare `sort` of their own (`?sort=title.asc`) — so they never, alone, override a Saved
299
+ * view's question.
300
+ */
301
+ declare function addressHasDrill(params: URLSearchParams, prefix?: string): boolean;
302
+ /**
303
+ * THE ADDRESS → THE QUESTION. `?by=condition,room&across=last_serviced:month&show=count,sum_quantity
304
+ * &f.condition=Needs%20repair&sort=-sum_quantity&path=condition,room`. The `f.` filters are read
305
+ * in the order the address holds them — that order IS the breadcrumb.
306
+ */
307
+ declare function drillQuestionFromParams(params: URLSearchParams, fallback: MatrxDrillQuestion, prefix?: string): MatrxDrillQuestion;
308
+ /**
309
+ * THE QUESTION → AN ADDRESS PATCH for `commitUrlParams`: every drill key set or cleared, and every
310
+ * `f.` filter the address holds today cleared unless the question keeps it. `f.` keys are written
311
+ * in the trail's order.
312
+ */
313
+ declare function drillQuestionToParams(question: MatrxDrillQuestion, current: URLSearchParams, prefix?: string): Record<string, string | null>;
314
+ /** Two questions ask the same thing (the address and a Saved view agree). */
315
+ declare function sameDrillQuestion(a: MatrxDrillQuestion, b: MatrxDrillQuestion): boolean;
316
+
78
317
  /** How a column's filter UI behaves. `auto` infers from sample values. */
79
318
  type ColumnFilterKind = "auto" | "text" | "select" | "boolean" | "number" | "date" | false;
80
319
  type SortDirection = "asc" | "desc";
@@ -1221,6 +1460,35 @@ interface MatrxDataTableGroupingConfig<T> {
1221
1460
  */
1222
1461
  readCell?: ((row: T, columnId: string) => unknown) | undefined;
1223
1462
  }
1463
+ /**
1464
+ * DRILL — group by a Dimension with SERVER-computed groups, pivot a second Dimension across the
1465
+ * top, pick the Measures shown, and drill on a group (lane D3; `./drill.ts` is the whole model).
1466
+ *
1467
+ * CONTROLLED like `grouping`: the question is the consumer's (it lives in the address and saves
1468
+ * as a Saved view), the table only asks for it to change. THE TABLE ASKS, THE HOST ANSWERS:
1469
+ * `drillRequests(question)` names each grouping the screen needs and the host puts each door's
1470
+ * rows into `answers` under the request's key. While `question.by` is empty the table lists its
1471
+ * records as always (narrowed by the host to `question.where`), and the trail stays in the
1472
+ * toolbar so a person can zoom back out.
1473
+ *
1474
+ * With `drill` the toolbar's group-by control groups by Dimensions on the server; the
1475
+ * page-scoped `grouping` is not drawn at the same time.
1476
+ */
1477
+ interface MatrxDataTableDrillConfig {
1478
+ dimensions: readonly MatrxDrillDimension[];
1479
+ measures: readonly MatrxDrillMeasure[];
1480
+ question: MatrxDrillQuestion;
1481
+ onQuestionChange: (next: MatrxDrillQuestion) => void;
1482
+ answers: MatrxDrillAnswers;
1483
+ /** A read that failed, in words the person can act on. */
1484
+ error?: string | null | undefined;
1485
+ /** The trail's first crumb. Default "All records". */
1486
+ rootLabel?: string | undefined;
1487
+ /** Singular noun ("record" → "12 records"). */
1488
+ rowNoun?: string | undefined;
1489
+ /** How a blank group reads. Default "No value". */
1490
+ emptyLabel?: string | undefined;
1491
+ }
1224
1492
  /**
1225
1493
  * VIRTUALIZATION — render the rows a person can actually see.
1226
1494
  *
@@ -1608,6 +1876,11 @@ interface MatrxDataTableProps<T> {
1608
1876
  * subtotals on each header. Opt-in and controlled; see the config's own doc.
1609
1877
  */
1610
1878
  grouping?: MatrxDataTableGroupingConfig<T>;
1879
+ /**
1880
+ * DRILL — server-computed groups, a pivot, a measure picker and drill-on-a-group, with the
1881
+ * breadcrumb in the toolbar. Controlled; see the config's own doc.
1882
+ */
1883
+ drill?: MatrxDataTableDrillConfig | undefined;
1611
1884
  /** Render only the rows in view. Opt-in; engages past its own threshold. */
1612
1885
  virtualize?: boolean | MatrxDataTableVirtualizeConfig;
1613
1886
  /**
@@ -1769,4 +2042,4 @@ declare function columnFiltersToLayeredRules(filters: ColumnFiltersState, fieldI
1769
2042
  declare function layeredFilterMatchesValue(value: unknown, rule: LayeredFilterRule): boolean;
1770
2043
  declare function layeredFilterRuleSummary(rule: LayeredFilterRule, fields: readonly LayeredFilterField[]): string;
1771
2044
 
1772
- export { type TableSearchScope as $, type AnyOfColumnSearch as A, type MatrxDataTableQueryControl as B, type ColumnFiltersState as C, type MatrxDataTableReadStatus as D, type MatrxDataTableSelectionConfig as E, type MatrxDataTableSingleExpandedDetailConfig as F, type MatrxDataTableSourceProcessing as G, type MatrxDataTableSpreadsheetConfig as H, type MatrxDataTableStyleConfig as I, type MatrxDataTableSummaryConfig as J, type MatrxDataTableSummaryContext as K, type LayeredFilterRule as L, type MatrxColumnDef as M, type MatrxDataTableSummaryMetric as N, type MatrxDataTableToolbar as O, type MatrxDataTableUrlStateConfig as P, type MatrxDataTableVirtualizeConfig as Q, type MatrxDataTableWindowConfig as R, type SortState as S, type TableSearchMatchMode as T, type MatrxTablePagination as U, type NumberFilterOp as V, type SavedTableViewTab as W, type SortDirection as X, type SpreadsheetSelection as Y, type TableRankedSearchOptions as Z, type TableSearchRole as _, type ColumnFilterValue as a, type TableViewQuery as a0, type TableViewTab as a1, TableViewTabs as a2, type TableViewTabsProps as a3, type TableViewTabsStore as a4, type TextFilterMode as a5, type ToolbarFacet as a6, inferTableSearchRole as a7, rankTableSearchRows as a8, resolveTableSearchScopes as a9, LAYERED_FILTER_OPERATORS as aa, LAYERED_FILTER_OPERATOR_LABELS as ab, type LayeredFilterField as ac, type LayeredFilterOperator as ad, columnFiltersToLayeredRules as ae, completeLayeredFilterRules as af, decodeLayeredFilterRules as ag, encodeLayeredFilterRules as ah, isCompleteLayeredFilterRule as ai, isLayeredFilterOperator as aj, layeredFilterMatchesValue as ak, layeredFilterNeedsValue as al, layeredFilterRuleSummary as am, operatorsForLayeredField as an, type TableSavedViewsProps as b, type MatrxDataTableDensity as c, type MatrxDataTableRecordControls as d, type MatrxDataTableQueryState as e, type ColumnFilterKind as f, type MatrxDataTableCopyConfig as g, type MatrxDataTableProps as h, type TableViewSnapshot as i, type MatrxDataTableRead as j, type ColumnMarker as k, type CellEditType as l, type CellEditsMap as m, type MatrxDataTableContextMenuConfig as n, type MatrxDataTableCoverageConfig as o, type MatrxDataTableDetailConfig as p, type MatrxDataTableEditConfig as q, type MatrxDataTableEmptyState as r, type MatrxDataTableExpandedDetailConfig as s, type MatrxDataTableFacetsConfig as t, type MatrxDataTableFilterUi as u, type MatrxDataTableGroupingConfig as v, type MatrxDataTableHierarchyConfig as w, type MatrxDataTableHierarchyMove as x, type MatrxDataTableMobileCardControls as y, type MatrxDataTableMultiExpandedDetailConfig as z };
2045
+ export { type MatrxDataTableUrlStateConfig as $, type AnyOfColumnSearch as A, type MatrxDataTableEditConfig as B, type ColumnFiltersState as C, type MatrxDataTableEmptyState as D, type MatrxDataTableExpandedDetailConfig as E, type MatrxDataTableFacetsConfig as F, type MatrxDataTableFilterUi as G, type MatrxDataTableGroupingConfig as H, type MatrxDataTableHierarchyConfig as I, type MatrxDataTableHierarchyMove as J, type MatrxDataTableMobileCardControls as K, type LayeredFilterRule as L, type MatrxColumnDef as M, type MatrxDataTableMultiExpandedDetailConfig as N, type MatrxDataTableQueryControl as O, type MatrxDataTableReadStatus as P, type MatrxDataTableSelectionConfig as Q, type MatrxDataTableSingleExpandedDetailConfig as R, type SortState as S, type TableSearchMatchMode as T, type MatrxDataTableSourceProcessing as U, type MatrxDataTableSpreadsheetConfig as V, type MatrxDataTableStyleConfig as W, type MatrxDataTableSummaryConfig as X, type MatrxDataTableSummaryContext as Y, type MatrxDataTableSummaryMetric as Z, type MatrxDataTableToolbar as _, type ColumnFilterValue as a, isLayeredFilterOperator as a$, type MatrxDataTableVirtualizeConfig as a0, type MatrxDataTableWindowConfig as a1, type MatrxDrillAnswerRow as a2, type MatrxDrillCrumb as a3, type MatrxDrillDimensionKind as a4, type MatrxDrillFilter as a5, type MatrxDrillGrain as a6, type MatrxDrillNode as a7, type MatrxDrillOther as a8, type MatrxDrillPivotColumn as a9, drillPath as aA, drillQuestionFromParams as aB, drillQuestionToParams as aC, drillRequestKey as aD, drillRequests as aE, drillToRecords as aF, drillValueLabel as aG, emptyDrillQuestion as aH, inferTableSearchRole as aI, nextDrillLevel as aJ, otherOf as aK, parseDimensionRef as aL, pivotCell as aM, pivotColumns as aN, rankTableSearchRows as aO, resolveTableSearchScopes as aP, sameDrillQuestion as aQ, zoomOutTo as aR, LAYERED_FILTER_OPERATORS as aS, LAYERED_FILTER_OPERATOR_LABELS as aT, type LayeredFilterField as aU, type LayeredFilterOperator as aV, columnFiltersToLayeredRules as aW, completeLayeredFilterRules as aX, decodeLayeredFilterRules as aY, encodeLayeredFilterRules as aZ, isCompleteLayeredFilterRule as a_, type MatrxDrillRequest as aa, type MatrxTablePagination as ab, type NumberFilterOp as ac, type SavedTableViewTab as ad, type SortDirection as ae, type SpreadsheetSelection as af, type TableRankedSearchOptions as ag, type TableSearchRole as ah, type TableSearchScope as ai, type TableViewQuery as aj, type TableViewTab as ak, TableViewTabs as al, type TableViewTabsProps as am, type TableViewTabsStore as an, type TextFilterMode as ao, type ToolbarFacet as ap, addressHasDrill as aq, bucketLabel as ar, bucketWindow as as, buildDrillTree as at, dimensionFor as au, dimensionRefLabel as av, dimensionRefs as aw, drillCrumbs as ax, drillInto as ay, drillIsGrouped as az, type TableSavedViewsProps as b, layeredFilterMatchesValue as b0, layeredFilterNeedsValue as b1, layeredFilterRuleSummary as b2, operatorsForLayeredField as b3, type MatrxDataTableDensity as c, type MatrxDataTableRecordControls as d, type MatrxDataTableQueryState as e, type ColumnFilterKind as f, type MatrxDataTableCopyConfig as g, type MatrxDataTableProps as h, type TableViewSnapshot as i, type MatrxDataTableRead as j, type ColumnMarker as k, type MatrxDrillDimension as l, type MatrxDrillMeasure as m, type MatrxDrillQuestion as n, type MatrxDrillAnswers as o, type CellEditType as p, type CellEditsMap as q, MATRX_DRILL_GRAINS as r, MATRX_DRILL_MAX_LEVELS as s, MATRX_DRILL_NONE as t, MATRX_DRILL_OTHER_COLUMN as u, MATRX_DRILL_PIVOT_COLUMNS as v, type MatrxDataTableContextMenuConfig as w, type MatrxDataTableCoverageConfig as x, type MatrxDataTableDetailConfig as y, type MatrxDataTableDrillConfig as z };
@@ -185,7 +185,7 @@
185
185
  }
186
186
  /* Only explicitly icon-only controls are square. Labeled actions must retain
187
187
  their intrinsic width or their text overlaps adjacent actions. */
188
- [data-matrx-table][data-matrx-table-density] [data-matrx-table-row-actions] :is(.matrx-tap-target:not(.matrx-tap-target-inline), [data-matrx-table-icon-action]) {
188
+ [data-matrx-table][data-matrx-table-density] [data-matrx-table-row-actions] :is(.matrx-tap-target:not(.matrx-tap-target-inline):not(.matrx-tap-target-inline-sm):not(.matrx-tap-target-mobile-icon-only):not(.matrx-tap-target-mobile-icon-only-sm), [data-matrx-table-icon-action]) {
189
189
  width: var(--matrx-table-row-action-size) !important;
190
190
  }
191
191
  [data-matrx-table][data-matrx-table-density] [data-matrx-table-selection-target] {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/design-system",
3
- "version": "0.49.28",
3
+ "version": "0.49.32",
4
4
  "description": "AI Matrx semantic React primitives shared across Vite, Next.js, desktop, and customer-built applications.",
5
5
  "type": "module",
6
6
  "license": "MIT",