@ai-matrx/records-ui 0.102.20 → 0.103.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 +15 -0
- package/dist/index.cjs +54 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +54 -19
- package/dist/index.js.map +1 -1
- package/dist/pickers.cjs.map +1 -1
- package/dist/pickers.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog — @ai-matrx/records-ui
|
|
2
2
|
|
|
3
|
+
## 0.103.0
|
|
4
|
+
|
|
5
|
+
- **Notion's calculation row on the embedded grid** (Spaces N6): every column's footer cell says "Calculate" on hover and offers Notion's list in Notion's words — Count all · Count unique values · Count empty · Count not empty · Percent empty · Percent not empty · Sum · Average · Median · Min · Max · Range — narrowed to what the column can mean and to the store's `custom.agg_operations`. The pick is reported through `onPresentationChange` as `summaries` (unchanged door). The band stays plain until one is picked.
|
|
6
|
+
- The summary bar knows the store's three newer measures `percent_empty`, `percent_filled` (shown as a percent) and `range` (a date column's range in days).
|
|
7
|
+
- `searchBox={false}` on `Grid` / `ViewSwitcher` / `TablePage` (and the built-in source's embedded views): the embedded grid draws no magnifier, for a host that draws its own and hands the term through `searchOverride` (Spaces N-19).
|
|
8
|
+
- Both embedded magnifiers are `TapTargetSearchGroup surface="solid"` — no more `[tap-target] glass on a solid surface` on a page. Needs design-system 0.72.1.
|
|
9
|
+
|
|
10
|
+
**Consumer action:** none required. A host drawing its own search field may pass `searchBox={false}`.
|
|
11
|
+
|
|
12
|
+
## 0.102.21
|
|
13
|
+
|
|
14
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
15
|
+
`git diff npm/records-ui/v0.102.20..npm/records-ui/v0.102.21 -- apps/shared/records-ui`).
|
|
16
|
+
No source changes intended and no consumer action required.
|
|
17
|
+
|
|
3
18
|
## 0.102.20
|
|
4
19
|
|
|
5
20
|
- `readTableShapes` reads markdown tables through THE GFM rule (`tableStartsAt` / `findTableEnd` / `rowCells` from `@ai-matrx/content-ir/source`) instead of a private pipe splitter and delimiter regex: edge pipes optional, `\|` stays in its cell, and the table ends where chat and the editor end it (AP-2).
|
package/dist/index.cjs
CHANGED
|
@@ -7138,7 +7138,7 @@ function RecordValue({
|
|
|
7138
7138
|
}
|
|
7139
7139
|
if (inCell && ui.grid === "merged" && ui.renderText && typeof value === "string" && value.trim() !== "" && editorKindFor(field2) === "long_text" && !shownAsOf(field2) && !(0, import_core4.wholeValueOf)(document2, field2.key) && !envelopeFor(document2, field2.key)?.absent && // A long-text cell holding a kind is drawn by the kind system below, not as markdown.
|
|
7140
7140
|
!kindValueOf(value)) {
|
|
7141
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "block
|
|
7141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "block h-[1.5em] min-w-0 overflow-hidden whitespace-normal", "data-records-cell-text": "", children: ui.renderText(value, "cell") });
|
|
7142
7142
|
}
|
|
7143
7143
|
if (isSignatureField(field2) && value !== null && value !== void 0 && value !== "") {
|
|
7144
7144
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SignatureValue, { value, inCell, recordId, fieldKey: field2.key, document: document2 });
|
|
@@ -10520,8 +10520,29 @@ var MEASURE_LABEL = {
|
|
|
10520
10520
|
median: "Median",
|
|
10521
10521
|
filled: "Filled",
|
|
10522
10522
|
empty: "Empty",
|
|
10523
|
-
unique: "Unique"
|
|
10523
|
+
unique: "Unique",
|
|
10524
|
+
percent_empty: "Percent empty",
|
|
10525
|
+
percent_filled: "Percent filled",
|
|
10526
|
+
range: "Range"
|
|
10524
10527
|
};
|
|
10528
|
+
var NOTION_CALCULATIONS = [
|
|
10529
|
+
{ op: "count", menu: "Count all", footer: "Count" },
|
|
10530
|
+
{ op: "unique", menu: "Count unique values", footer: "Unique" },
|
|
10531
|
+
{ op: "empty", menu: "Count empty", footer: "Empty" },
|
|
10532
|
+
{ op: "filled", menu: "Count not empty", footer: "Not empty" },
|
|
10533
|
+
{ op: "percent_empty", menu: "Percent empty", footer: "Empty" },
|
|
10534
|
+
{ op: "percent_filled", menu: "Percent not empty", footer: "Not empty" },
|
|
10535
|
+
{ op: "sum", menu: "Sum", footer: "Sum" },
|
|
10536
|
+
{ op: "avg", menu: "Average", footer: "Average" },
|
|
10537
|
+
{ op: "median", menu: "Median", footer: "Median" },
|
|
10538
|
+
{ op: "min", menu: "Min", footer: "Min" },
|
|
10539
|
+
{ op: "max", menu: "Max", footer: "Max" },
|
|
10540
|
+
{ op: "range", menu: "Range", footer: "Range" }
|
|
10541
|
+
];
|
|
10542
|
+
function calculationsFor(field2, storeOps) {
|
|
10543
|
+
const offered = new Set(measuresFor(field2, storeOps, true));
|
|
10544
|
+
return NOTION_CALCULATIONS.filter((c) => offered.has(c.op));
|
|
10545
|
+
}
|
|
10525
10546
|
var NUMERIC_ONLY = /* @__PURE__ */ new Set(["sum", "avg", "median"]);
|
|
10526
10547
|
var ARITHMETIC2 = /* @__PURE__ */ new Set([
|
|
10527
10548
|
"add",
|
|
@@ -10539,7 +10560,7 @@ var ARITHMETIC2 = /* @__PURE__ */ new Set([
|
|
|
10539
10560
|
"ceiling",
|
|
10540
10561
|
"floor"
|
|
10541
10562
|
]);
|
|
10542
|
-
var ORDERED = /* @__PURE__ */ new Set(["min", "max"]);
|
|
10563
|
+
var ORDERED = /* @__PURE__ */ new Set(["min", "max", "range"]);
|
|
10543
10564
|
function isNumericField(field2) {
|
|
10544
10565
|
const kind = editorKindFor(field2);
|
|
10545
10566
|
if (kind === "number" || kind === "currency" || kind === "percent" || kind === "rollup") return true;
|
|
@@ -13769,14 +13790,17 @@ function SummaryCell({
|
|
|
13769
13790
|
value,
|
|
13770
13791
|
rowCount,
|
|
13771
13792
|
summaries,
|
|
13772
|
-
onChoose
|
|
13793
|
+
onChoose,
|
|
13794
|
+
calculate = false
|
|
13773
13795
|
}) {
|
|
13774
13796
|
const offered = (0, import_react73.useMemo)(
|
|
13775
|
-
() => summaries.operations ? measuresFor(field2, summaries.operations, firstColumn) : null,
|
|
13776
|
-
[summaries.operations, field2, firstColumn]
|
|
13797
|
+
() => summaries.operations ? calculate ? calculationsFor(field2, summaries.operations).map((c) => c.op) : measuresFor(field2, summaries.operations, firstColumn) : null,
|
|
13798
|
+
[summaries.operations, field2, firstColumn, calculate]
|
|
13777
13799
|
);
|
|
13778
|
-
const
|
|
13779
|
-
const
|
|
13800
|
+
const words2 = (op2, where) => calculate ? NOTION_CALCULATIONS.find((c) => c.op === op2)?.[where] ?? MEASURE_LABEL[op2] ?? op2 : MEASURE_LABEL[op2] ?? op2;
|
|
13801
|
+
const label = chosen ? words2(chosen, "footer") : null;
|
|
13802
|
+
const isDate4 = editorKindFor(field2) === "datetime";
|
|
13803
|
+
const shown4 = chosen === void 0 ? null : summaries.loading && value === void 0 ? "\u2026" : value === null || value === void 0 ? "\u2014" : chosen === "count" || chosen === "filled" || chosen === "empty" || chosen === "unique" ? String(value) : chosen === "percent_empty" || chosen === "percent_filled" ? `${Number(value.toFixed(2))}%` : chosen === "range" && isDate4 ? `${Math.round(value)} day${Math.round(value) === 1 ? "" : "s"}` : null;
|
|
13780
13804
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_design_system42.DropdownMenu, { onOpenChange: (open) => open ? summaries.askOperations() : void 0, children: [
|
|
13781
13805
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system42.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
13782
13806
|
import_design_system42.Button,
|
|
@@ -13798,7 +13822,7 @@ function SummaryCell({
|
|
|
13798
13822
|
// AGG-WITHHELD: the store withheld this column from her — say so, never a bare dash.
|
|
13799
13823
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(WithheldValue, { field: field2, notice: summaries.withheld[field2.key] }) })
|
|
13800
13824
|
) : shown4 !== null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium tabular-nums", children: shown4 }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium tabular-nums", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(RecordValue, { field: field2, value, format: formatForField(field2) }) })
|
|
13801
|
-
] }) : "Summarize"
|
|
13825
|
+
] }) : calculate ? "Calculate" : "Summarize"
|
|
13802
13826
|
}
|
|
13803
13827
|
) }),
|
|
13804
13828
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_design_system42.DropdownMenuContent, { align: "start", children: [
|
|
@@ -13809,13 +13833,13 @@ function SummaryCell({
|
|
|
13809
13833
|
"data-records-summary-choice": op2,
|
|
13810
13834
|
onSelect: () => onChoose(op2),
|
|
13811
13835
|
className: (0, import_design_system42.cn)(op2 === chosen && "font-medium"),
|
|
13812
|
-
children:
|
|
13836
|
+
children: words2(op2, "menu")
|
|
13813
13837
|
},
|
|
13814
13838
|
op2
|
|
13815
13839
|
)),
|
|
13816
13840
|
chosen ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
13817
13841
|
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system42.DropdownMenuSeparator, {}),
|
|
13818
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system42.DropdownMenuItem, { onSelect: () => onChoose(null), children: "No summary" })
|
|
13842
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_design_system42.DropdownMenuItem, { onSelect: () => onChoose(null), children: calculate ? "None" : "No summary" })
|
|
13819
13843
|
] }) : null
|
|
13820
13844
|
] })
|
|
13821
13845
|
] });
|
|
@@ -20492,7 +20516,6 @@ function UndoRedoLive({ source }) {
|
|
|
20492
20516
|
}
|
|
20493
20517
|
function UndoRedoPair({ face, onUndo, onRedo }) {
|
|
20494
20518
|
const undo = { depth: { back: face.back, forward: face.forward }, busy: face.busy };
|
|
20495
|
-
if (undo.depth.back === 0 && undo.depth.forward === 0) return null;
|
|
20496
20519
|
return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(import_jsx_runtime66.Fragment, { children: [
|
|
20497
20520
|
/* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
|
|
20498
20521
|
import_design_system57.Button,
|
|
@@ -21790,7 +21813,8 @@ function GridBody({
|
|
|
21790
21813
|
newRowLabel,
|
|
21791
21814
|
sortOverride,
|
|
21792
21815
|
searchOverride,
|
|
21793
|
-
onSearchChange
|
|
21816
|
+
onSearchChange,
|
|
21817
|
+
searchBox = true
|
|
21794
21818
|
}) {
|
|
21795
21819
|
const toolbarSlot = useTableToolbarSlot();
|
|
21796
21820
|
const tableCard = (0, import_data_table11.useMatrxTableCard)();
|
|
@@ -22785,6 +22809,7 @@ function GridBody({
|
|
|
22785
22809
|
value: summaries.values[columnId2],
|
|
22786
22810
|
rowCount: summaries.rowCount,
|
|
22787
22811
|
summaries,
|
|
22812
|
+
calculate: embedded,
|
|
22788
22813
|
onChoose: (op2) => footerNow.current.choose(columnId2, op2)
|
|
22789
22814
|
}
|
|
22790
22815
|
);
|
|
@@ -23049,7 +23074,8 @@ function GridBody({
|
|
|
23049
23074
|
[storePaged, query, queryTotal, classicInCard, records.data?.total]
|
|
23050
23075
|
);
|
|
23051
23076
|
const showAddLine = mayAddRow && rows.length > 0;
|
|
23052
|
-
const showSummaryLine = rows.length > 0 && (embedded
|
|
23077
|
+
const showSummaryLine = rows.length > 0 && (embedded || !merged || Object.keys(chosenSummaries).length > 0);
|
|
23078
|
+
const calculationChosen = Object.keys(chosenSummaries).length > 0;
|
|
23053
23079
|
const footerFace = JSON.stringify([
|
|
23054
23080
|
showAddLine ? added.busy : null,
|
|
23055
23081
|
showSummaryLine ? [chosenSummaries, summaries.values, summaries.rowCount, summaries.loading] : null
|
|
@@ -23152,10 +23178,11 @@ function GridBody({
|
|
|
23152
23178
|
search: !embedded,
|
|
23153
23179
|
// EMBEDDED: Notion's magnifier — the design system's own search group, a button that
|
|
23154
23180
|
// opens into a field. It is the same `query.search` the store's read asks.
|
|
23155
|
-
...embedded ? {
|
|
23181
|
+
...embedded && searchBox ? {
|
|
23156
23182
|
customSearch: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
|
|
23157
23183
|
import_design_system60.TapTargetSearchGroup,
|
|
23158
23184
|
{
|
|
23185
|
+
surface: "solid",
|
|
23159
23186
|
placeholder: "Search",
|
|
23160
23187
|
value: searchOverride ?? query.search,
|
|
23161
23188
|
onValueChange: (term) => {
|
|
@@ -23367,7 +23394,8 @@ function GridBody({
|
|
|
23367
23394
|
noun,
|
|
23368
23395
|
embedded,
|
|
23369
23396
|
searchOverride,
|
|
23370
|
-
onSearchChange
|
|
23397
|
+
onSearchChange,
|
|
23398
|
+
searchBox
|
|
23371
23399
|
]
|
|
23372
23400
|
);
|
|
23373
23401
|
const labelOfField = (0, import_react113.useCallback)(
|
|
@@ -23569,7 +23597,7 @@ function GridBody({
|
|
|
23569
23597
|
{
|
|
23570
23598
|
...fills ? { className: "min-h-0 flex-1" } : {},
|
|
23571
23599
|
frameHeight: fills ? "fill" : "content",
|
|
23572
|
-
loadingRows: rememberedRowCount(rowMemoryKey, pageSize, fills ? "fill" : 5),
|
|
23600
|
+
loadingRows: rememberedRowCount(rowMemoryKey, pageSize, embedded ? fills ? "fill" : 5 : rememberedRowCount(`${tableId}:page:last`, pageSize, fills ? "fill" : 5)),
|
|
23573
23601
|
...!look.rowHeight ? { loadingRowHeight: RECORDS_GRID_ROW_PX } : {},
|
|
23574
23602
|
data: rows,
|
|
23575
23603
|
columns: tableColumns,
|
|
@@ -23589,7 +23617,7 @@ function GridBody({
|
|
|
23589
23617
|
!look.wrap && "[&_tbody_td]:max-w-[28rem] [&_tbody_td]:overflow-hidden [&_tbody_td]:text-ellipsis [&_tbody_td]:whitespace-nowrap! [&_tbody_td_*]:whitespace-nowrap!",
|
|
23590
23618
|
look.fit === "scroll" && "sm:[&>table]:w-max! sm:[&>table]:max-w-none! sm:[&>table]:min-w-full!",
|
|
23591
23619
|
embedded && EMBEDDED_TABLE_CLASS,
|
|
23592
|
-
embedded && !
|
|
23620
|
+
embedded && !calculationChosen && EMBEDDED_PLAIN_FOOTER_CLASS
|
|
23593
23621
|
),
|
|
23594
23622
|
footerRows,
|
|
23595
23623
|
...embedded ? { copy: false } : copyConfig ? { copy: copyConfig } : {},
|
|
@@ -32944,6 +32972,7 @@ function ViewSwitcher({
|
|
|
32944
32972
|
sortOverride,
|
|
32945
32973
|
searchOverride,
|
|
32946
32974
|
onSearchChange,
|
|
32975
|
+
searchBox,
|
|
32947
32976
|
newRowLabel,
|
|
32948
32977
|
className
|
|
32949
32978
|
}) {
|
|
@@ -33011,6 +33040,7 @@ function ViewSwitcher({
|
|
|
33011
33040
|
...sortOverride !== void 0 ? { sortOverride } : {},
|
|
33012
33041
|
...searchOverride !== void 0 ? { searchOverride } : {},
|
|
33013
33042
|
...onSearchChange ? { onSearchChange } : {},
|
|
33043
|
+
...searchBox === false ? { searchBox } : {},
|
|
33014
33044
|
...newRowLabel ? { newRowLabel } : {},
|
|
33015
33045
|
...filter ? { filter } : {},
|
|
33016
33046
|
...onClearFilter ? { onClearFilter } : {},
|
|
@@ -47662,6 +47692,7 @@ function TablePage({
|
|
|
47662
47692
|
newRowLabel,
|
|
47663
47693
|
searchOverride,
|
|
47664
47694
|
onSearchChange,
|
|
47695
|
+
searchBox,
|
|
47665
47696
|
pageSize: pageSizeAsked,
|
|
47666
47697
|
seedViews,
|
|
47667
47698
|
onLeave,
|
|
@@ -48551,6 +48582,7 @@ function TablePage({
|
|
|
48551
48582
|
...newRowLabel ? { newRowLabel } : {},
|
|
48552
48583
|
...searchOverride !== void 0 ? { searchOverride } : {},
|
|
48553
48584
|
...onSearchChange ? { onSearchChange } : {},
|
|
48585
|
+
...searchBox === false ? { searchBox } : {},
|
|
48554
48586
|
footer,
|
|
48555
48587
|
openExport: () => setRail("export"),
|
|
48556
48588
|
view: {
|
|
@@ -48857,6 +48889,7 @@ function EntityTablePageBody({
|
|
|
48857
48889
|
presentation = "page",
|
|
48858
48890
|
searchOverride,
|
|
48859
48891
|
onSearchChange,
|
|
48892
|
+
searchBox = true,
|
|
48860
48893
|
pageSize = presentation === "embedded" ? EMBEDDED_PAGE_SIZE : 100,
|
|
48861
48894
|
layout: opened = "grid",
|
|
48862
48895
|
onLayoutChange,
|
|
@@ -48944,9 +48977,10 @@ function EntityTablePageBody({
|
|
|
48944
48977
|
] }) : null,
|
|
48945
48978
|
addRefused ? /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(import_design_system142.ErrorBox, { className: "rounded border border-destructive/40 px-1.5 py-1 text-xs text-destructive", message: addRefused, operation: "Add a row", origin: "records-ui/entityViews" }) : null,
|
|
48946
48979
|
entity.error ? /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("p", { className: "px-1 py-3 text-xs text-muted-foreground", children: `This table could not be read: ${entity.error}` }) : layout === "board" && boardable ? /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(EntityBoard, { entity, groupBy, onOpenRecord }) : /* @__PURE__ */ (0, import_jsx_runtime156.jsxs)(import_jsx_runtime156.Fragment, { children: [
|
|
48947
|
-
presentation === "embedded" ? /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("div", { className: "flex min-w-0 items-center justify-end", "data-records-entity-search": "", children: /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(import_design_system141.TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(
|
|
48980
|
+
presentation === "embedded" && searchBox ? /* @__PURE__ */ (0, import_jsx_runtime156.jsx)("div", { className: "flex min-w-0 items-center justify-end", "data-records-entity-search": "", children: /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(import_design_system141.TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime156.jsx)(
|
|
48948
48981
|
import_design_system141.TapTargetSearchGroup,
|
|
48949
48982
|
{
|
|
48983
|
+
surface: "solid",
|
|
48950
48984
|
placeholder: "Search",
|
|
48951
48985
|
value: term,
|
|
48952
48986
|
onValueChange: (next) => {
|
|
@@ -48983,6 +49017,7 @@ function TablePage2(props) {
|
|
|
48983
49017
|
...rest.pageSize ? { pageSize: rest.pageSize } : {},
|
|
48984
49018
|
...rest.searchOverride !== void 0 ? { searchOverride: rest.searchOverride } : {},
|
|
48985
49019
|
...rest.onSearchChange ? { onSearchChange: rest.onSearchChange } : {},
|
|
49020
|
+
...rest.searchBox === false ? { searchBox: false } : {},
|
|
48986
49021
|
...layout ? { layout } : {},
|
|
48987
49022
|
...onLayoutChange ? { onLayoutChange } : {},
|
|
48988
49023
|
...groupBy ? { groupBy } : {},
|