@sincpro/web-ui 1.1.0 → 1.3.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/dist/components/activity/Activity.js +1 -1
- package/dist/components/activity/Messages.d.ts +4 -2
- package/dist/components/activity/Messages.js +4 -4
- package/dist/components/activity/Timeline.js +1 -1
- package/dist/components/assist/AssistMark.js +1 -1
- package/dist/components/assist/AssistSuggestion.js +1 -1
- package/dist/components/assist/ChangeReview.js +2 -2
- package/dist/components/calendar/RecordCalendar.js +4 -1
- package/dist/components/form/Sheet.js +1 -1
- package/dist/components/lines/LineItems.d.ts +1 -1
- package/dist/components/lines/LineItems.js +2 -2
- package/dist/components/listing/ListingBar.js +1 -1
- package/dist/components/listing/Row.d.ts +7 -0
- package/dist/components/listing/Row.js +7 -1
- package/dist/components/listing/ViewSwitcher.d.ts +7 -2
- package/dist/components/listing/index.d.ts +1 -1
- package/dist/components/listing/set.d.ts +4 -1
- package/dist/components/record/Breadcrumb.js +5 -1
- package/dist/components/search/CriteriaBuilder.d.ts +1 -1
- package/dist/components/search/CriteriaBuilder.js +3 -3
- package/dist/components/search/FilterBuilder.d.ts +1 -18
- package/dist/components/search/FilterBuilder.js +4 -4
- package/dist/components/search/JsonEditor.js +5 -1
- package/dist/components/search/SearchBar.d.ts +1 -2
- package/dist/components/search/SearchBar.js +6 -1
- package/dist/components/search/criteria.d.ts +17 -1
- package/dist/components/search/index.d.ts +2 -1
- package/dist/components/search/index.js +1 -0
- package/dist/components/shell/Panes.d.ts +18 -0
- package/dist/components/shell/Panes.js +36 -0
- package/dist/components/shell/index.d.ts +1 -0
- package/dist/components/shell/index.js +2 -0
- package/dist/foundations/calendar.d.ts +3 -1
- package/dist/foundations/catalog.d.ts +27 -0
- package/dist/foundations/catalog.js +48 -0
- package/dist/foundations/copy.d.ts +33 -62
- package/dist/foundations/copy.es.js +6 -0
- package/dist/foundations/copy.js +21 -93
- package/dist/{primitives/field/context.d.ts → foundations/form.d.ts} +9 -0
- package/dist/{primitives/field/mode.js → foundations/form.js} +11 -0
- package/dist/foundations/grouping.d.ts +9 -3
- package/dist/foundations/index.d.ts +2 -0
- package/dist/foundations/index.js +5 -0
- package/dist/foundations/sticky.d.ts +4 -0
- package/dist/foundations/sticky.js +1 -0
- package/dist/primitives/choice/ComboBox.d.ts +1 -1
- package/dist/primitives/choice/ComboBox.js +4 -4
- package/dist/primitives/choice/RadioGroup.d.ts +1 -1
- package/dist/primitives/choice/RadioGroup.js +3 -3
- package/dist/primitives/choice/SearchField.js +1 -1
- package/dist/primitives/choice/SegmentedControl.d.ts +1 -1
- package/dist/primitives/choice/SegmentedControl.js +2 -2
- package/dist/primitives/choice/Slider.d.ts +1 -1
- package/dist/primitives/choice/Slider.js +2 -2
- package/dist/primitives/choice/Switch.d.ts +1 -1
- package/dist/primitives/choice/Switch.js +2 -2
- package/dist/primitives/date/Calendar.js +1 -1
- package/dist/primitives/date/DatePicker.d.ts +1 -1
- package/dist/primitives/date/DatePicker.js +2 -2
- package/dist/primitives/date/DateTime.d.ts +1 -1
- package/dist/primitives/date/DateTime.js +2 -2
- package/dist/primitives/field/Checks.d.ts +1 -1
- package/dist/primitives/field/Checks.js +4 -4
- package/dist/primitives/field/DropZone.d.ts +1 -1
- package/dist/primitives/field/DropZone.js +2 -2
- package/dist/primitives/field/Field.d.ts +2 -2
- package/dist/primitives/field/Field.js +3 -3
- package/dist/primitives/field/Suggest.d.ts +1 -1
- package/dist/primitives/field/Suggest.js +2 -2
- package/dist/primitives/field/index.d.ts +1 -3
- package/dist/primitives/field/index.js +4 -4
- package/dist/primitives/picker/Picker.d.ts +1 -1
- package/dist/primitives/picker/Picker.js +4 -4
- package/dist/primitives/{tag → picker}/TagsField.d.ts +2 -2
- package/dist/primitives/{tag → picker}/TagsField.js +5 -5
- package/dist/primitives/picker/index.d.ts +2 -0
- package/dist/primitives/picker/index.js +5 -1
- package/dist/primitives/table/CellCopy.js +1 -1
- package/dist/primitives/table/CellEditor.js +2 -4
- package/dist/primitives/table/DataTable.d.ts +11 -1
- package/dist/primitives/table/DataTable.js +137 -38
- package/dist/primitives/table/EditableTable.js +2 -2
- package/dist/primitives/table/PivotTable.js +0 -0
- package/dist/primitives/table/ReportTable.js +4 -3
- package/dist/primitives/table/SheetTable.js +8 -14
- package/dist/primitives/table/Table.d.ts +12 -3
- package/dist/primitives/table/Table.js +7 -7
- package/dist/primitives/table/rowWindow.d.ts +39 -0
- package/dist/primitives/table/rowWindow.js +177 -0
- package/dist/primitives/tabs/Tabs.d.ts +22 -4
- package/dist/primitives/tabs/Tabs.js +77 -23
- package/dist/primitives/tabs/index.d.ts +1 -1
- package/dist/primitives/tabs/index.js +1 -1
- package/dist/primitives/tag/Tags.js +4 -1
- package/dist/primitives/tag/index.d.ts +0 -2
- package/dist/primitives/tag/index.js +0 -3
- package/dist/primitives/value/Avatar.js +8 -1
- package/dist/primitives/value/{Fecha.d.ts → DateValue.d.ts} +5 -2
- package/dist/primitives/value/{Fecha.js → DateValue.js} +9 -8
- package/dist/primitives/value/Relation.d.ts +1 -1
- package/dist/primitives/value/Relation.js +2 -2
- package/dist/primitives/value/Value.js +4 -1
- package/dist/primitives/value/index.d.ts +1 -1
- package/dist/primitives/value/index.js +1 -1
- package/dist/views/list/List.d.ts +14 -1
- package/dist/views/list/List.js +28 -6
- package/dist/views/list/ListView.d.ts +1 -1
- package/dist/views/list/ListView.js +41 -14
- package/dist/views/list/index.d.ts +2 -2
- package/dist/views/list/presentations.js +3 -1
- package/dist/views/list/types.d.ts +49 -1
- package/dist/views/list/useNarrowList.d.ts +2 -2
- package/dist/views/list/useNarrowList.js +5 -5
- package/dist/views/record/Record.js +46 -42
- package/package.json +1 -1
- package/dist/primitives/field/context.js +0 -13
- package/dist/primitives/field/mode.d.ts +0 -9
- /package/dist/primitives/field/{copy.d.ts → clipboard.d.ts} +0 -0
- /package/dist/primitives/field/{copy.js → clipboard.js} +0 -0
- /package/dist/primitives/{tag/choices.d.ts → picker/tagChoices.d.ts} +0 -0
- /package/dist/primitives/{tag/choices.js → picker/tagChoices.js} +0 -0
|
@@ -87,5 +87,12 @@ src, }) {
|
|
|
87
87
|
the same baseline the initials disc has. */
|
|
88
88
|
_jsxs("span", { title: name, className: `relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-pill ${SIZE[size]}`, children: [_jsx("span", { "aria-hidden": true, className: "invisible", children: initials(name) }), _jsx("img", { src: src, alt: name, className: "absolute inset-0 size-full object-cover" })] }));
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
/* Each identity is a tint and an ink: the tint goes on the disc, the ink on the letters. */
|
|
91
|
+
const [tint = "", ink = ""] = toneOf(name, surface).split(" ");
|
|
92
|
+
return (
|
|
93
|
+
/* The tint lies over an OPAQUE disc of the surface. Laid straight over whatever is
|
|
94
|
+
behind, a translucent tint took that colour: on a calendar event the letters fell to
|
|
95
|
+
3.8:1. Over the surface it is the same disc everywhere, and the contrast is the one
|
|
96
|
+
measured for it. */
|
|
97
|
+
_jsxs("span", { title: name, "aria-hidden": true, className: `relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-pill font-medium select-none ${SIZE[size]} ${surface === "chrome" ? "bg-chrome" : "bg-surface"}`, children: [_jsx("span", { className: `absolute inset-0 ${tint}` }), _jsx("span", { className: `relative ${ink}`, children: initials(name) })] }));
|
|
91
98
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { type UiCopy } from "../../foundations/copy.js";
|
|
2
|
+
/** Context: `copy` defaults to the installed words — what a caller outside a component has;
|
|
3
|
+
* a component passes its branch's (`useUiCopy()`), so a provider reaches the sentence. */
|
|
4
|
+
export declare function formatRelative(when: Date, now?: Date, copy?: UiCopy): string;
|
|
5
|
+
export declare function formatDateTime(when: Date, locale?: string): string;
|
|
3
6
|
export declare function DateValue({ when, format,
|
|
4
7
|
/** So it can be tested: without this, a story with «hace 2 min» changes its
|
|
5
8
|
* text every minute and no snapshot works as a reference. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { currentCopy, currentCopyLocale, useUiCopy } from "../../foundations/copy.js";
|
|
3
|
+
import { currentCopy, currentCopyLocale, useUiCopy, } from "../../foundations/copy.js";
|
|
4
4
|
/* ==================================================================== *
|
|
5
5
|
* WHEN — a date says two things and they can't both be said together.
|
|
6
6
|
*
|
|
@@ -45,20 +45,21 @@ const STEPS = [
|
|
|
45
45
|
[HOUR, "hour"],
|
|
46
46
|
[DAY, "day"],
|
|
47
47
|
];
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
/** Context: `copy` defaults to the installed words — what a caller outside a component has;
|
|
49
|
+
* a component passes its branch's (`useUiCopy()`), so a provider reaches the sentence. */
|
|
50
|
+
export function formatRelative(when, now = new Date(), copy = currentCopy()) {
|
|
51
|
+
const locale = copy.locale;
|
|
50
52
|
const delta = when.getTime() - now.getTime();
|
|
51
53
|
const abs = Math.abs(delta);
|
|
52
54
|
if (abs < MINUTE)
|
|
53
|
-
return
|
|
55
|
+
return copy.time.justNow;
|
|
54
56
|
if (abs > 7 * DAY)
|
|
55
57
|
return dateFormat(locale).format(when);
|
|
56
58
|
const step = STEPS.find(([ms]) => abs < ms * 60) ?? STEPS[STEPS.length - 1];
|
|
57
59
|
const [ms, unit] = step;
|
|
58
60
|
return relativeFormat(locale).format(Math.round(delta / ms), unit);
|
|
59
61
|
}
|
|
60
|
-
export function formatDateTime(when) {
|
|
61
|
-
const locale = currentCopyLocale();
|
|
62
|
+
export function formatDateTime(when, locale = currentCopyLocale()) {
|
|
62
63
|
return `${dateFormat(locale).format(when)} ${timeFormat(locale).format(when)}`;
|
|
63
64
|
}
|
|
64
65
|
/** A day written as `YYYY-MM-DD` (what a date field stores) is that day HERE. `new Date()`
|
|
@@ -79,11 +80,11 @@ now, }) {
|
|
|
79
80
|
if (Number.isNaN(d.getTime())) {
|
|
80
81
|
return (_jsx("span", { className: "text-meta text-muted italic", title: copy.time.invalid, children: copy.time.noDate }));
|
|
81
82
|
}
|
|
82
|
-
const exact = formatDateTime(d);
|
|
83
|
+
const exact = formatDateTime(d, copy.locale);
|
|
83
84
|
const text = format === "exact"
|
|
84
85
|
? exact
|
|
85
86
|
: format === "date"
|
|
86
87
|
? dateFormat(copy.locale).format(d)
|
|
87
|
-
: formatRelative(d, now);
|
|
88
|
+
: formatRelative(d, now, copy);
|
|
88
89
|
return (_jsx("time", { dateTime: d.toISOString(), title: exact, className: "text-meta whitespace-nowrap tabular-nums text-muted", children: text }));
|
|
89
90
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { type FormMode } from "../../foundations/form.js";
|
|
1
2
|
import type { OpenTarget, Tone } from "../../foundations/types.js";
|
|
2
|
-
import { type FormMode } from "../field/mode.js";
|
|
3
3
|
import { type PersonContact } from "./contact.js";
|
|
4
4
|
import type { LucideIcon } from "lucide-react";
|
|
5
5
|
import { type ReactNode } from "react";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { fillCopy, useUiCopy } from "../../foundations/copy.js";
|
|
4
|
+
import { FieldIdsContext } from "../../foundations/form.js";
|
|
5
|
+
import { useFormMode } from "../../foundations/form.js";
|
|
4
6
|
import { cn, focusRing } from "../../foundations/variants.js";
|
|
5
7
|
import { Button, ButtonLink, IconButton } from "../button/Button.js";
|
|
6
8
|
import { CellStack, Thumb } from "../cell/CellStack.js";
|
|
7
|
-
import { FieldIdsContext } from "../field/context.js";
|
|
8
|
-
import { useFormMode } from "../field/mode.js";
|
|
9
9
|
import { Menu } from "../menu/Menu.js";
|
|
10
10
|
import { PopoverTrigger } from "../overlay/PopoverTrigger.js";
|
|
11
11
|
import { Preview } from "../overlay/Preview.js";
|
|
@@ -64,7 +64,10 @@ export function Cell({ value,
|
|
|
64
64
|
max = 48, }) {
|
|
65
65
|
const copy = useUiCopy();
|
|
66
66
|
if (value === null || value === undefined) {
|
|
67
|
-
return (
|
|
67
|
+
return (
|
|
68
|
+
/* Said by the word and the italic, in ink: muted, it fell under 4.5:1 on a toned
|
|
69
|
+
cell — and a missing value is exactly what someone has to see. */
|
|
70
|
+
_jsx("span", { className: "text-ink italic", title: copy.cell.missing, children: copy.cell.missing }));
|
|
68
71
|
}
|
|
69
72
|
if (typeof value === "number")
|
|
70
73
|
return _jsx(Numeric, { value: value, format: "decimal" });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Copyable, type CopyableProps, CopyButton, } from "./Copyable.js";
|
|
2
|
-
export { DateValue, formatDateTime, formatRelative, } from "./
|
|
2
|
+
export { DateValue, formatDateTime, formatRelative, } from "./DateValue.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, type PersonContact, UserChip, type UserChipProps, UserStack, } from "./Person.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Show a number or a datum so that it reads as such and not as text. */
|
|
2
2
|
export { Copyable, CopyButton, } from "./Copyable.js";
|
|
3
|
-
export { DateValue, formatDateTime, formatRelative, } from "./
|
|
3
|
+
export { DateValue, formatDateTime, formatRelative, } from "./DateValue.js";
|
|
4
4
|
export { Meter, meterLevel, } from "./Meter.js";
|
|
5
5
|
export { Metric, Metrics } from "./Metric.js";
|
|
6
6
|
export { Avatar, UserChip, UserStack, } from "./Person.js";
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { BoardStages } from "../../components/listing/BoardColumns.js";
|
|
2
2
|
import type { ListIdentity } from "../../components/listing/ListingBar.js";
|
|
3
3
|
import type { SortField } from "../../components/listing/SortMenu.js";
|
|
4
|
+
import type { ViewIcon } from "../../components/listing/ViewSwitcher.js";
|
|
4
5
|
import type { Surface } from "../../foundations/types.js";
|
|
5
6
|
import type { DataColumn, DataTableCreate } from "../../primitives/table/DataTable.js";
|
|
6
7
|
import type { RowAction } from "../../primitives/table/RowActions.js";
|
|
7
8
|
import type { SortState } from "../../primitives/table/Table.js";
|
|
8
|
-
import { type ListCalendar, type ListCrumb, type ListEmpty, type ListGantt, type ListGroup, type ListPivot, type ListPresent, type ListReport, type ListSheet, type ListTimeline, type RowOf } from "./types.js";
|
|
9
|
+
import { type ListCalendar, type ListCrumb, type ListEmpty, type ListGantt, type ListGroup, type ListPivot, type ListPresent, type ListReport, type ListSet, type ListSheet, type ListTimeline, type RowOf } from "./types.js";
|
|
9
10
|
import type { ReactNode } from "react";
|
|
10
11
|
type BarProps = {
|
|
11
12
|
children?: ReactNode;
|
|
@@ -58,6 +59,17 @@ type BoardProps<T> = {
|
|
|
58
59
|
* de datos CRUDOS sí las trae, porque ahí salen del archivo y el código no sabe
|
|
59
60
|
* cuáles son. */
|
|
60
61
|
type SheetProps<T> = Partial<ListSheet<T>>;
|
|
62
|
+
export type ListPresentProps<T> = {
|
|
63
|
+
/** Its own name — not one of the nine the package draws. What `present` asks for. */
|
|
64
|
+
id: string;
|
|
65
|
+
/** Its name in the switcher: the button's `title` and accessible name. */
|
|
66
|
+
label: string;
|
|
67
|
+
icon: ViewIcon;
|
|
68
|
+
/** It needs width — a grid of columns — so a narrow list (a phone, a panel) does not
|
|
69
|
+
* offer it. A map or a gallery reflows, and stays. */
|
|
70
|
+
wide?: boolean;
|
|
71
|
+
children: (set: ListSet<T>) => ReactNode;
|
|
72
|
+
};
|
|
61
73
|
export type ListProps<T extends object> = {
|
|
62
74
|
items: readonly T[];
|
|
63
75
|
keyOf: (item: T) => string;
|
|
@@ -138,5 +150,6 @@ export declare namespace List {
|
|
|
138
150
|
var Calendar: <T>(props: ListCalendar<T>) => ReactNode;
|
|
139
151
|
var Gantt: <T>(props: ListGantt<T>) => ReactNode;
|
|
140
152
|
var Timeline: <T>(props: ListTimeline<T>) => ReactNode;
|
|
153
|
+
var Present: <T>(props: ListPresentProps<T>) => ReactNode;
|
|
141
154
|
}
|
|
142
155
|
export {};
|
package/dist/views/list/List.js
CHANGED
|
@@ -61,6 +61,23 @@ const TimelineSlot = slot("timeline", (_props) => null);
|
|
|
61
61
|
const CalendarSlot = slot("calendar", (_props) => null);
|
|
62
62
|
/** Each record as a span on a timeline, with its dependencies (`RecordGantt`). */
|
|
63
63
|
const GanttSlot = slot("gantt", (_props) => null);
|
|
64
|
+
/* Through `unknown`, like `TableSlot`: the set both gives a `T` (`items`) and takes one
|
|
65
|
+
(`press`), so the props are invariant in `T`. */
|
|
66
|
+
const Present = slot("present", (_props) => null);
|
|
67
|
+
/** The presentations written with `List.Present`, checked once: an id that repeats or that
|
|
68
|
+
* shadows a built-in one would make the switcher offer two buttons for one thing. */
|
|
69
|
+
function facesOf(nodes) {
|
|
70
|
+
const faces = nodes
|
|
71
|
+
.filter((node) => slotOf(node) === "present")
|
|
72
|
+
.map((node) => propsOf(node))
|
|
73
|
+
.map(({ children, ...face }) => ({ ...face, render: children }));
|
|
74
|
+
for (const [at, face] of faces.entries()) {
|
|
75
|
+
if (face.id in PRESENT_OF || faces.findIndex((one) => one.id === face.id) !== at) {
|
|
76
|
+
throw new Error(`List.Present: «${face.id}» is already a presentation of this list`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return faces;
|
|
80
|
+
}
|
|
64
81
|
export function List({ items, keyOf, embedded, surface, group, selection: selectWith, sort, onSortChange, sortable, present, onPresentChange, onOpen: openWith, onPeek: peekWith, isPeeked, readOnly = false, rowClick, onChoose, state, filtered, empty, children, }) {
|
|
65
82
|
const top = flatten(children);
|
|
66
83
|
const onOpen = readOnly ? undefined : openWith;
|
|
@@ -86,13 +103,17 @@ export function List({ items, keyOf, embedded, surface, group, selection: select
|
|
|
86
103
|
/* Las caras que hay son las que están escritas, EN ESE ORDEN. El conmutador
|
|
87
104
|
no puede ofrecer una que no se pueda dibujar, porque la que se dibuja y la
|
|
88
105
|
que se ofrece son el mismo nodo. */
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
const faces = facesOf(top);
|
|
107
|
+
const presents = top.flatMap((node) => {
|
|
108
|
+
const name = slotOf(node);
|
|
109
|
+
if (name === "present")
|
|
110
|
+
return [propsOf(node).id];
|
|
111
|
+
const builtIn = name === undefined ? undefined : PRESENT_OF[name];
|
|
112
|
+
return builtIn === undefined ? [] : [builtIn];
|
|
113
|
+
});
|
|
93
114
|
/* La escotilla: lo que el arquetipo no previó se dibuja igual, debajo. Que
|
|
94
115
|
aparezca algo acá es la señal de que al arquetipo le falta una pieza. */
|
|
95
|
-
const rest = loose(top, ["bar", "metrics", ...FACES]);
|
|
116
|
+
const rest = loose(top, ["bar", "metrics", "present", ...FACES]);
|
|
96
117
|
return (_jsx(ListView, { items: items, keyOf: keyOf, row: rows === undefined
|
|
97
118
|
? () => ({ name: "" })
|
|
98
119
|
: readOnly
|
|
@@ -120,7 +141,7 @@ export function List({ items, keyOf, embedded, surface, group, selection: select
|
|
|
120
141
|
: { onVisibleColumnIdsChange: table.onVisibleColumnIdsChange }),
|
|
121
142
|
}), ...(board?.card === undefined ? {} : { card: board.card }), ...(board?.stages === undefined ? {} : { boardStages: board.stages }), ...(sheet?.columns === undefined || sheet.cell === undefined
|
|
122
143
|
? {}
|
|
123
|
-
: { sheet: sheet }), ...(report === undefined ? {} : { report }), ...(pivot === undefined ? {} : { pivot }), ...(calendar === undefined ? {} : { calendar }), ...(gantt === undefined ? {} : { gantt }), ...(timeline === undefined ? {} : { timeline }), ...(presents.length === 0 ? {} : { presents }), ...(present === undefined ? {} : { present }), ...(onPresentChange === undefined ? {} : { onPresentChange }), ...(group === undefined ? {} : { group }), ...(selection === undefined ? {} : { selection }), ...(sort === undefined ? {} : { sort }), ...(onSortChange === undefined ? {} : { onSortChange }), ...(sortable === undefined ? {} : { sortable }), ...(onOpen === undefined ? {} : { onOpen }), ...(onPeek === undefined ? {} : { onPeek }), ...(isPeeked === undefined ? {} : { isPeeked }), ...(rowClick === undefined ? {} : { rowClick }), ...(onChoose === undefined || readOnly ? {} : { onChoose }), ...(state === undefined ? {} : { state }), ...(filtered === undefined ? {} : { filtered }), ...(empty === undefined ? {} : { empty }), children: rest.length === 0 ? undefined : rest }));
|
|
144
|
+
: { sheet: sheet }), ...(report === undefined ? {} : { report }), ...(pivot === undefined ? {} : { pivot }), ...(calendar === undefined ? {} : { calendar }), ...(gantt === undefined ? {} : { gantt }), ...(timeline === undefined ? {} : { timeline }), ...(faces.length === 0 ? {} : { faces }), ...(presents.length === 0 ? {} : { presents }), ...(present === undefined ? {} : { present }), ...(onPresentChange === undefined ? {} : { onPresentChange }), ...(group === undefined ? {} : { group }), ...(selection === undefined ? {} : { selection }), ...(sort === undefined ? {} : { sort }), ...(onSortChange === undefined ? {} : { onSortChange }), ...(sortable === undefined ? {} : { sortable }), ...(onOpen === undefined ? {} : { onOpen }), ...(onPeek === undefined ? {} : { onPeek }), ...(isPeeked === undefined ? {} : { isPeeked }), ...(rowClick === undefined ? {} : { rowClick }), ...(onChoose === undefined || readOnly ? {} : { onChoose }), ...(state === undefined ? {} : { state }), ...(filtered === undefined ? {} : { filtered }), ...(empty === undefined ? {} : { empty }), children: rest.length === 0 ? undefined : rest }));
|
|
124
145
|
}
|
|
125
146
|
List.Bar = Bar;
|
|
126
147
|
List.Crumbs = Crumbs;
|
|
@@ -139,3 +160,4 @@ List.Pivot = Pivot;
|
|
|
139
160
|
List.Calendar = CalendarSlot;
|
|
140
161
|
List.Gantt = GanttSlot;
|
|
141
162
|
List.Timeline = TimelineSlot;
|
|
163
|
+
List.Present = Present;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ListViewProps } from "./types.js";
|
|
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, boardStages, calendar, gantt, timeline, sheet, report, pivot, present: requested, presents, onPresentChange, sort, onSortChange, sortable, totals, rowActions, create, group, selection, onOpen, onPeek, rowClick, onChoose, 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, boardStages, calendar, gantt, timeline, sheet, report, pivot, faces, present: requested, presents, onPresentChange, sort, onSortChange, sortable, totals, rowActions, create, group, selection, onOpen, onPeek, rowClick, onChoose, 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;
|
|
@@ -9,9 +9,9 @@ import { Listing } from "../../components/listing/Listing.js";
|
|
|
9
9
|
import { ListingBar } from "../../components/listing/ListingBar.js";
|
|
10
10
|
import { PivotExplorer } from "../../components/listing/PivotExplorer.js";
|
|
11
11
|
import { RecordCard } from "../../components/listing/RecordCard.js";
|
|
12
|
-
import { GroupHeader, Row, RowHeader } from "../../components/listing/Row.js";
|
|
12
|
+
import { GroupHeader, GroupMore, Row, RowHeader, } from "../../components/listing/Row.js";
|
|
13
13
|
import { sortItems, SortMenu, } from "../../components/listing/SortMenu.js";
|
|
14
|
-
import { ViewSwitcher } from "../../components/listing/ViewSwitcher.js";
|
|
14
|
+
import { ViewSwitcher, } from "../../components/listing/ViewSwitcher.js";
|
|
15
15
|
import { Breadcrumb } from "../../components/record/Breadcrumb.js";
|
|
16
16
|
import { RecordTimeline } from "../../components/timeline/RecordTimeline.js";
|
|
17
17
|
import { useUiCopy } from "../../foundations/copy.js";
|
|
@@ -22,7 +22,7 @@ import { Button } from "../../primitives/button/Button.js";
|
|
|
22
22
|
import { Empty, Failed, Skeleton } from "../../primitives/notice/Notice.js";
|
|
23
23
|
import { PivotTable } from "../../primitives/table/PivotTable.js";
|
|
24
24
|
import { ReportTable } from "../../primitives/table/ReportTable.js";
|
|
25
|
-
import { groupedColumnIds } from "./columns.js";
|
|
25
|
+
import { groupedColumnIds, WIDE_PRESENTS } from "./columns.js";
|
|
26
26
|
import { groupLevelsOf, reportColumnsOf, reportRowsOf, sheetFromColumns, sheetRowsOf, } from "./derive.js";
|
|
27
27
|
import { SheetPresentation, TablePresentation, } from "./presentations.js";
|
|
28
28
|
import { useNarrowList } from "./useNarrowList.js";
|
|
@@ -66,8 +66,13 @@ const PRESENT_ICONS = [
|
|
|
66
66
|
{ id: "gantt", icon: ChartGantt },
|
|
67
67
|
{ id: "timeline", icon: CalendarRange },
|
|
68
68
|
];
|
|
69
|
-
export function ListView({ items, keyOf, identity, crumbs, embedded = false, surface: requestedSurface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, boardStages, calendar, gantt, timeline, sheet, report, pivot, present: requested = "rows", presents, onPresentChange, sort, onSortChange, sortable, totals = false, rowActions, create, group, selection, onOpen, onPeek, rowClick = "peek", onChoose, state, filtered = false, empty, children, }) {
|
|
70
|
-
const
|
|
69
|
+
export function ListView({ items, keyOf, identity, crumbs, embedded = false, surface: requestedSurface, metrics, search, pagination, views, actions, row, rowHeader, columns, visibleColumnIds, onVisibleColumnIdsChange, card, boardStages, calendar, gantt, timeline, sheet, report, pivot, faces, present: requested = "rows", presents, onPresentChange, sort, onSortChange, sortable, totals = false, rowActions, create, group, selection, onOpen, onPeek, rowClick = "peek", onChoose, state, filtered = false, empty, children, }) {
|
|
70
|
+
const wide = useMemo(() => [
|
|
71
|
+
...WIDE_PRESENTS,
|
|
72
|
+
...(faces ?? []).filter((f) => f.wide === true).map((f) => f.id),
|
|
73
|
+
], [faces]);
|
|
74
|
+
const { frame, offered, present } = useNarrowList(presents, requested, wide);
|
|
75
|
+
const face = faces?.find((one) => one.id === present);
|
|
71
76
|
/* Embedded, the list sits on the record's paper: there is no dark band to inherit, and a
|
|
72
77
|
navy switcher inside a white sheet would be a second chrome on the screen. */
|
|
73
78
|
const surface = embedded ? undefined : requestedSurface;
|
|
@@ -99,14 +104,18 @@ export function ListView({ items, keyOf, identity, crumbs, embedded = false, sur
|
|
|
99
104
|
];
|
|
100
105
|
const shownColumns = columns === undefined ? undefined : visibleColumns(columns, tableIds);
|
|
101
106
|
const groupLevels = useMemo(() => groupLevelsOf(group, columns), [group, columns]);
|
|
107
|
+
/* In the order the tree wrote them — the application's own among the package's. */
|
|
108
|
+
const options = offered.flatMap((id) => {
|
|
109
|
+
const own = faces?.find((one) => one.id === id);
|
|
110
|
+
if (own !== undefined)
|
|
111
|
+
return [{ id, label: own.label, icon: own.icon }];
|
|
112
|
+
const builtIn = PRESENT_ICONS.find((option) => option.id === id);
|
|
113
|
+
return builtIn === undefined
|
|
114
|
+
? []
|
|
115
|
+
: [{ id, label: copy.present[builtIn.id], icon: builtIn.icon }];
|
|
116
|
+
});
|
|
102
117
|
const switcher = views ??
|
|
103
|
-
(
|
|
104
|
-
id: option.id,
|
|
105
|
-
label: copy.present[option.id],
|
|
106
|
-
icon: option.icon,
|
|
107
|
-
})), current: present, ...(onPresentChange === undefined
|
|
108
|
-
? {}
|
|
109
|
-
: { onSelect: (id) => onPresentChange(id) }), ...(surface === undefined ? {} : { surface }) })) : undefined);
|
|
118
|
+
(options.length > 1 ? (_jsx(ViewSwitcher, { options: options, current: present, ...(onPresentChange === undefined ? {} : { onSelect: onPresentChange }), ...(surface === undefined ? {} : { surface }) })) : undefined);
|
|
110
119
|
const sheetFromDeclared = useMemo(() => sheetFromColumns(shownColumns), [shownColumns]);
|
|
111
120
|
const sheetSpec = sheet ?? sheetFromDeclared;
|
|
112
121
|
/* El menú de columnas vale en `table` y en la planilla DERIVADA —las dos
|
|
@@ -244,7 +253,10 @@ export function ListView({ items, keyOf, identity, crumbs, embedded = false, sur
|
|
|
244
253
|
? null
|
|
245
254
|
: pile.piles.length > 0
|
|
246
255
|
? renderPiles(pile.piles, nodes)
|
|
247
|
-
: nodes(pile.items)
|
|
256
|
+
: nodes(pile.items), open &&
|
|
257
|
+
pile.piles.length === 0 &&
|
|
258
|
+
pile.items.length < pile.count &&
|
|
259
|
+
group?.onMore !== undefined ? (_jsx(GroupMore, { left: pile.count - pile.items.length, depth: pile.depth, onMore: () => group.onMore?.(pile) })) : null] }, key));
|
|
248
260
|
});
|
|
249
261
|
}
|
|
250
262
|
const reportRows = useMemo(() => reportRowsOf(piles, columns, row), [piles, columns, row]);
|
|
@@ -260,7 +272,22 @@ export function ListView({ items, keyOf, identity, crumbs, embedded = false, sur
|
|
|
260
272
|
const d = row(item);
|
|
261
273
|
return (_jsx(RecordCard, { title: d.name, ...(d.tags === undefined ? {} : { tags: d.tags }), ...(d.meta === undefined ? {} : { meta: d.meta }), ...(press === undefined ? {} : { onOpen: () => press(item) }) }, keyOf(item)));
|
|
262
274
|
};
|
|
263
|
-
const body =
|
|
275
|
+
const body = face !== undefined ? (face.render({
|
|
276
|
+
items: ordered,
|
|
277
|
+
keyOf,
|
|
278
|
+
piles,
|
|
279
|
+
isOpen,
|
|
280
|
+
...(group?.onToggle === undefined
|
|
281
|
+
? {}
|
|
282
|
+
: { toggle: (pile) => group.onToggle?.(pathKey(pile.path)) }),
|
|
283
|
+
...(group?.onMore === undefined ? {} : { more: group.onMore }),
|
|
284
|
+
...(selection === undefined
|
|
285
|
+
? {}
|
|
286
|
+
: { selection: { has: selection.has, toggle: selection.toggle } }),
|
|
287
|
+
...(press === undefined ? {} : { press }),
|
|
288
|
+
...(onPeek === undefined || choosing ? {} : { peek: onPeek }),
|
|
289
|
+
...(onOpen === undefined || choosing ? {} : { open: onOpen }),
|
|
290
|
+
})) : present === "table" && shownColumns !== undefined ? (
|
|
264
291
|
/* The table receives EVERYTHING that belongs to the set: see `TablePresentation`. */
|
|
265
292
|
_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 || choosing ? {} : { onPeek }), ...(onOpen === undefined || choosing ? {} : { onOpen }), ...(choosing ? { onChoose } : {}), rowClick: rowClick })) : present === "sheet" && sheetSpec !== undefined ? (
|
|
266
293
|
/* La planilla recibe el conjunto por ÍNDICE y no una matriz ya armada: ver `SheetPresentation`. */
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { List, type ListProps } from "./List.js";
|
|
2
|
-
export { type ListCrumb, type ListEmpty, type ListGroup, type ListPivot, type ListPresent, type ListReport, type ListSheet, type RowOf, } from "./types.js";
|
|
1
|
+
export { List, type ListPresentProps, type ListProps } from "./List.js";
|
|
2
|
+
export { type ListCrumb, type ListEmpty, type ListGroup, type ListPivot, type ListPresent, type ListReport, type ListSet, type ListSheet, type RowOf, } from "./types.js";
|
|
@@ -37,7 +37,9 @@ export function TablePresentation({ items, columns, keyOf, levels, group, totals
|
|
|
37
37
|
]),
|
|
38
38
|
...(rowActions?.(item) ?? []),
|
|
39
39
|
];
|
|
40
|
-
|
|
40
|
+
/* Piles counted by whoever keeps the data go through as they are: the table draws those,
|
|
41
|
+
not the ones it would build from the page. */
|
|
42
|
+
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 }), ...(group?.piles === undefined || levels.length === 0 ? {} : { piles: group.piles }), ...(group?.onMore === undefined ? {} : { onMore: group.onMore }), ...(selection === undefined
|
|
41
43
|
? {}
|
|
42
44
|
: {
|
|
43
45
|
selected: new Set(items.filter((i) => selection.has(keyOf(i))).map(keyOf)),
|
|
@@ -4,9 +4,10 @@ import type { BoardStages } from "../../components/listing/BoardColumns.js";
|
|
|
4
4
|
import type { ListIdentity } from "../../components/listing/ListingBar.js";
|
|
5
5
|
import type { ListPresent } from "../../components/listing/set.js";
|
|
6
6
|
import type { SortField } from "../../components/listing/SortMenu.js";
|
|
7
|
+
import type { ViewIcon } from "../../components/listing/ViewSwitcher.js";
|
|
7
8
|
import type { RecordTimelineProps } from "../../components/timeline/RecordTimeline.js";
|
|
8
9
|
import type { GroupableField } from "../../foundations/grouping.js";
|
|
9
|
-
import type { Grouping, GroupLevel } from "../../foundations/grouping.js";
|
|
10
|
+
import type { Grouping, GroupLevel, Pile } from "../../foundations/grouping.js";
|
|
10
11
|
import type { Pivot, PivotKey, PivotSpec } from "../../foundations/pivot.js";
|
|
11
12
|
import type { Surface, Tone } from "../../foundations/types.js";
|
|
12
13
|
import type { DataColumn, DataTableCreate } from "../../primitives/table/DataTable.js";
|
|
@@ -40,6 +41,51 @@ export type RowOf = {
|
|
|
40
41
|
children?: ReactNode;
|
|
41
42
|
actions?: ReactNode;
|
|
42
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* The set as a presentation receives it — what a `List.Present` draws from.
|
|
46
|
+
*
|
|
47
|
+
* Context: the built-in presentations do not each sort, group and wire selection on their
|
|
48
|
+
* own; the list does it once and hands them the result. A presentation the application
|
|
49
|
+
* writes gets the same hand-off, so a map or a gallery is one more way of looking at the
|
|
50
|
+
* SAME set: the bar's sort, the search's grouping, the selection and the rule of what a
|
|
51
|
+
* press on a record does all hold, and switching to it and back loses none of them.
|
|
52
|
+
*/
|
|
53
|
+
export type ListSet<T> = {
|
|
54
|
+
/** In the order the bar asks for. The page, when the list pages. */
|
|
55
|
+
items: readonly T[];
|
|
56
|
+
keyOf: (item: T) => string;
|
|
57
|
+
/** Grouped: the piles, outermost level first, each with its sub-piles or its items.
|
|
58
|
+
* `null` when the list is not grouped — draw `items`. */
|
|
59
|
+
piles: readonly Pile<T>[] | null;
|
|
60
|
+
/** Whether a pile is open, with the same keys every presentation folds by. */
|
|
61
|
+
isOpen: (pile: Pile<T>) => boolean;
|
|
62
|
+
/** Folds or unfolds a pile — present when the list lets it. */
|
|
63
|
+
toggle?: (pile: Pile<T>) => void;
|
|
64
|
+
/** Asks for the next page of a pile that holds fewer records than it counts
|
|
65
|
+
* (`pile.items.length < pile.count`) — present when whoever keeps the data can. */
|
|
66
|
+
more?: (pile: Pile<T>) => void;
|
|
67
|
+
selection?: {
|
|
68
|
+
has: (id: string) => boolean;
|
|
69
|
+
toggle: (id: string) => void;
|
|
70
|
+
};
|
|
71
|
+
/** What a press on a record does in THIS list: choose it, look at it or open it, as the
|
|
72
|
+
* list decided (`onChoose`, `rowClick`). Call this from the body of a card or a marker. */
|
|
73
|
+
press?: (item: T) => void;
|
|
74
|
+
/** The two ways in, for a presentation that offers both buttons (👁 and ↗). Absent while
|
|
75
|
+
* the list is choosing. */
|
|
76
|
+
peek?: (item: T) => void;
|
|
77
|
+
open?: (item: T) => void;
|
|
78
|
+
};
|
|
79
|
+
/** A presentation the application writes, as the list receives it from `List.Present`. */
|
|
80
|
+
export type ListFace<T> = {
|
|
81
|
+
id: string;
|
|
82
|
+
/** Its name in the switcher — the `title` and the accessible name of its button. */
|
|
83
|
+
label: string;
|
|
84
|
+
icon: ViewIcon;
|
|
85
|
+
/** It needs width (a grid of columns): a narrow list does not offer it. */
|
|
86
|
+
wide?: boolean;
|
|
87
|
+
render: (set: ListSet<T>) => ReactNode;
|
|
88
|
+
};
|
|
43
89
|
/** A crumb of the list: where I came from. */
|
|
44
90
|
export type ListCrumb = {
|
|
45
91
|
label: string;
|
|
@@ -279,6 +325,8 @@ export type ListViewProps<T extends object> = {
|
|
|
279
325
|
* elegirlo acá sería adivinar la pregunta.
|
|
280
326
|
*/
|
|
281
327
|
pivot?: ListPivot<T>;
|
|
328
|
+
/** The presentations the application wrote (`List.Present`), by id. */
|
|
329
|
+
faces?: readonly ListFace<T>[];
|
|
282
330
|
present?: ListPresent;
|
|
283
331
|
/** Which presentations this list offers. Two or more draw the switcher. */
|
|
284
332
|
presents?: readonly ListPresent[];
|
|
@@ -13,7 +13,7 @@ import { type RefObject } from "react";
|
|
|
13
13
|
* Measured BEFORE paint: waiting for the observer's first report drew the table and swapped it
|
|
14
14
|
* for rows a frame later, so a click on a row of a list in a panel landed on a detached `<tr>`.
|
|
15
15
|
*/
|
|
16
|
-
export declare function useNarrowList(presents: readonly ListPresent[] | undefined, requested: ListPresent): {
|
|
16
|
+
export declare function useNarrowList(presents: readonly ListPresent[] | undefined, requested: ListPresent, wide?: readonly ListPresent[]): {
|
|
17
17
|
frame: RefObject<HTMLDivElement | null>;
|
|
18
18
|
offered: readonly ListPresent[];
|
|
19
19
|
present: ListPresent;
|
|
@@ -21,7 +21,7 @@ export declare function useNarrowList(presents: readonly ListPresent[] | undefin
|
|
|
21
21
|
/** What a list offers and draws at its width. Only a list that HAS rows folds into them: one
|
|
22
22
|
* that declares just a table fell back to rows it had no `row` for, and drew empty lines — a
|
|
23
23
|
* table that scrolls sideways says more. */
|
|
24
|
-
export declare function narrowed(presents: readonly ListPresent[] | undefined, requested: ListPresent, narrow: boolean): {
|
|
24
|
+
export declare function narrowed(presents: readonly ListPresent[] | undefined, requested: ListPresent, narrow: boolean, wide?: readonly ListPresent[]): {
|
|
25
25
|
offered: readonly ListPresent[];
|
|
26
26
|
present: ListPresent;
|
|
27
27
|
};
|
|
@@ -15,7 +15,7 @@ import { useLayoutEffect, useRef, useState } from "react";
|
|
|
15
15
|
* Measured BEFORE paint: waiting for the observer's first report drew the table and swapped it
|
|
16
16
|
* for rows a frame later, so a click on a row of a list in a panel landed on a detached `<tr>`.
|
|
17
17
|
*/
|
|
18
|
-
export function useNarrowList(presents, requested) {
|
|
18
|
+
export function useNarrowList(presents, requested, wide = WIDE_PRESENTS) {
|
|
19
19
|
const frame = useRef(null);
|
|
20
20
|
const [narrow, setNarrow] = useState(false);
|
|
21
21
|
useLayoutEffect(() => {
|
|
@@ -32,15 +32,15 @@ export function useNarrowList(presents, requested) {
|
|
|
32
32
|
watch.observe(el);
|
|
33
33
|
return () => watch.disconnect();
|
|
34
34
|
}, []);
|
|
35
|
-
return { frame, ...narrowed(presents, requested, narrow) };
|
|
35
|
+
return { frame, ...narrowed(presents, requested, narrow, wide) };
|
|
36
36
|
}
|
|
37
37
|
/** What a list offers and draws at its width. Only a list that HAS rows folds into them: one
|
|
38
38
|
* that declares just a table fell back to rows it had no `row` for, and drew empty lines — a
|
|
39
39
|
* table that scrolls sideways says more. */
|
|
40
|
-
export function narrowed(presents, requested, narrow) {
|
|
40
|
+
export function narrowed(presents, requested, narrow, wide = WIDE_PRESENTS) {
|
|
41
41
|
const folds = narrow && (presents === undefined || presents.includes("rows"));
|
|
42
42
|
return {
|
|
43
|
-
offered: (presents ?? []).filter((p) => !folds || !
|
|
44
|
-
present: folds &&
|
|
43
|
+
offered: (presents ?? []).filter((p) => !folds || !wide.includes(p)),
|
|
44
|
+
present: folds && wide.includes(requested) ? "rows" : requested,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
@@ -14,7 +14,7 @@ import { useUiCopy } from "../../foundations/copy.js";
|
|
|
14
14
|
import { byDensity, useDensity } from "../../foundations/density.js";
|
|
15
15
|
import { flatten, pick as pickSlot, pickAll, propsOf, slot, slotOf, } from "../../foundations/slots.js";
|
|
16
16
|
import { createNoteRegistry, NoteRegistryContext, } from "../../primitives/field/note.js";
|
|
17
|
-
import { Tabs } from "../../primitives/tabs/Tabs.js";
|
|
17
|
+
import { Tabs, TabsPanel, TabsScope, } from "../../primitives/tabs/Tabs.js";
|
|
18
18
|
import { useEffect, useId, useState, useSyncExternalStore } from "react";
|
|
19
19
|
const pick = (nodes, name) => pickSlot(nodes, name);
|
|
20
20
|
/** El riel: mi lugar delante del registro. Sin él, no hay banda — y eso
|
|
@@ -68,6 +68,10 @@ const Facts = slot("facts", (_props) => null);
|
|
|
68
68
|
* que no está escrita no tiene solapa, y ésa es toda la declaración. */
|
|
69
69
|
const Pages = slot("pages", (_props) => null);
|
|
70
70
|
const Page = slot("page", (_props) => null);
|
|
71
|
+
/** The notebook's tabs and its page share an id — only when there are tabs. */
|
|
72
|
+
function NotebookScope({ tabs, children }) {
|
|
73
|
+
return tabs ? _jsx(TabsScope, { children: children }) : children;
|
|
74
|
+
}
|
|
71
75
|
export function Record({ identity, error = null, dirty, children }) {
|
|
72
76
|
const d = useDensity();
|
|
73
77
|
const copy = useUiCopy();
|
|
@@ -166,48 +170,48 @@ export function Record({ identity, error = null, dirty, children }) {
|
|
|
166
170
|
shorter than the screen. The extra height has no paint of its own: on a desk
|
|
167
171
|
nothing changes. */
|
|
168
172
|
/* The record knows the notes of its fields and rows: their cards register here. */
|
|
169
|
-
_jsx(NoteRegistryContext, { value: registry, children: _jsx("article", { className: "flex min-w-0 flex-1 flex-col", children: _jsx(RecordHeader, { railSurface: surface, ...(ribbon === undefined
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
173
|
+
_jsx(NoteRegistryContext, { value: registry, children: _jsx("article", { className: "flex min-w-0 flex-1 flex-col", children: _jsx(NotebookScope, { tabs: tabs.length > 0, children: _jsx(RecordHeader, { railSurface: surface, ...(ribbon === undefined
|
|
174
|
+
? {}
|
|
175
|
+
: {
|
|
176
|
+
ribbon: (_jsx(RecordRibbon, { label: ribbon.label, ...(ribbon.tone === undefined ? {} : { tone: ribbon.tone }) })),
|
|
177
|
+
}), ...(paper?.width === undefined ? {} : { width: paper.width }), ...(dirty === undefined ? {} : { dirty }), ...(crumbs === undefined ? {} : { crumbs }), ...(pager === undefined
|
|
178
|
+
? {}
|
|
179
|
+
: {
|
|
180
|
+
pager: (_jsx(PagerControl, { index: pager.index, total: pager.total, surface: surface, ...(pager.onPrev === undefined ? {} : { onPrev: pager.onPrev }), ...(pager.onNext === undefined ? {} : { onNext: pager.onNext }) })),
|
|
181
|
+
}), ...(actions === undefined ? {} : { actions }), ...(statusBlock === undefined ? {} : { status: statusBlock }), ...(identity.icon === undefined ? {} : { icon: identity.icon }), title: identity.title, ...(identity.subtitle === undefined ? {} : { subtitle: identity.subtitle }), ...(identity.figure === undefined ? {} : { figure: identity.figure }), ...(identity.tag === undefined ? {} : { tag: identity.tag }), ...(smart === undefined || smart.length === 0
|
|
182
|
+
? {}
|
|
183
|
+
: {
|
|
184
|
+
smart: (_jsx(SmartButtons, { children: smart.map((s) => (_jsx(SmartButton, { icon: s.icon, ...(s.count === undefined ? {} : { count: s.count }), label: s.label, layout: onTheRail && d === "comfortable" ? "inline" : "stacked", ...(s.onClick === undefined ? {} : { onClick: s.onClick }) }, s.label))) })),
|
|
185
|
+
}), ...(aspectsNode === undefined || globalSheet ? {} : { aspects: aspectsNode }), ...(activitySlot === undefined
|
|
186
|
+
? {}
|
|
187
|
+
: {
|
|
188
|
+
activity: (_jsx(Activity, { ...activitySlot, alerts: rest, alertsId: alertsId, open: activityOpen, onToggle: () => setActivityOpen(!activityOpen) })),
|
|
189
|
+
activityLayout: activitySlot.layout ?? "auto",
|
|
190
|
+
}), ...(blocking.length === 0 && error === null
|
|
191
|
+
? {}
|
|
192
|
+
: {
|
|
193
|
+
blocking: (_jsx(RecordBlocking, { notices: blocking, error: error, errorHeading: copy.failed.operation })),
|
|
194
|
+
}), ...(rest.length === 0 && (activitySlot === undefined || notes.length === 0)
|
|
195
|
+
? {}
|
|
196
|
+
: {
|
|
197
|
+
indicator: (_jsx(RecordNoticeIndicator, { notices: rest, anchored: notes.map((entry) => ({ tone: entry.note.tone ?? "info" })), ...(activitySlot === undefined
|
|
198
|
+
? {}
|
|
199
|
+
: {
|
|
200
|
+
/* With a panel, the notices live there: the indicator goes to them
|
|
201
|
+
instead of floating a second copy in a popover. */
|
|
202
|
+
reveal: {
|
|
203
|
+
target: alertsId,
|
|
204
|
+
onReveal: () => {
|
|
205
|
+
setActivityOpen(true);
|
|
206
|
+
setReveal((n) => n + 1);
|
|
207
|
+
},
|
|
203
208
|
},
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
: {}), children: [pageBody, below] }) }), audit === undefined ? null : _jsx(RecordAudit, { ...audit })] }) }) }) }));
|
|
209
|
+
}) })),
|
|
210
|
+
}), children: _jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: `flex min-w-0 flex-col ${byDensity(d, "gap-(--spacing-block) px-4 pt-(--spacing-block) pb-4", "gap-2.5 pt-2.5 pb-2")}`, children: _jsxs(Sheet, { layout: paper?.layout ?? "stacked", columns: paper?.columns ?? 2, ...(hasFacts ? { fields } : {}), ...(above.length > 0 || (globalSheet && aspectsNode !== undefined)
|
|
211
|
+
? {
|
|
212
|
+
head: (_jsxs(_Fragment, { children: [above, globalSheet && aspectsNode !== undefined ? (_jsx("div", { className: `border-b border-line-strong ${byDensity(d, "-mx-4 px-4", "")}`, children: aspectsNode })) : null] })),
|
|
213
|
+
}
|
|
214
|
+
: {}), children: [tabs.length === 0 ? (pageBody) : (_jsx(TabsPanel, { id: current, className: `flex min-w-0 flex-col ${byDensity(d, "gap-(--spacing-block)", "gap-2.5")}`, children: pageBody })), below] }) }), audit === undefined ? null : _jsx(RecordAudit, { ...audit })] }) }) }) }) }));
|
|
211
215
|
}
|
|
212
216
|
Record.Skeleton = RecordSkeleton;
|
|
213
217
|
Record.Rail = Rail;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sincpro/web-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "An enterprise web design system for business software — ERPs, back offices, management tools — in React and Tailwind: tokens, primitives, components and the two views every management screen is made of.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|