@ai-matrx/records-ui 0.68.0 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/index.cjs +178 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -44
- package/dist/index.d.ts +85 -44
- package/dist/index.js +179 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ComponentType, RefObject } from 'react';
|
|
3
3
|
import * as _ai_matrx_records from '@ai-matrx/records';
|
|
4
|
-
import { PermissionLevel, Table, RecordScopeContext, EnrichCell, RecordsError, Uuid as Uuid$1, AggregateFilter, Field, RecordDocument, ReadRow, RelationDisplay, WriteConflict, ParityFieldType, NewFieldDeclaration, RuleExpression, ValueEnvelope, ChecklistRequirementKind, ContextPolicy, WorkDueState, FieldSensitivity, StageRuleOnFail, SubscriptionCadence, WorkInboxKind, FieldKind, FormSummary, PortalCard, PortalPrincipal, PortalPreviewRow, DashboardBlockKind, AggregateBucket, AggregateMeasure, DashboardBlock, DashboardSummary, DocTemplateRow, DocRenderRow, QuietHours, DashboardBlockResult, ChecklistRunStep, BookingSummary, CaptureSheetFace, CaptureField, AnonTokenBinding, RecordsConfig, RecordsActor, RecordsDataSource, HistoryActor, FieldHistoryEntry, FieldTypeWord } from '@ai-matrx/records';
|
|
5
|
-
import { Uuid, Field as Field$1, ReadRow as ReadRow$1 } from '@ai-matrx/records/react';
|
|
4
|
+
import { PermissionLevel, Table, RecordScopeContext, EnrichCell, RecordsError, Uuid as Uuid$1, AggregateFilter, Field, RecordDocument, ReadRow, RelationDisplay, WriteConflict, ParityFieldType, NewFieldDeclaration, RuleExpression, ValueEnvelope, ChecklistRequirementKind, ContextPolicy, WorkDueState, FieldSensitivity, StageRuleOnFail, SubscriptionCadence, WorkInboxKind, FieldKind, RecordFilter as RecordFilter$1, FormSummary, PortalCard, PortalPrincipal, PortalPreviewRow, DashboardBlockKind, AggregateBucket, AggregateMeasure, DashboardBlock, DashboardSummary, DocTemplateRow, DocRenderRow, QuietHours, DashboardBlockResult, ChecklistRunStep, BookingSummary, CaptureSheetFace, CaptureField, AnonTokenBinding, RecordsConfig, RecordsActor, RecordsDataSource, HistoryActor, FieldHistoryEntry, FieldTypeWord } from '@ai-matrx/records';
|
|
5
|
+
import { Uuid, RecordFilter, Field as Field$1, ReadRow as ReadRow$1 } from '@ai-matrx/records/react';
|
|
6
6
|
import { RecordsClient } from '@ai-matrx/records/core';
|
|
7
7
|
import { FieldFormatConfig } from '@ai-matrx/design-system/field-formats';
|
|
8
8
|
import { MatrxColumnDef } from '@ai-matrx/design-system/data-table/types';
|
|
@@ -1040,6 +1040,16 @@ interface GridProps {
|
|
|
1040
1040
|
tableId: Uuid;
|
|
1041
1041
|
/** Rows per page. The table's own pagination handles the rest. */
|
|
1042
1042
|
pageSize?: number | undefined;
|
|
1043
|
+
/**
|
|
1044
|
+
* THE QUESTION THIS GRID IS ANSWERING, in the store's one filter shape.
|
|
1045
|
+
*
|
|
1046
|
+
* Left out, it is the whole table. Supplied — a dashboard number was clicked,
|
|
1047
|
+
* or a saved view carries `filters` — the STORE narrows the page inside its
|
|
1048
|
+
* own query. Never filter `rows` here: this grid only ever holds one page,
|
|
1049
|
+
* so filtering in the browser would drop every matching record on page two
|
|
1050
|
+
* and call the result the answer.
|
|
1051
|
+
*/
|
|
1052
|
+
filter?: RecordFilter | undefined;
|
|
1043
1053
|
/** Opened when a row is clicked. A host that has a record page passes its own. */
|
|
1044
1054
|
onOpenRecord?: ((recordId: Uuid) => void) | undefined;
|
|
1045
1055
|
/** SCR-2. Called when an admin clicks the "+" at the end of the headers. */
|
|
@@ -1093,7 +1103,7 @@ interface GridProps {
|
|
|
1093
1103
|
onPresentationChange?: ((next: GridPresentation) => void) | undefined;
|
|
1094
1104
|
className?: string | undefined;
|
|
1095
1105
|
}
|
|
1096
|
-
declare function Grid({ tableId, pageSize, onOpenRecord, onAddField, onNewRecordForm, toolbarActions, editable, presentation, onPresentationChange, className, onAskWhoChanged, }: GridProps): react.JSX.Element;
|
|
1106
|
+
declare function Grid({ tableId, pageSize, filter, onOpenRecord, onAddField, onNewRecordForm, toolbarActions, editable, presentation, onPresentationChange, className, onAskWhoChanged, }: GridProps): react.JSX.Element;
|
|
1097
1107
|
/**
|
|
1098
1108
|
* One Field becomes one column. The header is the Field's own NAME — never its
|
|
1099
1109
|
* key (`names.ts`) — and the cell is the value, rendered by its parity type and
|
|
@@ -1406,8 +1416,18 @@ interface RelationPickerProps {
|
|
|
1406
1416
|
disabled?: boolean | undefined;
|
|
1407
1417
|
id?: string | undefined;
|
|
1408
1418
|
className?: string | undefined;
|
|
1419
|
+
/**
|
|
1420
|
+
* WHETHER A PERSON MAY MAKE THE THING SHE IS LOOKING FOR (RELATION-CREATE, 2026-09-22).
|
|
1421
|
+
*
|
|
1422
|
+
* On by default, because that is what this control is for on every surface a
|
|
1423
|
+
* person fills a record in: the grid cell, the generated form, a public form
|
|
1424
|
+
* runner. The one surface that passes `false` is the filter builder — picking
|
|
1425
|
+
* a value to FILTER by is not a reason to put a new customer in the book, and
|
|
1426
|
+
* a Create button there would write a row nobody asked for.
|
|
1427
|
+
*/
|
|
1428
|
+
allowCreate?: boolean | undefined;
|
|
1409
1429
|
}
|
|
1410
|
-
declare function RelationPicker({ field, value, onChange, disabled, id, className }: RelationPickerProps): react.JSX.Element;
|
|
1430
|
+
declare function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate }: RelationPickerProps): react.JSX.Element;
|
|
1411
1431
|
|
|
1412
1432
|
interface FieldEditorControlProps {
|
|
1413
1433
|
field: Field;
|
|
@@ -1807,17 +1827,24 @@ interface ViewSwitcherProps {
|
|
|
1807
1827
|
/** "Who changed this?" from a grid cell — the host opens that column's timeline. */
|
|
1808
1828
|
onAskWhoChanged?: ((fieldKey: string, recordId: Uuid) => void) | undefined;
|
|
1809
1829
|
pageSize?: number | undefined;
|
|
1830
|
+
/**
|
|
1831
|
+
* THE QUESTION THE ADDRESS ASKED, in the store's one filter shape — the same
|
|
1832
|
+
* object the chart counted with. It narrows the grid AND the board through
|
|
1833
|
+
* the store, so switching layout after a drill-through keeps the same rows
|
|
1834
|
+
* instead of quietly widening back to the whole table.
|
|
1835
|
+
*/
|
|
1836
|
+
filter?: RecordFilter$1 | undefined;
|
|
1810
1837
|
className?: string | undefined;
|
|
1811
1838
|
}
|
|
1812
1839
|
/** The records this view holds: its Rule's members when it names one, the table otherwise. */
|
|
1813
|
-
declare function useViewRecords(view: SavedViewSpec, pageSize?: number): {
|
|
1840
|
+
declare function useViewRecords(view: SavedViewSpec, pageSize?: number, filter?: RecordFilter$1): {
|
|
1814
1841
|
rows: ReadRow$1[];
|
|
1815
1842
|
loading: boolean;
|
|
1816
1843
|
error: RecordsError | null;
|
|
1817
1844
|
/** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */
|
|
1818
1845
|
membership: string;
|
|
1819
1846
|
};
|
|
1820
|
-
declare function ViewSwitcher({ view, onLayoutChange, onViewChange, onOpenRecord, onMoved, onNewRecordForm, onAskWhoChanged, pageSize, className, }: ViewSwitcherProps): react.JSX.Element;
|
|
1847
|
+
declare function ViewSwitcher({ view, onLayoutChange, onViewChange, onOpenRecord, onMoved, onNewRecordForm, onAskWhoChanged, pageSize, filter, className, }: ViewSwitcherProps): react.JSX.Element;
|
|
1821
1848
|
|
|
1822
1849
|
interface ViewBarProps {
|
|
1823
1850
|
/** The Table whose views these are. */
|
|
@@ -2159,8 +2186,16 @@ interface DigestSchedulerProps {
|
|
|
2159
2186
|
* view's name, so nothing in the list is called "Saved view".
|
|
2160
2187
|
*/
|
|
2161
2188
|
subjectName?: string | null | undefined;
|
|
2162
|
-
/**
|
|
2163
|
-
|
|
2189
|
+
/**
|
|
2190
|
+
* The filters of the thing being scheduled, written straight into the saved
|
|
2191
|
+
* view — in the store's ONE filter shape (`RecordFilter`), which is what
|
|
2192
|
+
* `custom.view_declare` stores, what `custom.agg_view_admits` reads to decide
|
|
2193
|
+
* whether a change belongs to this view, and what the read and aggregate
|
|
2194
|
+
* doors both take. It was `Record<string, unknown>` until DRILL named the
|
|
2195
|
+
* shape: an unknown here is a subscription that silently notifies about the
|
|
2196
|
+
* wrong records.
|
|
2197
|
+
*/
|
|
2198
|
+
filters?: RecordFilter$1 | null | undefined;
|
|
2164
2199
|
onScheduled?: (() => void) | undefined;
|
|
2165
2200
|
onClose?: (() => void) | undefined;
|
|
2166
2201
|
className?: string | undefined;
|
|
@@ -2882,14 +2917,12 @@ interface TablePageProps {
|
|
|
2882
2917
|
/**
|
|
2883
2918
|
* WHICH FIELD THE ADDRESS WANTS THE BOARD'S COLUMNS TO BE, for this visit.
|
|
2884
2919
|
*
|
|
2885
|
-
* 🚨 THIS IS HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2886
|
-
*
|
|
2887
|
-
*
|
|
2888
|
-
*
|
|
2889
|
-
*
|
|
2890
|
-
*
|
|
2891
|
-
* with its columns set to the very field the chart grouped by, where the
|
|
2892
|
-
* column the person clicked is right there and every card in it is real.
|
|
2920
|
+
* 🚨 THIS IS HALF OF HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2921
|
+
* 2026-09-22): the board opens with its columns set to the very field the
|
|
2922
|
+
* chart grouped by, so the column the person clicked is right there. The
|
|
2923
|
+
* other half is `filter`, which lane DRILL added hours later once the store
|
|
2924
|
+
* grew `custom.read_records_matching` — until then a click could only widen,
|
|
2925
|
+
* and the sentence under the board said so out loud.
|
|
2893
2926
|
*
|
|
2894
2927
|
* It overrides the saved view's own `groupField` for this visit only, exactly
|
|
2895
2928
|
* as `activeView` overrides its layout, and it is never written back.
|
|
@@ -2898,40 +2931,48 @@ interface TablePageProps {
|
|
|
2898
2931
|
/**
|
|
2899
2932
|
* WHAT THE PERSON CLICKED TO GET HERE — "Jobs by stage · Awaiting parts".
|
|
2900
2933
|
*
|
|
2901
|
-
* Present, the board says where they came from AND
|
|
2902
|
-
*
|
|
2903
|
-
*
|
|
2904
|
-
*
|
|
2934
|
+
* Present, the board says where they came from AND, when `filter` came with
|
|
2935
|
+
* it, which question is holding the rest of the table back. A screen showing
|
|
2936
|
+
* a subset without saying so is a table lying about how much of itself it is
|
|
2937
|
+
* — and one showing MORE rows than the number promised is the number lying
|
|
2938
|
+
* twice.
|
|
2905
2939
|
*/
|
|
2906
2940
|
cameFrom?: string | null | undefined;
|
|
2941
|
+
/**
|
|
2942
|
+
* WHICH RECORDS THE ADDRESS ASKED FOR, in the store's one filter shape.
|
|
2943
|
+
*
|
|
2944
|
+
* 🚨 THIS IS WHAT MAKES A DASHBOARD NUMBER WALKABLE (lane DRILL, 2026-09-22).
|
|
2945
|
+
* TAILS-6 could route a bar click here but could not narrow anything: the
|
|
2946
|
+
* store had no door that took a filter, so the click opened the WHOLE table
|
|
2947
|
+
* and a sentence underneath said so. `custom.read_records_matching` takes the
|
|
2948
|
+
* same object the chart counted with, and this prop is how the address hands
|
|
2949
|
+
* it to the grid and the board — both of them, so switching layout does not
|
|
2950
|
+
* quietly widen back to every record.
|
|
2951
|
+
*
|
|
2952
|
+
* It is a QUESTION for this visit, exactly like `activeView` and
|
|
2953
|
+
* `activeGroupField`, and is never written onto the saved view.
|
|
2954
|
+
*/
|
|
2955
|
+
filter?: RecordFilter$1 | null | undefined;
|
|
2907
2956
|
className?: string | undefined;
|
|
2908
2957
|
}
|
|
2909
|
-
/**
|
|
2910
|
-
* THE SENTENCE A TABLE YOU CANNOT SEE SAYS.
|
|
2911
|
-
*
|
|
2912
|
-
* Measured on the real screen (independent verdict, 19 September): opening a
|
|
2913
|
-
* table's page while another organization was active left the main area's text
|
|
2914
|
-
* "literally the empty string" after eighteen seconds — no sentence, no
|
|
2915
|
-
* spinner, no console error. A made-up id did the same. The cause is exactly
|
|
2916
|
-
* one line of this file: `custom.table_list` correctly answers the tables this
|
|
2917
|
-
* person can see in THIS organization, the table is not among them, so
|
|
2918
|
-
* `useTable` answers `{ data: null, error: null }` — not a refusal, just
|
|
2919
|
-
* absence — and the page rendered a skeleton for ever.
|
|
2920
|
-
*
|
|
2921
|
-
* Absence is an ANSWER and it gets a sentence. It deliberately does not say
|
|
2922
|
-
* whether the table exists: this person cannot see it, and which of the two it
|
|
2923
|
-
* is is not theirs to learn.
|
|
2924
|
-
*/
|
|
2925
2958
|
/**
|
|
2926
2959
|
* WHAT THE BOARD SAYS TO SOMEBODY A DASHBOARD NUMBER SENT HERE.
|
|
2927
2960
|
*
|
|
2928
|
-
*
|
|
2929
|
-
*
|
|
2930
|
-
*
|
|
2931
|
-
*
|
|
2932
|
-
*
|
|
2933
|
-
|
|
2934
|
-
|
|
2961
|
+
* 🚨 IT USED TO SAY THE OPPOSITE, AND IT WAS TELLING THE TRUTH WHEN IT DID.
|
|
2962
|
+
* Until 2026-09-22 this sentence read "This is every record grouped into the
|
|
2963
|
+
* same columns the chart used — not only the ones that number counted",
|
|
2964
|
+
* because `custom.read_records` took no filter and `custom.record_aggregate`
|
|
2965
|
+
* answers groups and counts, never ids: the store had no door that could open
|
|
2966
|
+
* the rows behind a number, so claiming a narrowed list would have been a lie.
|
|
2967
|
+
* `custom.read_records_matching` is that door, and it evaluates the question
|
|
2968
|
+
* through the very same `custom.record_filter_sql` the number was counted
|
|
2969
|
+
* with — so this now says the narrow thing, and means it.
|
|
2970
|
+
*
|
|
2971
|
+
* It still says both halves out loud: which number they clicked, and WHICH
|
|
2972
|
+
* QUESTION is holding rows back. A screen showing a subset without saying so
|
|
2973
|
+
* is a table lying about how much of itself it is.
|
|
2974
|
+
*/
|
|
2975
|
+
declare function cameFromLine(label: string, groupField: string | null, question?: string | null): string;
|
|
2935
2976
|
declare const TABLE_NOT_REACHABLE: string;
|
|
2936
2977
|
/**
|
|
2937
2978
|
* THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.
|
|
@@ -3040,7 +3081,7 @@ declare function openingView(activeView: string | null | undefined, activeDashbo
|
|
|
3040
3081
|
layout: ViewLayout | null;
|
|
3041
3082
|
unknown: string | null;
|
|
3042
3083
|
};
|
|
3043
|
-
declare function TablePage({ tableId, pageSize, seedViews, onLeave, leaveLabel, activeDashboardId, activeRecordId, activeView, onViewChanged, activeGroupField, cameFrom, className, }: TablePageProps): react.JSX.Element;
|
|
3084
|
+
declare function TablePage({ tableId, pageSize, seedViews, onLeave, leaveLabel, activeDashboardId, activeRecordId, activeView, onViewChanged, activeGroupField, cameFrom, filter, className, }: TablePageProps): react.JSX.Element;
|
|
3044
3085
|
|
|
3045
3086
|
/** What the roster can tell us about a user id. `null` when it cannot. */
|
|
3046
3087
|
type ResolveName = (userId: Uuid$1) => string | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ComponentType, RefObject } from 'react';
|
|
3
3
|
import * as _ai_matrx_records from '@ai-matrx/records';
|
|
4
|
-
import { PermissionLevel, Table, RecordScopeContext, EnrichCell, RecordsError, Uuid as Uuid$1, AggregateFilter, Field, RecordDocument, ReadRow, RelationDisplay, WriteConflict, ParityFieldType, NewFieldDeclaration, RuleExpression, ValueEnvelope, ChecklistRequirementKind, ContextPolicy, WorkDueState, FieldSensitivity, StageRuleOnFail, SubscriptionCadence, WorkInboxKind, FieldKind, FormSummary, PortalCard, PortalPrincipal, PortalPreviewRow, DashboardBlockKind, AggregateBucket, AggregateMeasure, DashboardBlock, DashboardSummary, DocTemplateRow, DocRenderRow, QuietHours, DashboardBlockResult, ChecklistRunStep, BookingSummary, CaptureSheetFace, CaptureField, AnonTokenBinding, RecordsConfig, RecordsActor, RecordsDataSource, HistoryActor, FieldHistoryEntry, FieldTypeWord } from '@ai-matrx/records';
|
|
5
|
-
import { Uuid, Field as Field$1, ReadRow as ReadRow$1 } from '@ai-matrx/records/react';
|
|
4
|
+
import { PermissionLevel, Table, RecordScopeContext, EnrichCell, RecordsError, Uuid as Uuid$1, AggregateFilter, Field, RecordDocument, ReadRow, RelationDisplay, WriteConflict, ParityFieldType, NewFieldDeclaration, RuleExpression, ValueEnvelope, ChecklistRequirementKind, ContextPolicy, WorkDueState, FieldSensitivity, StageRuleOnFail, SubscriptionCadence, WorkInboxKind, FieldKind, RecordFilter as RecordFilter$1, FormSummary, PortalCard, PortalPrincipal, PortalPreviewRow, DashboardBlockKind, AggregateBucket, AggregateMeasure, DashboardBlock, DashboardSummary, DocTemplateRow, DocRenderRow, QuietHours, DashboardBlockResult, ChecklistRunStep, BookingSummary, CaptureSheetFace, CaptureField, AnonTokenBinding, RecordsConfig, RecordsActor, RecordsDataSource, HistoryActor, FieldHistoryEntry, FieldTypeWord } from '@ai-matrx/records';
|
|
5
|
+
import { Uuid, RecordFilter, Field as Field$1, ReadRow as ReadRow$1 } from '@ai-matrx/records/react';
|
|
6
6
|
import { RecordsClient } from '@ai-matrx/records/core';
|
|
7
7
|
import { FieldFormatConfig } from '@ai-matrx/design-system/field-formats';
|
|
8
8
|
import { MatrxColumnDef } from '@ai-matrx/design-system/data-table/types';
|
|
@@ -1040,6 +1040,16 @@ interface GridProps {
|
|
|
1040
1040
|
tableId: Uuid;
|
|
1041
1041
|
/** Rows per page. The table's own pagination handles the rest. */
|
|
1042
1042
|
pageSize?: number | undefined;
|
|
1043
|
+
/**
|
|
1044
|
+
* THE QUESTION THIS GRID IS ANSWERING, in the store's one filter shape.
|
|
1045
|
+
*
|
|
1046
|
+
* Left out, it is the whole table. Supplied — a dashboard number was clicked,
|
|
1047
|
+
* or a saved view carries `filters` — the STORE narrows the page inside its
|
|
1048
|
+
* own query. Never filter `rows` here: this grid only ever holds one page,
|
|
1049
|
+
* so filtering in the browser would drop every matching record on page two
|
|
1050
|
+
* and call the result the answer.
|
|
1051
|
+
*/
|
|
1052
|
+
filter?: RecordFilter | undefined;
|
|
1043
1053
|
/** Opened when a row is clicked. A host that has a record page passes its own. */
|
|
1044
1054
|
onOpenRecord?: ((recordId: Uuid) => void) | undefined;
|
|
1045
1055
|
/** SCR-2. Called when an admin clicks the "+" at the end of the headers. */
|
|
@@ -1093,7 +1103,7 @@ interface GridProps {
|
|
|
1093
1103
|
onPresentationChange?: ((next: GridPresentation) => void) | undefined;
|
|
1094
1104
|
className?: string | undefined;
|
|
1095
1105
|
}
|
|
1096
|
-
declare function Grid({ tableId, pageSize, onOpenRecord, onAddField, onNewRecordForm, toolbarActions, editable, presentation, onPresentationChange, className, onAskWhoChanged, }: GridProps): react.JSX.Element;
|
|
1106
|
+
declare function Grid({ tableId, pageSize, filter, onOpenRecord, onAddField, onNewRecordForm, toolbarActions, editable, presentation, onPresentationChange, className, onAskWhoChanged, }: GridProps): react.JSX.Element;
|
|
1097
1107
|
/**
|
|
1098
1108
|
* One Field becomes one column. The header is the Field's own NAME — never its
|
|
1099
1109
|
* key (`names.ts`) — and the cell is the value, rendered by its parity type and
|
|
@@ -1406,8 +1416,18 @@ interface RelationPickerProps {
|
|
|
1406
1416
|
disabled?: boolean | undefined;
|
|
1407
1417
|
id?: string | undefined;
|
|
1408
1418
|
className?: string | undefined;
|
|
1419
|
+
/**
|
|
1420
|
+
* WHETHER A PERSON MAY MAKE THE THING SHE IS LOOKING FOR (RELATION-CREATE, 2026-09-22).
|
|
1421
|
+
*
|
|
1422
|
+
* On by default, because that is what this control is for on every surface a
|
|
1423
|
+
* person fills a record in: the grid cell, the generated form, a public form
|
|
1424
|
+
* runner. The one surface that passes `false` is the filter builder — picking
|
|
1425
|
+
* a value to FILTER by is not a reason to put a new customer in the book, and
|
|
1426
|
+
* a Create button there would write a row nobody asked for.
|
|
1427
|
+
*/
|
|
1428
|
+
allowCreate?: boolean | undefined;
|
|
1409
1429
|
}
|
|
1410
|
-
declare function RelationPicker({ field, value, onChange, disabled, id, className }: RelationPickerProps): react.JSX.Element;
|
|
1430
|
+
declare function RelationPicker({ field, value, onChange, disabled, id, className, allowCreate }: RelationPickerProps): react.JSX.Element;
|
|
1411
1431
|
|
|
1412
1432
|
interface FieldEditorControlProps {
|
|
1413
1433
|
field: Field;
|
|
@@ -1807,17 +1827,24 @@ interface ViewSwitcherProps {
|
|
|
1807
1827
|
/** "Who changed this?" from a grid cell — the host opens that column's timeline. */
|
|
1808
1828
|
onAskWhoChanged?: ((fieldKey: string, recordId: Uuid) => void) | undefined;
|
|
1809
1829
|
pageSize?: number | undefined;
|
|
1830
|
+
/**
|
|
1831
|
+
* THE QUESTION THE ADDRESS ASKED, in the store's one filter shape — the same
|
|
1832
|
+
* object the chart counted with. It narrows the grid AND the board through
|
|
1833
|
+
* the store, so switching layout after a drill-through keeps the same rows
|
|
1834
|
+
* instead of quietly widening back to the whole table.
|
|
1835
|
+
*/
|
|
1836
|
+
filter?: RecordFilter$1 | undefined;
|
|
1810
1837
|
className?: string | undefined;
|
|
1811
1838
|
}
|
|
1812
1839
|
/** The records this view holds: its Rule's members when it names one, the table otherwise. */
|
|
1813
|
-
declare function useViewRecords(view: SavedViewSpec, pageSize?: number): {
|
|
1840
|
+
declare function useViewRecords(view: SavedViewSpec, pageSize?: number, filter?: RecordFilter$1): {
|
|
1814
1841
|
rows: ReadRow$1[];
|
|
1815
1842
|
loading: boolean;
|
|
1816
1843
|
error: RecordsError | null;
|
|
1817
1844
|
/** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */
|
|
1818
1845
|
membership: string;
|
|
1819
1846
|
};
|
|
1820
|
-
declare function ViewSwitcher({ view, onLayoutChange, onViewChange, onOpenRecord, onMoved, onNewRecordForm, onAskWhoChanged, pageSize, className, }: ViewSwitcherProps): react.JSX.Element;
|
|
1847
|
+
declare function ViewSwitcher({ view, onLayoutChange, onViewChange, onOpenRecord, onMoved, onNewRecordForm, onAskWhoChanged, pageSize, filter, className, }: ViewSwitcherProps): react.JSX.Element;
|
|
1821
1848
|
|
|
1822
1849
|
interface ViewBarProps {
|
|
1823
1850
|
/** The Table whose views these are. */
|
|
@@ -2159,8 +2186,16 @@ interface DigestSchedulerProps {
|
|
|
2159
2186
|
* view's name, so nothing in the list is called "Saved view".
|
|
2160
2187
|
*/
|
|
2161
2188
|
subjectName?: string | null | undefined;
|
|
2162
|
-
/**
|
|
2163
|
-
|
|
2189
|
+
/**
|
|
2190
|
+
* The filters of the thing being scheduled, written straight into the saved
|
|
2191
|
+
* view — in the store's ONE filter shape (`RecordFilter`), which is what
|
|
2192
|
+
* `custom.view_declare` stores, what `custom.agg_view_admits` reads to decide
|
|
2193
|
+
* whether a change belongs to this view, and what the read and aggregate
|
|
2194
|
+
* doors both take. It was `Record<string, unknown>` until DRILL named the
|
|
2195
|
+
* shape: an unknown here is a subscription that silently notifies about the
|
|
2196
|
+
* wrong records.
|
|
2197
|
+
*/
|
|
2198
|
+
filters?: RecordFilter$1 | null | undefined;
|
|
2164
2199
|
onScheduled?: (() => void) | undefined;
|
|
2165
2200
|
onClose?: (() => void) | undefined;
|
|
2166
2201
|
className?: string | undefined;
|
|
@@ -2882,14 +2917,12 @@ interface TablePageProps {
|
|
|
2882
2917
|
/**
|
|
2883
2918
|
* WHICH FIELD THE ADDRESS WANTS THE BOARD'S COLUMNS TO BE, for this visit.
|
|
2884
2919
|
*
|
|
2885
|
-
* 🚨 THIS IS HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2886
|
-
*
|
|
2887
|
-
*
|
|
2888
|
-
*
|
|
2889
|
-
*
|
|
2890
|
-
*
|
|
2891
|
-
* with its columns set to the very field the chart grouped by, where the
|
|
2892
|
-
* column the person clicked is right there and every card in it is real.
|
|
2920
|
+
* 🚨 THIS IS HALF OF HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2921
|
+
* 2026-09-22): the board opens with its columns set to the very field the
|
|
2922
|
+
* chart grouped by, so the column the person clicked is right there. The
|
|
2923
|
+
* other half is `filter`, which lane DRILL added hours later once the store
|
|
2924
|
+
* grew `custom.read_records_matching` — until then a click could only widen,
|
|
2925
|
+
* and the sentence under the board said so out loud.
|
|
2893
2926
|
*
|
|
2894
2927
|
* It overrides the saved view's own `groupField` for this visit only, exactly
|
|
2895
2928
|
* as `activeView` overrides its layout, and it is never written back.
|
|
@@ -2898,40 +2931,48 @@ interface TablePageProps {
|
|
|
2898
2931
|
/**
|
|
2899
2932
|
* WHAT THE PERSON CLICKED TO GET HERE — "Jobs by stage · Awaiting parts".
|
|
2900
2933
|
*
|
|
2901
|
-
* Present, the board says where they came from AND
|
|
2902
|
-
*
|
|
2903
|
-
*
|
|
2904
|
-
*
|
|
2934
|
+
* Present, the board says where they came from AND, when `filter` came with
|
|
2935
|
+
* it, which question is holding the rest of the table back. A screen showing
|
|
2936
|
+
* a subset without saying so is a table lying about how much of itself it is
|
|
2937
|
+
* — and one showing MORE rows than the number promised is the number lying
|
|
2938
|
+
* twice.
|
|
2905
2939
|
*/
|
|
2906
2940
|
cameFrom?: string | null | undefined;
|
|
2941
|
+
/**
|
|
2942
|
+
* WHICH RECORDS THE ADDRESS ASKED FOR, in the store's one filter shape.
|
|
2943
|
+
*
|
|
2944
|
+
* 🚨 THIS IS WHAT MAKES A DASHBOARD NUMBER WALKABLE (lane DRILL, 2026-09-22).
|
|
2945
|
+
* TAILS-6 could route a bar click here but could not narrow anything: the
|
|
2946
|
+
* store had no door that took a filter, so the click opened the WHOLE table
|
|
2947
|
+
* and a sentence underneath said so. `custom.read_records_matching` takes the
|
|
2948
|
+
* same object the chart counted with, and this prop is how the address hands
|
|
2949
|
+
* it to the grid and the board — both of them, so switching layout does not
|
|
2950
|
+
* quietly widen back to every record.
|
|
2951
|
+
*
|
|
2952
|
+
* It is a QUESTION for this visit, exactly like `activeView` and
|
|
2953
|
+
* `activeGroupField`, and is never written onto the saved view.
|
|
2954
|
+
*/
|
|
2955
|
+
filter?: RecordFilter$1 | null | undefined;
|
|
2907
2956
|
className?: string | undefined;
|
|
2908
2957
|
}
|
|
2909
|
-
/**
|
|
2910
|
-
* THE SENTENCE A TABLE YOU CANNOT SEE SAYS.
|
|
2911
|
-
*
|
|
2912
|
-
* Measured on the real screen (independent verdict, 19 September): opening a
|
|
2913
|
-
* table's page while another organization was active left the main area's text
|
|
2914
|
-
* "literally the empty string" after eighteen seconds — no sentence, no
|
|
2915
|
-
* spinner, no console error. A made-up id did the same. The cause is exactly
|
|
2916
|
-
* one line of this file: `custom.table_list` correctly answers the tables this
|
|
2917
|
-
* person can see in THIS organization, the table is not among them, so
|
|
2918
|
-
* `useTable` answers `{ data: null, error: null }` — not a refusal, just
|
|
2919
|
-
* absence — and the page rendered a skeleton for ever.
|
|
2920
|
-
*
|
|
2921
|
-
* Absence is an ANSWER and it gets a sentence. It deliberately does not say
|
|
2922
|
-
* whether the table exists: this person cannot see it, and which of the two it
|
|
2923
|
-
* is is not theirs to learn.
|
|
2924
|
-
*/
|
|
2925
2958
|
/**
|
|
2926
2959
|
* WHAT THE BOARD SAYS TO SOMEBODY A DASHBOARD NUMBER SENT HERE.
|
|
2927
2960
|
*
|
|
2928
|
-
*
|
|
2929
|
-
*
|
|
2930
|
-
*
|
|
2931
|
-
*
|
|
2932
|
-
*
|
|
2933
|
-
|
|
2934
|
-
|
|
2961
|
+
* 🚨 IT USED TO SAY THE OPPOSITE, AND IT WAS TELLING THE TRUTH WHEN IT DID.
|
|
2962
|
+
* Until 2026-09-22 this sentence read "This is every record grouped into the
|
|
2963
|
+
* same columns the chart used — not only the ones that number counted",
|
|
2964
|
+
* because `custom.read_records` took no filter and `custom.record_aggregate`
|
|
2965
|
+
* answers groups and counts, never ids: the store had no door that could open
|
|
2966
|
+
* the rows behind a number, so claiming a narrowed list would have been a lie.
|
|
2967
|
+
* `custom.read_records_matching` is that door, and it evaluates the question
|
|
2968
|
+
* through the very same `custom.record_filter_sql` the number was counted
|
|
2969
|
+
* with — so this now says the narrow thing, and means it.
|
|
2970
|
+
*
|
|
2971
|
+
* It still says both halves out loud: which number they clicked, and WHICH
|
|
2972
|
+
* QUESTION is holding rows back. A screen showing a subset without saying so
|
|
2973
|
+
* is a table lying about how much of itself it is.
|
|
2974
|
+
*/
|
|
2975
|
+
declare function cameFromLine(label: string, groupField: string | null, question?: string | null): string;
|
|
2935
2976
|
declare const TABLE_NOT_REACHABLE: string;
|
|
2936
2977
|
/**
|
|
2937
2978
|
* THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.
|
|
@@ -3040,7 +3081,7 @@ declare function openingView(activeView: string | null | undefined, activeDashbo
|
|
|
3040
3081
|
layout: ViewLayout | null;
|
|
3041
3082
|
unknown: string | null;
|
|
3042
3083
|
};
|
|
3043
|
-
declare function TablePage({ tableId, pageSize, seedViews, onLeave, leaveLabel, activeDashboardId, activeRecordId, activeView, onViewChanged, activeGroupField, cameFrom, className, }: TablePageProps): react.JSX.Element;
|
|
3084
|
+
declare function TablePage({ tableId, pageSize, seedViews, onLeave, leaveLabel, activeDashboardId, activeRecordId, activeView, onViewChanged, activeGroupField, cameFrom, filter, className, }: TablePageProps): react.JSX.Element;
|
|
3044
3085
|
|
|
3045
3086
|
/** What the roster can tell us about a user id. `null` when it cannot. */
|
|
3046
3087
|
type ResolveName = (userId: Uuid$1) => string | null;
|