@ai-matrx/records-ui 0.69.0 → 0.71.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 +55 -0
- package/dist/index.cjs +95 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -43
- package/dist/index.d.ts +74 -43
- package/dist/index.js +192 -122
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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
|
|
@@ -1817,17 +1827,24 @@ interface ViewSwitcherProps {
|
|
|
1817
1827
|
/** "Who changed this?" from a grid cell — the host opens that column's timeline. */
|
|
1818
1828
|
onAskWhoChanged?: ((fieldKey: string, recordId: Uuid) => void) | undefined;
|
|
1819
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;
|
|
1820
1837
|
className?: string | undefined;
|
|
1821
1838
|
}
|
|
1822
1839
|
/** The records this view holds: its Rule's members when it names one, the table otherwise. */
|
|
1823
|
-
declare function useViewRecords(view: SavedViewSpec, pageSize?: number): {
|
|
1840
|
+
declare function useViewRecords(view: SavedViewSpec, pageSize?: number, filter?: RecordFilter$1): {
|
|
1824
1841
|
rows: ReadRow$1[];
|
|
1825
1842
|
loading: boolean;
|
|
1826
1843
|
error: RecordsError | null;
|
|
1827
1844
|
/** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */
|
|
1828
1845
|
membership: string;
|
|
1829
1846
|
};
|
|
1830
|
-
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;
|
|
1831
1848
|
|
|
1832
1849
|
interface ViewBarProps {
|
|
1833
1850
|
/** The Table whose views these are. */
|
|
@@ -2169,8 +2186,16 @@ interface DigestSchedulerProps {
|
|
|
2169
2186
|
* view's name, so nothing in the list is called "Saved view".
|
|
2170
2187
|
*/
|
|
2171
2188
|
subjectName?: string | null | undefined;
|
|
2172
|
-
/**
|
|
2173
|
-
|
|
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;
|
|
2174
2199
|
onScheduled?: (() => void) | undefined;
|
|
2175
2200
|
onClose?: (() => void) | undefined;
|
|
2176
2201
|
className?: string | undefined;
|
|
@@ -2892,14 +2917,12 @@ interface TablePageProps {
|
|
|
2892
2917
|
/**
|
|
2893
2918
|
* WHICH FIELD THE ADDRESS WANTS THE BOARD'S COLUMNS TO BE, for this visit.
|
|
2894
2919
|
*
|
|
2895
|
-
* 🚨 THIS IS HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2896
|
-
*
|
|
2897
|
-
*
|
|
2898
|
-
*
|
|
2899
|
-
*
|
|
2900
|
-
*
|
|
2901
|
-
* with its columns set to the very field the chart grouped by, where the
|
|
2902
|
-
* 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.
|
|
2903
2926
|
*
|
|
2904
2927
|
* It overrides the saved view's own `groupField` for this visit only, exactly
|
|
2905
2928
|
* as `activeView` overrides its layout, and it is never written back.
|
|
@@ -2908,40 +2931,48 @@ interface TablePageProps {
|
|
|
2908
2931
|
/**
|
|
2909
2932
|
* WHAT THE PERSON CLICKED TO GET HERE — "Jobs by stage · Awaiting parts".
|
|
2910
2933
|
*
|
|
2911
|
-
* Present, the board says where they came from AND
|
|
2912
|
-
*
|
|
2913
|
-
*
|
|
2914
|
-
*
|
|
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.
|
|
2915
2939
|
*/
|
|
2916
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;
|
|
2917
2956
|
className?: string | undefined;
|
|
2918
2957
|
}
|
|
2919
|
-
/**
|
|
2920
|
-
* THE SENTENCE A TABLE YOU CANNOT SEE SAYS.
|
|
2921
|
-
*
|
|
2922
|
-
* Measured on the real screen (independent verdict, 19 September): opening a
|
|
2923
|
-
* table's page while another organization was active left the main area's text
|
|
2924
|
-
* "literally the empty string" after eighteen seconds — no sentence, no
|
|
2925
|
-
* spinner, no console error. A made-up id did the same. The cause is exactly
|
|
2926
|
-
* one line of this file: `custom.table_list` correctly answers the tables this
|
|
2927
|
-
* person can see in THIS organization, the table is not among them, so
|
|
2928
|
-
* `useTable` answers `{ data: null, error: null }` — not a refusal, just
|
|
2929
|
-
* absence — and the page rendered a skeleton for ever.
|
|
2930
|
-
*
|
|
2931
|
-
* Absence is an ANSWER and it gets a sentence. It deliberately does not say
|
|
2932
|
-
* whether the table exists: this person cannot see it, and which of the two it
|
|
2933
|
-
* is is not theirs to learn.
|
|
2934
|
-
*/
|
|
2935
2958
|
/**
|
|
2936
2959
|
* WHAT THE BOARD SAYS TO SOMEBODY A DASHBOARD NUMBER SENT HERE.
|
|
2937
2960
|
*
|
|
2938
|
-
*
|
|
2939
|
-
*
|
|
2940
|
-
*
|
|
2941
|
-
*
|
|
2942
|
-
*
|
|
2943
|
-
|
|
2944
|
-
|
|
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;
|
|
2945
2976
|
declare const TABLE_NOT_REACHABLE: string;
|
|
2946
2977
|
/**
|
|
2947
2978
|
* THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.
|
|
@@ -3050,7 +3081,7 @@ declare function openingView(activeView: string | null | undefined, activeDashbo
|
|
|
3050
3081
|
layout: ViewLayout | null;
|
|
3051
3082
|
unknown: string | null;
|
|
3052
3083
|
};
|
|
3053
|
-
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;
|
|
3054
3085
|
|
|
3055
3086
|
/** What the roster can tell us about a user id. `null` when it cannot. */
|
|
3056
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
|
|
@@ -1817,17 +1827,24 @@ interface ViewSwitcherProps {
|
|
|
1817
1827
|
/** "Who changed this?" from a grid cell — the host opens that column's timeline. */
|
|
1818
1828
|
onAskWhoChanged?: ((fieldKey: string, recordId: Uuid) => void) | undefined;
|
|
1819
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;
|
|
1820
1837
|
className?: string | undefined;
|
|
1821
1838
|
}
|
|
1822
1839
|
/** The records this view holds: its Rule's members when it names one, the table otherwise. */
|
|
1823
|
-
declare function useViewRecords(view: SavedViewSpec, pageSize?: number): {
|
|
1840
|
+
declare function useViewRecords(view: SavedViewSpec, pageSize?: number, filter?: RecordFilter$1): {
|
|
1824
1841
|
rows: ReadRow$1[];
|
|
1825
1842
|
loading: boolean;
|
|
1826
1843
|
error: RecordsError | null;
|
|
1827
1844
|
/** Where membership came from, in a sentence. A screen that hides this is hiding the view's meaning. */
|
|
1828
1845
|
membership: string;
|
|
1829
1846
|
};
|
|
1830
|
-
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;
|
|
1831
1848
|
|
|
1832
1849
|
interface ViewBarProps {
|
|
1833
1850
|
/** The Table whose views these are. */
|
|
@@ -2169,8 +2186,16 @@ interface DigestSchedulerProps {
|
|
|
2169
2186
|
* view's name, so nothing in the list is called "Saved view".
|
|
2170
2187
|
*/
|
|
2171
2188
|
subjectName?: string | null | undefined;
|
|
2172
|
-
/**
|
|
2173
|
-
|
|
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;
|
|
2174
2199
|
onScheduled?: (() => void) | undefined;
|
|
2175
2200
|
onClose?: (() => void) | undefined;
|
|
2176
2201
|
className?: string | undefined;
|
|
@@ -2892,14 +2917,12 @@ interface TablePageProps {
|
|
|
2892
2917
|
/**
|
|
2893
2918
|
* WHICH FIELD THE ADDRESS WANTS THE BOARD'S COLUMNS TO BE, for this visit.
|
|
2894
2919
|
*
|
|
2895
|
-
* 🚨 THIS IS HOW A DASHBOARD NUMBER CLICKS THROUGH (lane TAILS-6,
|
|
2896
|
-
*
|
|
2897
|
-
*
|
|
2898
|
-
*
|
|
2899
|
-
*
|
|
2900
|
-
*
|
|
2901
|
-
* with its columns set to the very field the chart grouped by, where the
|
|
2902
|
-
* 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.
|
|
2903
2926
|
*
|
|
2904
2927
|
* It overrides the saved view's own `groupField` for this visit only, exactly
|
|
2905
2928
|
* as `activeView` overrides its layout, and it is never written back.
|
|
@@ -2908,40 +2931,48 @@ interface TablePageProps {
|
|
|
2908
2931
|
/**
|
|
2909
2932
|
* WHAT THE PERSON CLICKED TO GET HERE — "Jobs by stage · Awaiting parts".
|
|
2910
2933
|
*
|
|
2911
|
-
* Present, the board says where they came from AND
|
|
2912
|
-
*
|
|
2913
|
-
*
|
|
2914
|
-
*
|
|
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.
|
|
2915
2939
|
*/
|
|
2916
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;
|
|
2917
2956
|
className?: string | undefined;
|
|
2918
2957
|
}
|
|
2919
|
-
/**
|
|
2920
|
-
* THE SENTENCE A TABLE YOU CANNOT SEE SAYS.
|
|
2921
|
-
*
|
|
2922
|
-
* Measured on the real screen (independent verdict, 19 September): opening a
|
|
2923
|
-
* table's page while another organization was active left the main area's text
|
|
2924
|
-
* "literally the empty string" after eighteen seconds — no sentence, no
|
|
2925
|
-
* spinner, no console error. A made-up id did the same. The cause is exactly
|
|
2926
|
-
* one line of this file: `custom.table_list` correctly answers the tables this
|
|
2927
|
-
* person can see in THIS organization, the table is not among them, so
|
|
2928
|
-
* `useTable` answers `{ data: null, error: null }` — not a refusal, just
|
|
2929
|
-
* absence — and the page rendered a skeleton for ever.
|
|
2930
|
-
*
|
|
2931
|
-
* Absence is an ANSWER and it gets a sentence. It deliberately does not say
|
|
2932
|
-
* whether the table exists: this person cannot see it, and which of the two it
|
|
2933
|
-
* is is not theirs to learn.
|
|
2934
|
-
*/
|
|
2935
2958
|
/**
|
|
2936
2959
|
* WHAT THE BOARD SAYS TO SOMEBODY A DASHBOARD NUMBER SENT HERE.
|
|
2937
2960
|
*
|
|
2938
|
-
*
|
|
2939
|
-
*
|
|
2940
|
-
*
|
|
2941
|
-
*
|
|
2942
|
-
*
|
|
2943
|
-
|
|
2944
|
-
|
|
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;
|
|
2945
2976
|
declare const TABLE_NOT_REACHABLE: string;
|
|
2946
2977
|
/**
|
|
2947
2978
|
* THE VIEW EVERY TABLE HAS, AND WHY IT IS NOT OPTIONAL.
|
|
@@ -3050,7 +3081,7 @@ declare function openingView(activeView: string | null | undefined, activeDashbo
|
|
|
3050
3081
|
layout: ViewLayout | null;
|
|
3051
3082
|
unknown: string | null;
|
|
3052
3083
|
};
|
|
3053
|
-
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;
|
|
3054
3085
|
|
|
3055
3086
|
/** What the roster can tell us about a user id. `null` when it cannot. */
|
|
3056
3087
|
type ResolveName = (userId: Uuid$1) => string | null;
|