@sincpro/web-ui 0.1.0 → 0.2.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/README.md +37 -10
- package/dist/components/activity/Activity.d.ts +69 -0
- package/dist/components/activity/Activity.js +279 -0
- package/dist/components/{chatter → activity}/Messages.d.ts +2 -2
- package/dist/components/{chatter → activity}/Messages.js +9 -6
- package/dist/components/{chatter → activity}/index.d.ts +1 -1
- package/dist/components/activity/index.js +4 -0
- package/dist/components/assist/AssistMark.d.ts +3 -3
- package/dist/components/assist/AssistMark.js +1 -1
- package/dist/components/assist/assist.d.ts +1 -1
- package/dist/components/assist/assist.js +1 -1
- package/dist/components/form/Sheet.d.ts +4 -0
- package/dist/components/form/Sheet.js +11 -4
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/lines/LineItems.d.ts +42 -5
- package/dist/components/lines/LineItems.js +106 -18
- package/dist/components/listing/Listing.js +1 -1
- package/dist/components/listing/ListingBar.d.ts +41 -2
- package/dist/components/listing/ListingBar.js +43 -4
- package/dist/components/listing/Row.d.ts +5 -1
- package/dist/components/listing/Row.js +3 -2
- package/dist/components/record/RecordHeader.d.ts +21 -17
- package/dist/components/record/RecordHeader.js +46 -14
- package/dist/components/record/RecordNotices.d.ts +37 -0
- package/dist/components/record/RecordNotices.js +75 -0
- package/dist/components/record/ThumbBar.js +1 -1
- package/dist/foundations/copy.d.ts +96 -12
- package/dist/foundations/copy.es.js +63 -10
- package/dist/foundations/copy.js +55 -7
- package/dist/primitives/choice/ComboBox.d.ts +3 -0
- package/dist/primitives/choice/ComboBox.js +2 -2
- package/dist/primitives/choice/SearchField.d.ts +10 -1
- package/dist/primitives/choice/SearchField.js +21 -2
- package/dist/primitives/date/Calendar.js +30 -6
- package/dist/primitives/date/DatePicker.d.ts +11 -3
- package/dist/primitives/date/DatePicker.js +12 -8
- package/dist/primitives/date/DateTime.d.ts +35 -0
- package/dist/primitives/date/DateTime.js +100 -0
- package/dist/primitives/date/index.d.ts +1 -0
- package/dist/primitives/date/index.js +4 -2
- package/dist/primitives/dialog/Drill.d.ts +90 -0
- package/dist/primitives/dialog/Drill.js +172 -0
- package/dist/primitives/dialog/index.d.ts +1 -0
- package/dist/primitives/dialog/index.js +2 -0
- package/dist/primitives/field/DropZone.js +1 -1
- package/dist/primitives/field/Field.d.ts +14 -2
- package/dist/primitives/field/Field.js +25 -14
- package/dist/primitives/field/copy.d.ts +16 -0
- package/dist/primitives/field/copy.js +69 -0
- package/dist/primitives/field/index.d.ts +2 -0
- package/dist/primitives/field/index.js +4 -0
- package/dist/primitives/field/note.d.ts +55 -0
- package/dist/primitives/field/note.js +117 -0
- package/dist/primitives/index.d.ts +1 -0
- package/dist/primitives/index.js +1 -0
- package/dist/primitives/menu/Menu.d.ts +28 -0
- package/dist/primitives/menu/Menu.js +47 -17
- package/dist/primitives/notice/Callout.js +1 -1
- package/dist/primitives/notice/Flag.d.ts +13 -0
- package/dist/primitives/notice/Flag.js +31 -0
- package/dist/primitives/notice/index.d.ts +1 -0
- package/dist/primitives/notice/index.js +1 -0
- package/dist/primitives/overlay/Preview.d.ts +19 -0
- package/dist/primitives/overlay/Preview.js +60 -0
- package/dist/primitives/overlay/index.d.ts +1 -0
- package/dist/primitives/overlay/index.js +3 -1
- package/dist/primitives/picker/Picker.d.ts +41 -0
- package/dist/primitives/picker/Picker.js +62 -8
- package/dist/primitives/table/CellCopy.d.ts +20 -0
- package/dist/primitives/table/CellCopy.js +23 -0
- package/dist/primitives/table/DataTable.d.ts +55 -1
- package/dist/primitives/table/DataTable.js +126 -40
- package/dist/primitives/table/EditableTable.d.ts +97 -2
- package/dist/primitives/table/EditableTable.js +223 -29
- package/dist/primitives/table/SheetTable.d.ts +4 -1
- package/dist/primitives/table/SheetTable.js +38 -5
- package/dist/primitives/table/index.d.ts +2 -2
- package/dist/primitives/table/index.js +1 -1
- package/dist/primitives/tabs/Tabs.d.ts +2 -2
- package/dist/primitives/tabs/Tabs.js +1 -1
- package/dist/primitives/tag/TagsField.d.ts +3 -0
- package/dist/primitives/tag/TagsField.js +6 -2
- package/dist/primitives/tree/Tree.d.ts +56 -0
- package/dist/primitives/tree/Tree.js +74 -0
- package/dist/primitives/tree/index.d.ts +1 -0
- package/dist/primitives/tree/index.js +3 -0
- package/dist/primitives/value/Copyable.d.ts +11 -0
- package/dist/primitives/value/Copyable.js +27 -6
- package/dist/primitives/value/Fecha.js +10 -1
- package/dist/primitives/value/ProgressBar.d.ts +31 -0
- package/dist/primitives/value/ProgressBar.js +53 -0
- package/dist/primitives/value/Relation.d.ts +6 -1
- package/dist/primitives/value/Relation.js +27 -10
- package/dist/primitives/value/Totals.d.ts +102 -7
- package/dist/primitives/value/Totals.js +52 -2
- package/dist/primitives/value/Value.d.ts +0 -37
- package/dist/primitives/value/Value.js +0 -39
- package/dist/primitives/value/index.d.ts +4 -3
- package/dist/primitives/value/index.js +4 -3
- package/dist/tokens.css +44 -7
- package/dist/views/list/List.d.ts +8 -2
- package/dist/views/list/List.js +6 -2
- package/dist/views/list/ListView.d.ts +1 -1
- package/dist/views/list/ListView.js +34 -8
- package/dist/views/list/derive.d.ts +12 -1
- package/dist/views/list/derive.js +29 -3
- package/dist/views/list/presentations.d.ts +2 -2
- package/dist/views/list/presentations.js +5 -3
- package/dist/views/list/types.d.ts +13 -1
- package/dist/views/record/Record.d.ts +27 -8
- package/dist/views/record/Record.js +97 -27
- package/dist/views/record/index.d.ts +1 -1
- package/package.json +5 -1
- package/dist/components/chatter/Chatter.d.ts +0 -161
- package/dist/components/chatter/Chatter.js +0 -232
- package/dist/components/chatter/index.js +0 -4
- /package/dist/components/{chatter → activity}/Timeline.d.ts +0 -0
- /package/dist/components/{chatter → activity}/Timeline.js +0 -0
|
@@ -47,45 +47,6 @@ export function Numeric({ value, unit, format = "integer", }) {
|
|
|
47
47
|
: formatCount(value);
|
|
48
48
|
return (_jsxs("span", { className: "block text-right text-body tabular-nums whitespace-nowrap text-ink", children: [_jsx("span", { className: "tabular-nums", children: text }), unit === undefined ? null : _jsx("span", { className: "ml-1 text-muted", children: unit })] }));
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
51
|
-
* A real bar, never a spinner.
|
|
52
|
-
*
|
|
53
|
-
* Context: a spinner says «wait» and doesn't say how much; a bar says both
|
|
54
|
-
* things.
|
|
55
|
-
*
|
|
56
|
-
* ── Why the fill is FLAT and the gradient is asked for ──────────────
|
|
57
|
-
*
|
|
58
|
-
* The bar always lived with `bar-brand`, the blue→gold gradient. At 3 px and at
|
|
59
|
-
* 62 % that doesn't read as a brand: it reads as a blue bar with a broken tip.
|
|
60
|
-
* A gradient needs length to be a gradient, and a bar inside a list row doesn't
|
|
61
|
-
* have it.
|
|
62
|
-
*
|
|
63
|
-
* Now the fill is a flat tone —and the tone SAYS something: `good` finished,
|
|
64
|
-
* `warn` is running slow, `bad` failed— and the gradient is asked for with
|
|
65
|
-
* `tone="brand"`, which is the long bar of a live import: there it does have room
|
|
66
|
-
* to be read.
|
|
67
|
-
*
|
|
68
|
-
* And it got fatter, from 3 px to 6 px. At 3 px it isn't a bar, it's a line: it
|
|
69
|
-
* can't be told apart from a separator and the fill isn't visible unless it goes
|
|
70
|
-
* past 20 %.
|
|
71
|
-
*/
|
|
72
|
-
export function ProgressBar({ value, label, width = "w-24", tone = "brand",
|
|
73
|
-
/** The percentage next to it. It is turned off when the bar lives inside
|
|
74
|
-
* something that already says the figure —a cell with its column— and it
|
|
75
|
-
* would only mean reading it twice. */
|
|
76
|
-
showValue = true, }) {
|
|
77
|
-
const clamped = Math.max(0, Math.min(100, Math.round(value)));
|
|
78
|
-
const fill = tone === "brand" ? "bar-brand" : FILL[tone];
|
|
79
|
-
return (_jsxs("span", { className: "flex items-center gap-2", children: [_jsx("span", { className: `h-(--size-track) overflow-hidden rounded-pill bg-ink/10 ${width}`, role: "progressbar", "aria-valuenow": clamped, "aria-valuemin": 0, "aria-valuemax": 100, "aria-label": label, children: _jsx("span", { className: `block h-full rounded-pill transition-[width] duration-(--duration-panel) ease-out ${fill}`, style: { width: `${clamped}%` } }) }), showValue ? (_jsxs("span", { className: "text-meta tabular-nums text-muted", children: [clamped, "%"] })) : null] }));
|
|
80
|
-
}
|
|
81
|
-
const FILL = {
|
|
82
|
-
neutral: "bg-muted",
|
|
83
|
-
info: "bg-info",
|
|
84
|
-
good: "bg-good",
|
|
85
|
-
warn: "bg-warn",
|
|
86
|
-
bad: "bg-bad",
|
|
87
|
-
accent: "bg-accent",
|
|
88
|
-
};
|
|
89
50
|
/**
|
|
90
51
|
* The content of a data cell, with what the system decides and the view does not.
|
|
91
52
|
*
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
export { Copyable, type CopyableProps } from "./Copyable.js";
|
|
1
|
+
export { Copyable, type CopyableProps, CopyButton, } from "./Copyable.js";
|
|
2
2
|
export { DateValue, formatDateTime, formatRelative, } from "./Fecha.js";
|
|
3
3
|
export { Meter, type MeterLevel, meterLevel, type MeterProps, type MeterThresholds, } from "./Meter.js";
|
|
4
4
|
export { Metric, type MetricProps, Metrics } from "./Metric.js";
|
|
5
5
|
export { Avatar, type AvatarSize, ContactCard, type ContactCardProps, type PersonContact, UserChip, type UserChipProps, UserStack, } from "./Person.js";
|
|
6
|
+
export { ProgressBar, type ProgressBarProps, } from "./ProgressBar.js";
|
|
6
7
|
export { RelationCard, type RelationCardProps, type RelationSummary, RelationValue, type RelationValueProps, } from "./Relation.js";
|
|
7
|
-
export { Totals, type TotalsRow } from "./Totals.js";
|
|
8
|
-
export { Cell, formatCount, formatDistance, formatNumber, KeyValue, Numeric,
|
|
8
|
+
export { Totals, type TotalsCredit, type TotalsDeduction, type TotalsFact, type TotalsProps, type TotalsRow, } from "./Totals.js";
|
|
9
|
+
export { Cell, formatCount, formatDistance, formatNumber, KeyValue, Numeric, } from "./Value.js";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* Show a number or a datum so that it reads as such and not as text. */
|
|
2
|
-
export { Copyable } from "./Copyable.js";
|
|
2
|
+
export { Copyable, CopyButton, } from "./Copyable.js";
|
|
3
3
|
export { DateValue, formatDateTime, formatRelative, } from "./Fecha.js";
|
|
4
4
|
export { Meter, meterLevel, } from "./Meter.js";
|
|
5
5
|
export { Metric, Metrics } from "./Metric.js";
|
|
6
6
|
export { Avatar, ContactCard, UserChip, UserStack, } from "./Person.js";
|
|
7
|
+
export { ProgressBar, } from "./ProgressBar.js";
|
|
7
8
|
export { RelationCard, RelationValue, } from "./Relation.js";
|
|
8
|
-
export { Totals } from "./Totals.js";
|
|
9
|
-
export { Cell, formatCount, formatDistance, formatNumber, KeyValue, Numeric,
|
|
9
|
+
export { Totals, } from "./Totals.js";
|
|
10
|
+
export { Cell, formatCount, formatDistance, formatNumber, KeyValue, Numeric, } from "./Value.js";
|
package/dist/tokens.css
CHANGED
|
@@ -501,13 +501,25 @@
|
|
|
501
501
|
—which has to stay clickable— reduced to a useless strip. */
|
|
502
502
|
--container-peek: 30rem;
|
|
503
503
|
|
|
504
|
-
/*
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
is
|
|
510
|
-
|
|
504
|
+
/* THE ACTIVITY COLUMN — at the RIGHT of a record's sheet, joined to it (`Activity`,
|
|
505
|
+
`RecordHeader` THE PAGE). It holds what is true now (the record's
|
|
506
|
+
notices and its fields' and rows' notes, compact) over what happened (the timeline:
|
|
507
|
+
messages, notes and events by time) — both always in sight.
|
|
508
|
+
|
|
509
|
+
`--container-activity` is the column: 22rem holds a notice with its action and a
|
|
510
|
+
message bubble of readable measure.
|
|
511
|
+
|
|
512
|
+
`--container-beside` is how wide the record's PAGE has to be for the column to stand
|
|
513
|
+
beside the sheet: the column and a sheet that keeps 54rem — two groups of fields side by
|
|
514
|
+
side still fit their labels. Narrower (a laptop with a sidebar, a phone, a `Drill`), the
|
|
515
|
+
panel goes BELOW the sheet as a card. Written as a number and not a `calc()` because a container query cannot
|
|
516
|
+
read a variable.
|
|
517
|
+
|
|
518
|
+
`--container-record` is the pair at its widest — the sheet's reading width and the
|
|
519
|
+
column — so on a big screen they are placed together, centred. At 1680 px: 72 + 22. */
|
|
520
|
+
--container-activity: 22rem;
|
|
521
|
+
--container-beside: 76rem;
|
|
522
|
+
--container-record: calc(var(--container-sheet) + var(--container-activity));
|
|
511
523
|
|
|
512
524
|
/* Below this a surface is held in one hand: a phone, or a panel just as narrow. 40rem is
|
|
513
525
|
the width the list already stops offering a table at (`ListView`), and it is the same
|
|
@@ -523,6 +535,12 @@
|
|
|
523
535
|
covering the bottom of the screen, which is exactly where the sheet's actions are. */
|
|
524
536
|
--size-sheet: 90dvh;
|
|
525
537
|
|
|
538
|
+
/* How tall a floating list grows before it scrolls inside: about eight two-line rows,
|
|
539
|
+
the height a capped `Picker` already has, so a list that loads page after page from the
|
|
540
|
+
backend opens at the same size as one that shows the first eight. Taller, and a list of
|
|
541
|
+
two thousand customers fills the window and covers the form it is choosing for. */
|
|
542
|
+
--size-dropdown: 20rem;
|
|
543
|
+
|
|
526
544
|
/* The width of a module's sidebar. 15rem holds an icon, a screen name of two
|
|
527
545
|
words —«Notas de crédito», «Órdenes de compra»— a count and one step of
|
|
528
546
|
nesting without truncating, and still leaves a 1280-wide window more than
|
|
@@ -583,6 +601,25 @@
|
|
|
583
601
|
--duration-panel: 240ms;
|
|
584
602
|
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
585
603
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
604
|
+
|
|
605
|
+
/* The one loop of the system: the bar of a task under way that cannot say how far
|
|
606
|
+
it is (`ProgressBar` without a value). It is not a move between two states — it
|
|
607
|
+
has no end until the task ends — so the 250ms ceiling above does not apply; at
|
|
608
|
+
1.6s a bar that stays a minute on screen moves slowly enough not to flicker in
|
|
609
|
+
the corner of the eye. The bar uses it behind `motion-safe:`: with reduced
|
|
610
|
+
motion it stands still. */
|
|
611
|
+
--animate-progress-sweep: progress-sweep 1.6s var(--ease-in-out) infinite;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/* The segment is two fifths of its track: from just off the left edge (-100 % of
|
|
615
|
+
itself) to just off the right one (250 % of itself = the track's width). */
|
|
616
|
+
@keyframes progress-sweep {
|
|
617
|
+
from {
|
|
618
|
+
translate: -100%;
|
|
619
|
+
}
|
|
620
|
+
to {
|
|
621
|
+
translate: 250%;
|
|
622
|
+
}
|
|
586
623
|
}
|
|
587
624
|
|
|
588
625
|
/* ==================================================================== *
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ListIdentity } from "../../components/listing/ListingBar.js";
|
|
2
2
|
import type { SortField } from "../../components/listing/SortMenu.js";
|
|
3
3
|
import type { Surface } from "../../foundations/types.js";
|
|
4
|
-
import type { DataColumn } from "../../primitives/table/DataTable.js";
|
|
4
|
+
import type { DataColumn, DataTableCreate } from "../../primitives/table/DataTable.js";
|
|
5
5
|
import type { RowAction } from "../../primitives/table/RowActions.js";
|
|
6
6
|
import type { SortState } from "../../primitives/table/Table.js";
|
|
7
7
|
import { type ListCrumb, type ListEmpty, type ListGroup, type ListPivot, type ListPresent, type ListReport, type ListSheet, type RowOf } from "./types.js";
|
|
@@ -41,6 +41,9 @@ type TableProps<T extends object> = {
|
|
|
41
41
|
/** Lo que se le hace a UNA fila sin entrar. Se dibujan escondidas y aparecen
|
|
42
42
|
* sobre la fila que se está apuntando. */
|
|
43
43
|
rowActions?: (item: T) => readonly RowAction[];
|
|
44
|
+
/** Escribir un registro nuevo como una fila más de la tabla (la lista editable de
|
|
45
|
+
* Odoo). Ver la cabecera de `DataTable`. */
|
|
46
|
+
create?: DataTableCreate<T>;
|
|
44
47
|
};
|
|
45
48
|
/** El tablero. Sin `card`, la tarjeta sale de lo que ya dice `List.Rows`: el
|
|
46
49
|
* nombre, el `meta` y las fichas. Escribirla igual es declarar que ESTA lista
|
|
@@ -55,6 +58,9 @@ type SheetProps<T> = Partial<ListSheet<T>>;
|
|
|
55
58
|
export type ListProps<T extends object> = {
|
|
56
59
|
items: readonly T[];
|
|
57
60
|
keyOf: (item: T) => string;
|
|
61
|
+
/** The list is a FIELD of a record — a one2many / many2many — and not a screen: a
|
|
62
|
+
* one-line bar that does not stick. See «A list INSIDE a record» above. */
|
|
63
|
+
embedded?: boolean;
|
|
58
64
|
/** En qué superficie se apoya la BARRA. `canvas` (el default) es una barra
|
|
59
65
|
* de control clara; `chrome` la convierte en una banda oscura, una opción
|
|
60
66
|
* explícita: la barra de la aplicación es la única banda oscura de la
|
|
@@ -93,7 +99,7 @@ export type ListProps<T extends object> = {
|
|
|
93
99
|
empty?: ListEmpty;
|
|
94
100
|
children?: ReactNode;
|
|
95
101
|
};
|
|
96
|
-
export declare function List<T extends object>({ items, keyOf, surface, group, selection, sort, onSortChange, sortable, present, onPresentChange, onOpen, onPeek, isPeeked, state, filtered, empty, children, }: ListProps<T>): import("react").JSX.Element;
|
|
102
|
+
export declare function List<T extends object>({ items, keyOf, embedded, surface, group, selection, sort, onSortChange, sortable, present, onPresentChange, onOpen, onPeek, isPeeked, state, filtered, empty, children, }: ListProps<T>): import("react").JSX.Element;
|
|
97
103
|
export declare namespace List {
|
|
98
104
|
var Bar: ((props: BarProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"bar">;
|
|
99
105
|
var Crumbs: ((props: CrumbsProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"crumbs">;
|
package/dist/views/list/List.js
CHANGED
|
@@ -22,6 +22,9 @@ const Views = slot("views", (_props) => null);
|
|
|
22
22
|
* arriba de las filas, porque son del conjunto y no del marco. */
|
|
23
23
|
const Metrics = slot("metrics", (_props) => null);
|
|
24
24
|
const Rows = slot("rows", (_props) => null);
|
|
25
|
+
/* Through `unknown`: `create` both receives and hands back a `T` (`onChange`, `draft`),
|
|
26
|
+
so `TableProps` is invariant in `T` and `TableProps<never>` no longer narrows to it. The
|
|
27
|
+
slot only carries the props; `List` reads them back typed against the list's `T`. */
|
|
25
28
|
const TableSlot = slot("table", (_props) => null);
|
|
26
29
|
const Board = slot("board", (_props) => null);
|
|
27
30
|
const SheetSlot = slot("sheet", (_props) => null);
|
|
@@ -39,7 +42,7 @@ const PRESENT_OF = {
|
|
|
39
42
|
pivot: "pivot",
|
|
40
43
|
};
|
|
41
44
|
const FACES = ["rows", "table", "board", "sheet", "report", "pivot"];
|
|
42
|
-
export function List({ items, keyOf, surface, group, selection, sort, onSortChange, sortable, present, onPresentChange, onOpen, onPeek, isPeeked, state, filtered, empty, children, }) {
|
|
45
|
+
export function List({ items, keyOf, embedded, surface, group, selection, sort, onSortChange, sortable, present, onPresentChange, onOpen, onPeek, isPeeked, state, filtered, empty, children, }) {
|
|
43
46
|
const top = flatten(children);
|
|
44
47
|
const bar = flatten(propsOf(pick(top, "bar"))?.children);
|
|
45
48
|
const crumbs = propsOf(pick(bar, "crumbs"))?.crumbs;
|
|
@@ -65,12 +68,13 @@ export function List({ items, keyOf, surface, group, selection, sort, onSortChan
|
|
|
65
68
|
/* La escotilla: lo que el arquetipo no previó se dibuja igual, debajo. Que
|
|
66
69
|
aparezca algo acá es la señal de que al arquetipo le falta una pieza. */
|
|
67
70
|
const rest = loose(top, ["bar", "metrics", ...FACES]);
|
|
68
|
-
return (_jsx(ListView, { items: items, keyOf: keyOf, row: rows?.row ?? (() => ({ name: "" })), ...(rows?.header === undefined ? {} : { rowHeader: rows.header }), ...(identity === undefined ? {} : { identity }), ...(crumbs === undefined ? {} : { crumbs }), ...(surface === undefined ? {} : { surface }), ...(search === undefined ? {} : { search }), ...(actions === undefined ? {} : { actions }), ...(pagination === undefined ? {} : { pagination }), ...(views === undefined ? {} : { views }), ...(metrics === undefined ? {} : { metrics }), ...(table === undefined
|
|
71
|
+
return (_jsx(ListView, { items: items, keyOf: keyOf, row: rows?.row ?? (() => ({ name: "" })), ...(rows?.header === undefined ? {} : { rowHeader: rows.header }), ...(identity === undefined ? {} : { identity }), ...(crumbs === undefined ? {} : { crumbs }), ...(embedded === undefined ? {} : { embedded }), ...(surface === undefined ? {} : { surface }), ...(search === undefined ? {} : { search }), ...(actions === undefined ? {} : { actions }), ...(pagination === undefined ? {} : { pagination }), ...(views === undefined ? {} : { views }), ...(metrics === undefined ? {} : { metrics }), ...(table === undefined
|
|
69
72
|
? {}
|
|
70
73
|
: {
|
|
71
74
|
columns: table.columns,
|
|
72
75
|
...(table.totals === undefined ? {} : { totals: table.totals }),
|
|
73
76
|
...(table.rowActions === undefined ? {} : { rowActions: table.rowActions }),
|
|
77
|
+
...(table.create === undefined ? {} : { create: table.create }),
|
|
74
78
|
...(table.visibleColumnIds === undefined
|
|
75
79
|
? {}
|
|
76
80
|
: { visibleColumnIds: table.visibleColumnIds }),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ListViewProps } from "./types.js";
|
|
2
|
-
export declare function ListView<T extends object>({ items, keyOf, identity, crumbs, surface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, sheet, report, pivot, present: requested, presents, onPresentChange, sort, onSortChange, sortable, totals, rowActions, group, selection, onOpen, onPeek, state, filtered, empty, children, }: ListViewProps<T>): import("react").JSX.Element;
|
|
2
|
+
export declare function ListView<T extends object>({ items, keyOf, identity, crumbs, embedded, surface: requestedSurface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, sheet, report, pivot, present: requested, presents, onPresentChange, sort, onSortChange, sortable, totals, rowActions, create, group, selection, onOpen, onPeek, state, filtered, empty, children, }: ListViewProps<T>): import("react").JSX.Element;
|
|
3
3
|
/** What a list offers when it fails and can be retried. */
|
|
4
4
|
export declare function RetryAction({ onRetry }: {
|
|
5
5
|
onRetry: () => void;
|
|
@@ -18,7 +18,7 @@ import { Empty, Failed, Skeleton } from "../../primitives/notice/Notice.js";
|
|
|
18
18
|
import { PivotTable } from "../../primitives/table/PivotTable.js";
|
|
19
19
|
import { ReportTable } from "../../primitives/table/ReportTable.js";
|
|
20
20
|
import { groupedColumnIds } from "./columns.js";
|
|
21
|
-
import { groupLevelsOf, reportRowsOf, sheetFromColumns, sheetRowsOf, } from "./derive.js";
|
|
21
|
+
import { groupLevelsOf, reportColumnsOf, reportRowsOf, sheetFromColumns, sheetRowsOf, } from "./derive.js";
|
|
22
22
|
import { SheetPresentation, TablePresentation, } from "./presentations.js";
|
|
23
23
|
import { useNarrowList } from "./useNarrowList.js";
|
|
24
24
|
import { Grid3x3, LayoutGrid, List, Sheet, Sigma, Table2 } from "lucide-react";
|
|
@@ -58,8 +58,11 @@ const PRESENT_ICONS = [
|
|
|
58
58
|
/* La cuadrícula: dos ejes, y lo que importa está adentro. */
|
|
59
59
|
{ id: "pivot", icon: Grid3x3 },
|
|
60
60
|
];
|
|
61
|
-
export function ListView({ items, keyOf, identity, crumbs, surface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, sheet, report, pivot, present: requested = "rows", presents, onPresentChange, sort, onSortChange, sortable, totals = false, rowActions, group, selection, onOpen, onPeek, state, filtered = false, empty, children, }) {
|
|
61
|
+
export function ListView({ items, keyOf, identity, crumbs, embedded = false, surface: requestedSurface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, sheet, report, pivot, present: requested = "rows", presents, onPresentChange, sort, onSortChange, sortable, totals = false, rowActions, create, group, selection, onOpen, onPeek, state, filtered = false, empty, children, }) {
|
|
62
62
|
const { frame, offered, present } = useNarrowList(presents, requested);
|
|
63
|
+
/* Embedded, the list sits on the record's paper: there is no dark band to inherit, and a
|
|
64
|
+
navy switcher inside a white sheet would be a second chrome on the screen. */
|
|
65
|
+
const surface = embedded ? undefined : requestedSurface;
|
|
63
66
|
const density = useDensity();
|
|
64
67
|
const copy = useUiCopy();
|
|
65
68
|
const loading = state?.loading === true;
|
|
@@ -128,7 +131,15 @@ export function ListView({ items, keyOf, identity, crumbs, surface, metrics, sea
|
|
|
128
131
|
present === "pivot" ? null : (_jsx(SortMenu, { fields: sortable, sort: sort ?? null, onSortChange: (next) => onSortChange?.(next), ...(surface === undefined ? {} : { surface }) }));
|
|
129
132
|
const rightViews = views ?? switcher;
|
|
130
133
|
const viewsSlot = columnsMenu === null && sortMenu === null && rightViews === undefined ? undefined : (_jsxs(_Fragment, { children: [sortMenu, columnsMenu, rightViews] }));
|
|
131
|
-
|
|
134
|
+
/* Embedded, the line is drawn only if it has something to OFFER: a count alone repeats
|
|
135
|
+
what the rows (and the footer) already say. */
|
|
136
|
+
const barHasControls = !embedded ||
|
|
137
|
+
search !== undefined ||
|
|
138
|
+
viewsSlot !== undefined ||
|
|
139
|
+
actions !== undefined ||
|
|
140
|
+
pagination !== undefined ||
|
|
141
|
+
(selection?.count ?? 0) > 0;
|
|
142
|
+
const bar = !barHasControls ? undefined : (_jsx(ListingBar, { surface: surface, ...(embedded ? { inline: true, count: items.length } : {}), ...(embedded || crumbs === undefined || crumbs.length === 0 || density === "compact"
|
|
132
143
|
? {}
|
|
133
144
|
: {
|
|
134
145
|
crumbs: (_jsx(Breadcrumb, { crumbs: crumbs, ...(surface === undefined ? {} : { surface }) })),
|
|
@@ -183,7 +194,10 @@ export function ListView({ items, keyOf, identity, crumbs, surface, metrics, sea
|
|
|
183
194
|
error === null &&
|
|
184
195
|
(present === "pivot" && pivotShown !== undefined
|
|
185
196
|
? pivotIsEmpty(pivotShown)
|
|
186
|
-
: items.length === 0)
|
|
197
|
+
: items.length === 0) &&
|
|
198
|
+
/* The first record of an empty list is written in the table, not under a sentence
|
|
199
|
+
saying there is nothing. */
|
|
200
|
+
!(present === "table" && create?.draft != null);
|
|
187
201
|
/* La única línea que hace agrupable a una vista: el árbol que le pasaron, o el
|
|
188
202
|
que se arma con las filas en la mano. */
|
|
189
203
|
const piles = useMemo(() => pilesOf(ordered, group), [group, ordered]);
|
|
@@ -225,7 +239,7 @@ export function ListView({ items, keyOf, identity, crumbs, surface, metrics, sea
|
|
|
225
239
|
};
|
|
226
240
|
const body = present === "table" && shownColumns !== undefined ? (
|
|
227
241
|
/* The table receives EVERYTHING that belongs to the set: see `TablePresentation`. */
|
|
228
|
-
_jsx(TablePresentation, { items: items, columns: shownColumns, keyOf: keyOf, levels: groupLevels, ...(sort === undefined ? {} : { sort }), ...(onSortChange === undefined ? {} : { onSortChange }), ...(group === undefined ? {} : { group }), ...(selection === undefined ? {} : { selection }), totals: totals, ...(rowActions === undefined ? {} : { rowActions }), ...(onPeek === undefined ? {} : { onPeek }), ...(onOpen === undefined ? {} : { onOpen }) })) : present === "sheet" && sheetSpec !== undefined ? (
|
|
242
|
+
_jsx(TablePresentation, { items: items, columns: shownColumns, keyOf: keyOf, levels: groupLevels, ...(sort === undefined ? {} : { sort }), ...(onSortChange === undefined ? {} : { onSortChange }), ...(group === undefined ? {} : { group }), ...(selection === undefined ? {} : { selection }), totals: totals, ...(rowActions === undefined ? {} : { rowActions }), ...(create === undefined ? {} : { create }), ...(onPeek === undefined ? {} : { onPeek }), ...(onOpen === undefined ? {} : { onOpen }) })) : present === "sheet" && sheetSpec !== undefined ? (
|
|
229
243
|
/* La planilla recibe el conjunto por ÍNDICE y no una matriz ya armada: ver `SheetPresentation`. */
|
|
230
244
|
_jsx(SheetPresentation, { spec: sheetSpec, entries: sheetRows, ordered: ordered, ...(group === undefined ? {} : { group }) })) : present === "report" && report !== undefined ? (
|
|
231
245
|
/* El informe declarado por el dominio no se ORDENA desde la barra: el
|
|
@@ -233,7 +247,15 @@ export function ListView({ items, keyOf, identity, crumbs, surface, metrics, sea
|
|
|
233
247
|
Activos» en el medio. Pero sí se AGRUPA cuando las líneas no vienen
|
|
234
248
|
declaradas: ahí el informe es este conjunto contado por los niveles que
|
|
235
249
|
estén puestos. */
|
|
236
|
-
_jsx(ReportTable
|
|
250
|
+
_jsx(ReportTable
|
|
251
|
+
/* Built from the piles, the numbers are the list's columns' — and so is how they
|
|
252
|
+
are written. Declared by the domain, the columns are the domain's. */
|
|
253
|
+
, {
|
|
254
|
+
/* Built from the piles, the numbers are the list's columns' — and so is how they
|
|
255
|
+
are written. Declared by the domain, the columns are the domain's. */
|
|
256
|
+
columns: report.rows === undefined
|
|
257
|
+
? reportColumnsOf(report.columns, columns)
|
|
258
|
+
: report.columns, rows: report.rows ?? reportRows, ...(report.defaultOpen === undefined ? {} : { defaultOpen: report.defaultOpen }), ...(report.height === undefined ? {} : { height: report.height }) })) : present === "pivot" && pivotShown !== undefined ? (
|
|
237
259
|
/* El pivote recibe la grilla y nada más: no hay selección que pasarle
|
|
238
260
|
—una casilla por montón elegiría cosas que no son registros—, no hay
|
|
239
261
|
orden —cada eje viene en el orden de sus claves— y no hay menú de
|
|
@@ -253,8 +275,12 @@ export function ListView({ items, keyOf, identity, crumbs, surface, metrics, sea
|
|
|
253
275
|
wrapped it in a `div` to get both. */
|
|
254
276
|
_jsxs("div", { ref: frame, className: "@container flex min-w-0 flex-1 flex-col bg-surface", children: [_jsxs(Listing, { bar: bar,
|
|
255
277
|
/* La barra se queda arriba: con 187 filas, scrollear para ver la última
|
|
256
|
-
dejaba sin buscador, sin paginador y sin el conmutador.
|
|
257
|
-
|
|
278
|
+
dejaba sin buscador, sin paginador y sin el conmutador.
|
|
279
|
+
Embedded it does NOT: the record has its own sticky parts (its rail, its tabs),
|
|
280
|
+
and a second band stuck under them — or carried up into the frame's header slot,
|
|
281
|
+
which is what a sticky list bar does under a sidebar — would cover the record
|
|
282
|
+
for a collection of a dozen rows. */
|
|
283
|
+
sticky: !embedded, ...(surface === undefined ? {} : { surface }), ...(metrics === undefined
|
|
258
284
|
? {}
|
|
259
285
|
: {
|
|
260
286
|
metrics: _jsx("div", { className: "px-3.5", children: metrics }),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Pile } from "../../foundations/grouping.js";
|
|
2
2
|
import { type DataColumn } from "../../primitives/table/DataTable.js";
|
|
3
|
-
import type { ReportRow } from "../../primitives/table/ReportTable.js";
|
|
3
|
+
import type { ReportColumn, ReportRow } from "../../primitives/table/ReportTable.js";
|
|
4
4
|
import type { SheetColumn } from "../../primitives/table/SheetTable.js";
|
|
5
5
|
import type { ListGroup, ListSheet, RowOf } from "./types.js";
|
|
6
6
|
/**
|
|
@@ -74,3 +74,14 @@ export declare function sheetRowsOf<T extends object>(piles: readonly Pile<T>[]
|
|
|
74
74
|
* no digan totales distintos del mismo conjunto.
|
|
75
75
|
*/
|
|
76
76
|
export declare function reportRowsOf<T extends object>(piles: readonly Pile<T>[] | null, columns: readonly DataColumn<T>[] | undefined, row: (item: T) => RowOf): readonly ReportRow[];
|
|
77
|
+
/**
|
|
78
|
+
* The columns of a report built from the piles, written like the list's own columns.
|
|
79
|
+
*
|
|
80
|
+
* `reportRowsOf` puts in position `i` the aggregate of the `i`-th column that declared one,
|
|
81
|
+
* so `report.columns[i]` is THAT column's: a report column without its own `format` takes
|
|
82
|
+
* the one the list column declared — otherwise the report wrote «Bs. 78.752,90» in the
|
|
83
|
+
* table's footer and «78.752,90» in its own total line. A format declared on the report
|
|
84
|
+
* column wins: it is the more specific declaration. A `count` column keeps the report's own
|
|
85
|
+
* number format — a count of rows is not an amount.
|
|
86
|
+
*/
|
|
87
|
+
export declare function reportColumnsOf<T extends object>(reportColumns: readonly ReportColumn[], columns: readonly DataColumn<T>[] | undefined): readonly ReportColumn[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { levelKey, pathKey, pileItems, pileLabel, } from "../../foundations/grouping.js";
|
|
2
|
-
import { aggregateOf } from "../../primitives/table/DataTable.js";
|
|
2
|
+
import { aggregateFormat, aggregateOf, aggregateText, } from "../../primitives/table/DataTable.js";
|
|
3
3
|
/**
|
|
4
4
|
* Context: what a list DERIVES from its set, as pure functions — the table's group levels,
|
|
5
5
|
* the sheet drawn from the declared columns, the sheet's flattened band/row sequence and
|
|
@@ -114,10 +114,14 @@ export function sheetRowsOf(piles, isOpen, columns) {
|
|
|
114
114
|
las `columns` de la lista —las mismas que suma el pie de la
|
|
115
115
|
tabla— para que la planilla y la tabla no digan números distintos
|
|
116
116
|
del mismo montón. La planilla declara SUS columnas aparte, así que
|
|
117
|
-
se busca por id.
|
|
117
|
+
se busca por id. Y se ESCRIBE como el pie: con el `format` de la
|
|
118
|
+
columna, para que el montón no diga «78752,9» debajo de «Bs.». */
|
|
118
119
|
total: (column) => {
|
|
119
120
|
const declared = columns?.find((one) => one.id === column.id);
|
|
120
|
-
|
|
121
|
+
const value = declared === undefined ? null : aggregateOf(declared, inside);
|
|
122
|
+
return declared === undefined || value === null
|
|
123
|
+
? null
|
|
124
|
+
: aggregateText(declared, value);
|
|
121
125
|
},
|
|
122
126
|
},
|
|
123
127
|
});
|
|
@@ -179,3 +183,25 @@ export function reportRowsOf(piles, columns, row) {
|
|
|
179
183
|
};
|
|
180
184
|
return piles.map(line);
|
|
181
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* The columns of a report built from the piles, written like the list's own columns.
|
|
188
|
+
*
|
|
189
|
+
* `reportRowsOf` puts in position `i` the aggregate of the `i`-th column that declared one,
|
|
190
|
+
* so `report.columns[i]` is THAT column's: a report column without its own `format` takes
|
|
191
|
+
* the one the list column declared — otherwise the report wrote «Bs. 78.752,90» in the
|
|
192
|
+
* table's footer and «78.752,90» in its own total line. A format declared on the report
|
|
193
|
+
* column wins: it is the more specific declaration. A `count` column keeps the report's own
|
|
194
|
+
* number format — a count of rows is not an amount.
|
|
195
|
+
*/
|
|
196
|
+
export function reportColumnsOf(reportColumns, columns) {
|
|
197
|
+
if (columns === undefined)
|
|
198
|
+
return reportColumns;
|
|
199
|
+
const numeric = columns.filter((column) => column.aggregate !== undefined);
|
|
200
|
+
return reportColumns.map((column, index) => {
|
|
201
|
+
const declared = numeric[index];
|
|
202
|
+
const format = declared === undefined ? undefined : aggregateFormat(declared);
|
|
203
|
+
return column.format !== undefined || format === undefined
|
|
204
|
+
? column
|
|
205
|
+
: { ...column, format };
|
|
206
|
+
});
|
|
207
|
+
}
|
|
@@ -15,11 +15,11 @@ type TableProps<T extends object> = {
|
|
|
15
15
|
levels: NonNullable<Parameters<typeof DataTable<T>>[0]["levels"]>;
|
|
16
16
|
group?: ListGroup<T>;
|
|
17
17
|
totals: boolean;
|
|
18
|
-
} & Pick<ListViewProps<T>, "sort" | "onSortChange" | "selection" | "rowActions" | "onPeek" | "onOpen">;
|
|
18
|
+
} & Pick<ListViewProps<T>, "sort" | "onSortChange" | "selection" | "rowActions" | "create" | "onPeek" | "onOpen">;
|
|
19
19
|
/** The table receives EVERYTHING that belongs to the set —sorting, selection, grouping,
|
|
20
20
|
* which columns are on screen— and not a trimmed down version: that was exactly the trap
|
|
21
21
|
* this archetype exists to avoid, that switching presentation loses capabilities. */
|
|
22
|
-
export declare function TablePresentation<T extends object>({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, onPeek, onOpen, }: TableProps<T>): import("react").JSX.Element;
|
|
22
|
+
export declare function TablePresentation<T extends object>({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, create, onPeek, onOpen, }: TableProps<T>): import("react").JSX.Element;
|
|
23
23
|
type SheetProps<T extends object> = {
|
|
24
24
|
spec: ListSheet<T>;
|
|
25
25
|
/** The flattened bands and rows when the set is grouped; `null` when it is not. */
|
|
@@ -6,7 +6,7 @@ import { SheetTable } from "../../primitives/table/SheetTable.js";
|
|
|
6
6
|
/** The table receives EVERYTHING that belongs to the set —sorting, selection, grouping,
|
|
7
7
|
* which columns are on screen— and not a trimmed down version: that was exactly the trap
|
|
8
8
|
* this archetype exists to avoid, that switching presentation loses capabilities. */
|
|
9
|
-
export function TablePresentation({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, onPeek, onOpen, }) {
|
|
9
|
+
export function TablePresentation({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, create, onPeek, onOpen, }) {
|
|
10
10
|
return (_jsx(DataTable, { data: items, columns: columns, getRowId: keyOf, ...(sort === undefined ? {} : { sort }), ...(onSortChange === undefined ? {} : { onSortChange }), ...(levels.length === 0 ? {} : { levels: levels }), ...(group?.collapsed === undefined ? {} : { collapsed: group.collapsed }), ...(group?.onToggle === undefined ? {} : { onGroupToggle: group.onToggle }), ...(selection === undefined
|
|
11
11
|
? {}
|
|
12
12
|
: {
|
|
@@ -22,7 +22,7 @@ export function TablePresentation({ items, columns, keyOf, levels, group, totals
|
|
|
22
22
|
selection.toggle(id);
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
}), ...(totals ? { totals: true } : {}), ...(rowActions === undefined ? {} : { rowActions }), ...((onPeek ?? onOpen) === undefined ? {} : { onRowClick: onPeek ?? onOpen }) }));
|
|
25
|
+
}), ...(totals ? { totals: true } : {}), ...(rowActions === undefined ? {} : { rowActions }), ...(create === undefined ? {} : { create }), ...((onPeek ?? onOpen) === undefined ? {} : { onRowClick: onPeek ?? onOpen }) }));
|
|
26
26
|
}
|
|
27
27
|
/** The sheet receives the set by INDEX and not a ready-made matrix: `SheetTable` is
|
|
28
28
|
* virtualized precisely so as not to materialize a million rows, and handing it copies
|
|
@@ -99,5 +99,7 @@ export function SheetPresentation({ spec, entries, ordered, group, }) {
|
|
|
99
99
|
? false
|
|
100
100
|
: (spec.editable?.(item, column, columnIndex) ?? false);
|
|
101
101
|
},
|
|
102
|
-
})
|
|
102
|
+
}), ...(spec.onAddRow === undefined || entries !== null
|
|
103
|
+
? {}
|
|
104
|
+
: { onAddRow: spec.onAddRow }) }));
|
|
103
105
|
}
|
|
@@ -4,7 +4,7 @@ import type { SortField } from "../../components/listing/SortMenu.js";
|
|
|
4
4
|
import type { Grouping, GroupLevel } from "../../foundations/grouping.js";
|
|
5
5
|
import type { Pivot, PivotKey, PivotSpec } from "../../foundations/pivot.js";
|
|
6
6
|
import type { Surface, Tone } from "../../foundations/types.js";
|
|
7
|
-
import type { DataColumn } from "../../primitives/table/DataTable.js";
|
|
7
|
+
import type { DataColumn, DataTableCreate } from "../../primitives/table/DataTable.js";
|
|
8
8
|
import type { ReportColumn, ReportRow } from "../../primitives/table/ReportTable.js";
|
|
9
9
|
import type { RowAction } from "../../primitives/table/RowActions.js";
|
|
10
10
|
import type { SheetColumn } from "../../primitives/table/SheetTable.js";
|
|
@@ -87,6 +87,9 @@ export type ListSheet<T> = {
|
|
|
87
87
|
* convertirlo al tipo de la columna es del dominio, no de acá. */
|
|
88
88
|
onCommit?: (item: T, column: SheetColumn, columnIndex: number, next: string) => void;
|
|
89
89
|
editable?: (item: T, column: SheetColumn, columnIndex: number) => boolean;
|
|
90
|
+
/** Present = the sheet adds rows: «add a row» under it, and `Enter` on the last row.
|
|
91
|
+
* The consumer appends the item; the sheet lands on it. Not while grouped. */
|
|
92
|
+
onAddRow?: () => void;
|
|
90
93
|
};
|
|
91
94
|
/**
|
|
92
95
|
* El INFORME de una lista: los períodos y la jerarquía que termina en totales.
|
|
@@ -160,6 +163,11 @@ export type ListViewProps<T extends object> = {
|
|
|
160
163
|
/** The metrics that also NARROW: «2 por confirmar», «41 por entregar». They go
|
|
161
164
|
* below the bar and above the rows — they belong to the set, not to the frame. */
|
|
162
165
|
metrics?: ReactNode;
|
|
166
|
+
/** The list is a FIELD of a record (a one2many / many2many) and not a screen: the bar
|
|
167
|
+
* is one line — search, count, sort, columns, switcher, actions —, it does not stick
|
|
168
|
+
* and it does not move into the frame's header. Identity and crumbs are not drawn: the
|
|
169
|
+
* record around it already says them. See `ListingBar`'s header. */
|
|
170
|
+
embedded?: boolean;
|
|
163
171
|
/** Which surface the BAR sits on. `canvas` (the default) is a light control bar;
|
|
164
172
|
* `chrome` turns it into a dark band — an explicit choice, since the application bar
|
|
165
173
|
* is the screen's one dark band (same as the rail of a record). */
|
|
@@ -212,6 +220,10 @@ export type ListViewProps<T extends object> = {
|
|
|
212
220
|
/** What gets done to ONE row without entering it, in the table presentation.
|
|
213
221
|
* They are drawn hidden and appear on the row being pointed at. */
|
|
214
222
|
rowActions?: (item: T) => readonly RowAction[];
|
|
223
|
+
/** Write a new record as a row of the table presentation — Odoo's editable list. The
|
|
224
|
+
* columns that declare `input` get a control in that row. See `DataTable`'s header.
|
|
225
|
+
* While a record is being written the table shows even if the set is empty. */
|
|
226
|
+
create?: DataTableCreate<T>;
|
|
215
227
|
/** The board presentation. */
|
|
216
228
|
card?: (item: T) => ReactNode;
|
|
217
229
|
/**
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import { type ActivityProps } from "../../components/activity/Activity.js";
|
|
1
2
|
import { type SheetField, type SheetLayout } from "../../components/form/Sheet.js";
|
|
2
3
|
import type { Crumb } from "../../components/record/Breadcrumb.js";
|
|
3
4
|
import type { DirtyState } from "../../components/record/DirtyActions.js";
|
|
5
|
+
import { type RecordNoticeSpec } from "../../components/record/RecordNotices.js";
|
|
4
6
|
import { RecordSkeleton } from "../../components/record/RecordSkeleton.js";
|
|
5
7
|
import { type Stage } from "../../components/record/StatusBar.js";
|
|
6
8
|
import type { Surface, Tone } from "../../foundations/types.js";
|
|
7
9
|
import { type TabNotice } from "../../primitives/tabs/Tabs.js";
|
|
8
10
|
import type { LucideIcon } from "lucide-react";
|
|
9
|
-
import type
|
|
11
|
+
import { type ReactNode } from "react";
|
|
10
12
|
export type RecordIdentity = {
|
|
11
13
|
icon?: LucideIcon;
|
|
12
14
|
title: ReactNode;
|
|
@@ -42,6 +44,9 @@ export type RecordPager = {
|
|
|
42
44
|
onNext?: () => void;
|
|
43
45
|
};
|
|
44
46
|
export type { SheetField };
|
|
47
|
+
/** A notice of the record: the props of `Record.Notice` (a `Callout` without its × label,
|
|
48
|
+
* which the record writes from the copy table). */
|
|
49
|
+
export type RecordNotice = RecordNoticeSpec;
|
|
45
50
|
type RailProps = {
|
|
46
51
|
children?: ReactNode;
|
|
47
52
|
/** The rail's surface. `canvas` (the default) is a light control bar; `chrome` is the dark
|
|
@@ -95,9 +100,27 @@ type PageProps = {
|
|
|
95
100
|
notice?: TabNotice;
|
|
96
101
|
children?: ReactNode;
|
|
97
102
|
};
|
|
103
|
+
/** The record's ACTIVITY panel, as DATA: its conversation, its history, its composer.
|
|
104
|
+
* The record draws the `Activity` itself and gives it what only the record has — its
|
|
105
|
+
* notices (the ones that are not blocking), and the indicator in the rail that opens the
|
|
106
|
+
* panel on them.
|
|
107
|
+
*
|
|
108
|
+
* Context: it was `<Record.Chatter><Chatter open onToggle …/></Record.Chatter>`, a node
|
|
109
|
+
* the record could only place. Written as data — like `Record.Status` — the record owns
|
|
110
|
+
* the panel's open state (`defaultOpen`, or `open` + `onOpenChange` to control it), so
|
|
111
|
+
* «⚠ 2 avisos» in the rail can open it and move the focus to its notices. */
|
|
112
|
+
export type RecordActivityProps = Omit<ActivityProps, "open" | "onToggle" | "alerts" | "alertsId"> & {
|
|
113
|
+
/** Starts OPEN unless this says otherwise: on a big screen you see what the record has. */
|
|
114
|
+
defaultOpen?: boolean;
|
|
115
|
+
/** Controls the panel: then `onOpenChange` must follow it. Remembering it between
|
|
116
|
+
* records is the app's — the system only reports. */
|
|
117
|
+
open?: boolean;
|
|
118
|
+
onOpenChange?: (open: boolean) => void;
|
|
119
|
+
};
|
|
98
120
|
export type RecordProps = {
|
|
99
121
|
identity: RecordIdentity;
|
|
100
|
-
/** Lo que falló al operar sobre el registro. Va
|
|
122
|
+
/** Lo que falló al operar sobre el registro. Va con los avisos que bloquean, primero:
|
|
123
|
+
* entre el riel y el papel, siempre a la vista (ver `Record.Notice`). */
|
|
101
124
|
error?: string | null;
|
|
102
125
|
/** Hay cambios sin guardar. Su presencia REEMPLAZA los botones de acción por
|
|
103
126
|
* guardar y descartar — ver la nota en `RecordHeader`. */
|
|
@@ -114,13 +137,9 @@ export declare namespace Record {
|
|
|
114
137
|
var Actions: ((props: ActionsProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"actions">;
|
|
115
138
|
var Status: ((props: StatusProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"status">;
|
|
116
139
|
var Paper: ((props: PaperProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"paper">;
|
|
117
|
-
var
|
|
118
|
-
children?: ReactNode;
|
|
119
|
-
/** `page` lo pone SIEMPRE debajo y a todo el ancho, como una hoja propia. Sin
|
|
120
|
-
* esto va al costado cuando hay ancho, que es la forma angosta. */
|
|
121
|
-
layout?: "aside" | "page";
|
|
122
|
-
}) => ReactNode) & import("../../foundations/slots.js").Slotted<"chatter">;
|
|
140
|
+
var Activity: ((props: RecordActivityProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"activity">;
|
|
123
141
|
var Facts: ((props: FactsProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"facts">;
|
|
124
142
|
var Pages: ((props: PagesProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"pages">;
|
|
125
143
|
var Page: ((props: PageProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"page">;
|
|
144
|
+
var Notice: ((props: RecordNoticeSpec) => ReactNode) & import("../../foundations/slots.js").Slotted<"notice">;
|
|
126
145
|
}
|