@ai-matrx/records-ui 0.102.21 → 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 +9 -0
- package/dist/index.cjs +52 -16
- 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 +52 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
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
|
+
|
|
3
12
|
## 0.102.21
|
|
4
13
|
|
|
5
14
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
package/dist/index.cjs
CHANGED
|
@@ -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
|
] });
|
|
@@ -21789,7 +21813,8 @@ function GridBody({
|
|
|
21789
21813
|
newRowLabel,
|
|
21790
21814
|
sortOverride,
|
|
21791
21815
|
searchOverride,
|
|
21792
|
-
onSearchChange
|
|
21816
|
+
onSearchChange,
|
|
21817
|
+
searchBox = true
|
|
21793
21818
|
}) {
|
|
21794
21819
|
const toolbarSlot = useTableToolbarSlot();
|
|
21795
21820
|
const tableCard = (0, import_data_table11.useMatrxTableCard)();
|
|
@@ -22784,6 +22809,7 @@ function GridBody({
|
|
|
22784
22809
|
value: summaries.values[columnId2],
|
|
22785
22810
|
rowCount: summaries.rowCount,
|
|
22786
22811
|
summaries,
|
|
22812
|
+
calculate: embedded,
|
|
22787
22813
|
onChoose: (op2) => footerNow.current.choose(columnId2, op2)
|
|
22788
22814
|
}
|
|
22789
22815
|
);
|
|
@@ -23048,7 +23074,8 @@ function GridBody({
|
|
|
23048
23074
|
[storePaged, query, queryTotal, classicInCard, records.data?.total]
|
|
23049
23075
|
);
|
|
23050
23076
|
const showAddLine = mayAddRow && rows.length > 0;
|
|
23051
|
-
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;
|
|
23052
23079
|
const footerFace = JSON.stringify([
|
|
23053
23080
|
showAddLine ? added.busy : null,
|
|
23054
23081
|
showSummaryLine ? [chosenSummaries, summaries.values, summaries.rowCount, summaries.loading] : null
|
|
@@ -23151,10 +23178,11 @@ function GridBody({
|
|
|
23151
23178
|
search: !embedded,
|
|
23152
23179
|
// EMBEDDED: Notion's magnifier — the design system's own search group, a button that
|
|
23153
23180
|
// opens into a field. It is the same `query.search` the store's read asks.
|
|
23154
|
-
...embedded ? {
|
|
23181
|
+
...embedded && searchBox ? {
|
|
23155
23182
|
customSearch: /* @__PURE__ */ (0, import_jsx_runtime70.jsx)(
|
|
23156
23183
|
import_design_system60.TapTargetSearchGroup,
|
|
23157
23184
|
{
|
|
23185
|
+
surface: "solid",
|
|
23158
23186
|
placeholder: "Search",
|
|
23159
23187
|
value: searchOverride ?? query.search,
|
|
23160
23188
|
onValueChange: (term) => {
|
|
@@ -23366,7 +23394,8 @@ function GridBody({
|
|
|
23366
23394
|
noun,
|
|
23367
23395
|
embedded,
|
|
23368
23396
|
searchOverride,
|
|
23369
|
-
onSearchChange
|
|
23397
|
+
onSearchChange,
|
|
23398
|
+
searchBox
|
|
23370
23399
|
]
|
|
23371
23400
|
);
|
|
23372
23401
|
const labelOfField = (0, import_react113.useCallback)(
|
|
@@ -23588,7 +23617,7 @@ function GridBody({
|
|
|
23588
23617
|
!look.wrap && "[&_tbody_td]:max-w-[28rem] [&_tbody_td]:overflow-hidden [&_tbody_td]:text-ellipsis [&_tbody_td]:whitespace-nowrap! [&_tbody_td_*]:whitespace-nowrap!",
|
|
23589
23618
|
look.fit === "scroll" && "sm:[&>table]:w-max! sm:[&>table]:max-w-none! sm:[&>table]:min-w-full!",
|
|
23590
23619
|
embedded && EMBEDDED_TABLE_CLASS,
|
|
23591
|
-
embedded && !
|
|
23620
|
+
embedded && !calculationChosen && EMBEDDED_PLAIN_FOOTER_CLASS
|
|
23592
23621
|
),
|
|
23593
23622
|
footerRows,
|
|
23594
23623
|
...embedded ? { copy: false } : copyConfig ? { copy: copyConfig } : {},
|
|
@@ -32943,6 +32972,7 @@ function ViewSwitcher({
|
|
|
32943
32972
|
sortOverride,
|
|
32944
32973
|
searchOverride,
|
|
32945
32974
|
onSearchChange,
|
|
32975
|
+
searchBox,
|
|
32946
32976
|
newRowLabel,
|
|
32947
32977
|
className
|
|
32948
32978
|
}) {
|
|
@@ -33010,6 +33040,7 @@ function ViewSwitcher({
|
|
|
33010
33040
|
...sortOverride !== void 0 ? { sortOverride } : {},
|
|
33011
33041
|
...searchOverride !== void 0 ? { searchOverride } : {},
|
|
33012
33042
|
...onSearchChange ? { onSearchChange } : {},
|
|
33043
|
+
...searchBox === false ? { searchBox } : {},
|
|
33013
33044
|
...newRowLabel ? { newRowLabel } : {},
|
|
33014
33045
|
...filter ? { filter } : {},
|
|
33015
33046
|
...onClearFilter ? { onClearFilter } : {},
|
|
@@ -47661,6 +47692,7 @@ function TablePage({
|
|
|
47661
47692
|
newRowLabel,
|
|
47662
47693
|
searchOverride,
|
|
47663
47694
|
onSearchChange,
|
|
47695
|
+
searchBox,
|
|
47664
47696
|
pageSize: pageSizeAsked,
|
|
47665
47697
|
seedViews,
|
|
47666
47698
|
onLeave,
|
|
@@ -48550,6 +48582,7 @@ function TablePage({
|
|
|
48550
48582
|
...newRowLabel ? { newRowLabel } : {},
|
|
48551
48583
|
...searchOverride !== void 0 ? { searchOverride } : {},
|
|
48552
48584
|
...onSearchChange ? { onSearchChange } : {},
|
|
48585
|
+
...searchBox === false ? { searchBox } : {},
|
|
48553
48586
|
footer,
|
|
48554
48587
|
openExport: () => setRail("export"),
|
|
48555
48588
|
view: {
|
|
@@ -48856,6 +48889,7 @@ function EntityTablePageBody({
|
|
|
48856
48889
|
presentation = "page",
|
|
48857
48890
|
searchOverride,
|
|
48858
48891
|
onSearchChange,
|
|
48892
|
+
searchBox = true,
|
|
48859
48893
|
pageSize = presentation === "embedded" ? EMBEDDED_PAGE_SIZE : 100,
|
|
48860
48894
|
layout: opened = "grid",
|
|
48861
48895
|
onLayoutChange,
|
|
@@ -48943,9 +48977,10 @@ function EntityTablePageBody({
|
|
|
48943
48977
|
] }) : null,
|
|
48944
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,
|
|
48945
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: [
|
|
48946
|
-
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)(
|
|
48947
48981
|
import_design_system141.TapTargetSearchGroup,
|
|
48948
48982
|
{
|
|
48983
|
+
surface: "solid",
|
|
48949
48984
|
placeholder: "Search",
|
|
48950
48985
|
value: term,
|
|
48951
48986
|
onValueChange: (next) => {
|
|
@@ -48982,6 +49017,7 @@ function TablePage2(props) {
|
|
|
48982
49017
|
...rest.pageSize ? { pageSize: rest.pageSize } : {},
|
|
48983
49018
|
...rest.searchOverride !== void 0 ? { searchOverride: rest.searchOverride } : {},
|
|
48984
49019
|
...rest.onSearchChange ? { onSearchChange: rest.onSearchChange } : {},
|
|
49020
|
+
...rest.searchBox === false ? { searchBox: false } : {},
|
|
48985
49021
|
...layout ? { layout } : {},
|
|
48986
49022
|
...onLayoutChange ? { onLayoutChange } : {},
|
|
48987
49023
|
...groupBy ? { groupBy } : {},
|