@sincpro/web-ui 0.1.0 → 1.0.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 +40 -13
- package/dist/components/activity/Activity.d.ts +69 -0
- package/dist/components/activity/Activity.js +279 -0
- package/dist/components/activity/ActivityBadge.d.ts +16 -0
- package/dist/components/activity/ActivityBadge.js +29 -0
- package/dist/components/{chatter → activity}/Messages.d.ts +2 -2
- package/dist/components/{chatter → activity}/Messages.js +9 -6
- package/dist/components/activity/index.d.ts +4 -0
- package/dist/components/activity/index.js +5 -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/calendar/RecordCalendar.d.ts +48 -0
- package/dist/components/calendar/RecordCalendar.js +101 -0
- package/dist/components/calendar/index.d.ts +1 -0
- package/dist/components/calendar/index.js +1 -0
- package/dist/components/form/Sheet.d.ts +4 -0
- package/dist/components/form/Sheet.js +16 -5
- package/dist/components/gantt/RecordGantt.d.ts +44 -0
- package/dist/components/gantt/RecordGantt.js +110 -0
- package/dist/components/gantt/index.d.ts +1 -0
- package/dist/components/gantt/index.js +1 -0
- package/dist/components/index.d.ts +4 -1
- package/dist/components/index.js +4 -1
- package/dist/components/lines/LineItems.d.ts +45 -5
- package/dist/components/lines/LineItems.js +106 -18
- package/dist/components/listing/BoardColumns.d.ts +39 -0
- package/dist/components/listing/BoardColumns.js +138 -0
- package/dist/components/listing/Listing.js +1 -1
- package/dist/components/listing/ListingBar.d.ts +46 -2
- package/dist/components/listing/ListingBar.js +47 -5
- package/dist/components/listing/PivotExplorer.d.ts +34 -0
- package/dist/components/listing/PivotExplorer.js +86 -0
- package/dist/components/listing/RecordCard.d.ts +6 -8
- package/dist/components/listing/RecordCard.js +13 -7
- package/dist/components/listing/Row.d.ts +25 -2
- package/dist/components/listing/Row.js +30 -13
- package/dist/components/listing/index.d.ts +2 -0
- package/dist/components/listing/index.js +2 -0
- package/dist/components/listing/set.d.ts +1 -1
- package/dist/components/navigation/index.d.ts +0 -2
- package/dist/components/navigation/index.js +2 -3
- package/dist/components/record/RecordAudit.d.ts +17 -0
- package/dist/components/record/RecordAudit.js +27 -0
- package/dist/components/record/RecordHeader.d.ts +27 -17
- package/dist/components/record/RecordHeader.js +64 -20
- package/dist/components/record/RecordNotices.d.ts +37 -0
- package/dist/components/record/RecordNotices.js +75 -0
- package/dist/components/record/RecordRibbon.d.ts +13 -0
- package/dist/components/record/RecordRibbon.js +22 -0
- package/dist/components/record/ThumbBar.js +1 -1
- package/dist/components/record/index.d.ts +2 -0
- package/dist/components/record/index.js +2 -0
- package/dist/components/search/CriteriaChips.d.ts +6 -1
- package/dist/components/search/CriteriaChips.js +71 -20
- package/dist/components/search/SearchBar.d.ts +4 -1
- package/dist/components/search/SearchBar.js +15 -7
- package/dist/components/timeline/RecordTimeline.d.ts +60 -0
- package/dist/components/timeline/RecordTimeline.js +214 -0
- package/dist/components/timeline/TimelineToolbar.d.ts +30 -0
- package/dist/components/timeline/TimelineToolbar.js +31 -0
- package/dist/components/timeline/index.d.ts +3 -0
- package/dist/components/timeline/index.js +3 -0
- package/dist/components/timeline/time.d.ts +43 -0
- package/dist/components/timeline/time.js +135 -0
- package/dist/foundations/copy.d.ts +194 -18
- package/dist/foundations/copy.es.js +142 -15
- package/dist/foundations/copy.js +133 -11
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/match.d.ts +23 -0
- package/dist/foundations/match.js +63 -0
- package/dist/foundations/slots.d.ts +1 -1
- package/dist/foundations/slots.js +8 -3
- package/dist/foundations/types.d.ts +7 -0
- package/dist/foundations/types.js +0 -36
- package/dist/primitives/block/index.d.ts +1 -1
- package/dist/primitives/block/index.js +1 -1
- package/dist/primitives/cell/CellStack.d.ts +7 -1
- package/dist/primitives/cell/CellStack.js +5 -2
- package/dist/primitives/choice/ComboBox.d.ts +3 -0
- package/dist/primitives/choice/ComboBox.js +10 -6
- package/dist/primitives/choice/KanbanState.d.ts +14 -0
- package/dist/primitives/choice/KanbanState.js +37 -0
- package/dist/primitives/choice/Priority.d.ts +20 -0
- package/dist/primitives/choice/Priority.js +41 -0
- package/dist/primitives/choice/SearchField.d.ts +10 -1
- package/dist/primitives/choice/SearchField.js +21 -2
- package/dist/primitives/choice/Slider.d.ts +6 -1
- package/dist/primitives/choice/Slider.js +2 -2
- package/dist/primitives/choice/index.d.ts +2 -0
- package/dist/primitives/choice/index.js +2 -0
- 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/Dialog.d.ts +9 -3
- package/dist/primitives/dialog/Dialog.js +41 -5
- 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 +2 -1
- package/dist/primitives/notice/index.js +2 -1
- package/dist/primitives/overlay/Preview.d.ts +19 -0
- package/dist/primitives/overlay/Preview.js +69 -0
- package/dist/primitives/overlay/index.d.ts +1 -0
- package/dist/primitives/overlay/index.js +3 -1
- package/dist/primitives/picker/MatchedText.d.ts +10 -0
- package/dist/primitives/picker/MatchedText.js +12 -0
- package/dist/primitives/picker/Picker.d.ts +67 -4
- package/dist/primitives/picker/Picker.js +142 -23
- 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 +102 -2
- package/dist/primitives/table/EditableTable.js +287 -32
- package/dist/primitives/table/ReportTable.js +2 -1
- package/dist/primitives/table/RowActions.js +7 -2
- package/dist/primitives/table/SheetTable.d.ts +4 -1
- package/dist/primitives/table/SheetTable.js +38 -5
- package/dist/primitives/table/Table.d.ts +5 -0
- package/dist/primitives/table/Table.js +17 -8
- 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/Tags.d.ts +2 -0
- package/dist/primitives/tag/Tags.js +2 -1
- package/dist/primitives/tag/TagsField.d.ts +13 -0
- package/dist/primitives/tag/TagsField.js +39 -10
- package/dist/primitives/tag/choices.d.ts +2 -0
- 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/Avatar.d.ts +16 -0
- package/dist/primitives/value/Avatar.js +91 -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/Person.d.ts +6 -51
- package/dist/primitives/value/Person.js +9 -148
- package/dist/primitives/value/ProgressBar.d.ts +31 -0
- package/dist/primitives/value/ProgressBar.js +53 -0
- package/dist/primitives/value/Relation.d.ts +22 -5
- package/dist/primitives/value/Relation.js +42 -14
- 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/contact.d.ts +30 -0
- package/dist/primitives/value/contact.js +51 -0
- package/dist/primitives/value/index.d.ts +5 -4
- package/dist/primitives/value/index.js +5 -4
- package/dist/tokens.css +179 -7
- package/dist/views/list/List.d.ts +32 -3
- package/dist/views/list/List.js +51 -7
- package/dist/views/list/ListView.d.ts +1 -1
- package/dist/views/list/ListView.js +70 -13
- package/dist/views/list/columns.js +8 -1
- package/dist/views/list/derive.d.ts +12 -1
- package/dist/views/list/derive.js +29 -3
- package/dist/views/list/presentations.d.ts +5 -2
- package/dist/views/list/presentations.js +35 -3
- package/dist/views/list/types.d.ts +57 -1
- package/dist/views/list/useNarrowList.d.ts +10 -0
- package/dist/views/list/useNarrowList.js +20 -6
- package/dist/views/record/Record.d.ts +41 -8
- package/dist/views/record/Record.js +113 -28
- package/dist/views/record/index.d.ts +1 -1
- package/package.json +15 -4
- package/dist/components/chatter/Chatter.d.ts +0 -161
- package/dist/components/chatter/Chatter.js +0 -232
- package/dist/components/chatter/index.d.ts +0 -3
- package/dist/components/chatter/index.js +0 -4
- package/dist/components/navigation/CommandPalette.d.ts +0 -40
- package/dist/components/navigation/CommandPalette.js +0 -114
- package/dist/components/navigation/commands.d.ts +0 -30
- package/dist/components/navigation/commands.js +0 -30
- /package/dist/components/{chatter → activity}/Timeline.d.ts +0 -0
- /package/dist/components/{chatter → activity}/Timeline.js +0 -0
|
@@ -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,14 @@ 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
|
+
rowClick?: "peek" | "open";
|
|
20
|
+
onChoose?: (item: T) => void;
|
|
21
|
+
};
|
|
19
22
|
/** The table receives EVERYTHING that belongs to the set —sorting, selection, grouping,
|
|
20
23
|
* which columns are on screen— and not a trimmed down version: that was exactly the trap
|
|
21
24
|
* 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;
|
|
25
|
+
export declare function TablePresentation<T extends object>({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, create, onPeek, onOpen, rowClick, onChoose, }: TableProps<T>): import("react").JSX.Element;
|
|
23
26
|
type SheetProps<T extends object> = {
|
|
24
27
|
spec: ListSheet<T>;
|
|
25
28
|
/** The flattened bands and rows when the set is grouped; `null` when it is not. */
|
|
@@ -3,10 +3,40 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import { useUiCopy } from "../../foundations/copy.js";
|
|
4
4
|
import { DataTable } from "../../primitives/table/DataTable.js";
|
|
5
5
|
import { SheetTable } from "../../primitives/table/SheetTable.js";
|
|
6
|
+
import { Eye, SquareArrowOutUpRight } from "lucide-react";
|
|
6
7
|
/** The table receives EVERYTHING that belongs to the set —sorting, selection, grouping,
|
|
7
8
|
* which columns are on screen— and not a trimmed down version: that was exactly the trap
|
|
8
9
|
* 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, }) {
|
|
10
|
+
export function TablePresentation({ items, columns, keyOf, levels, group, totals, sort, onSortChange, selection, rowActions, create, onPeek, onOpen, rowClick = "peek", onChoose, }) {
|
|
11
|
+
const copy = useUiCopy();
|
|
12
|
+
const press = onChoose ?? (rowClick === "open" ? (onOpen ?? onPeek) : (onPeek ?? onOpen));
|
|
13
|
+
/* The row's ways in go FIRST among its actions, so they are always the inline ones and
|
|
14
|
+
always in the same place; the domain's actions follow (and fold into ⋯ past two). */
|
|
15
|
+
const withOpeners = onPeek === undefined && onOpen === undefined
|
|
16
|
+
? rowActions
|
|
17
|
+
: (item) => [
|
|
18
|
+
...(onPeek === undefined
|
|
19
|
+
? []
|
|
20
|
+
: [
|
|
21
|
+
{
|
|
22
|
+
id: "peek",
|
|
23
|
+
label: copy.list.peek,
|
|
24
|
+
icon: Eye,
|
|
25
|
+
onSelect: () => onPeek(item),
|
|
26
|
+
},
|
|
27
|
+
]),
|
|
28
|
+
...(onOpen === undefined
|
|
29
|
+
? []
|
|
30
|
+
: [
|
|
31
|
+
{
|
|
32
|
+
id: "open",
|
|
33
|
+
label: copy.list.open,
|
|
34
|
+
icon: SquareArrowOutUpRight,
|
|
35
|
+
onSelect: () => onOpen(item),
|
|
36
|
+
},
|
|
37
|
+
]),
|
|
38
|
+
...(rowActions?.(item) ?? []),
|
|
39
|
+
];
|
|
10
40
|
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
41
|
? {}
|
|
12
42
|
: {
|
|
@@ -22,7 +52,7 @@ export function TablePresentation({ items, columns, keyOf, levels, group, totals
|
|
|
22
52
|
selection.toggle(id);
|
|
23
53
|
}
|
|
24
54
|
},
|
|
25
|
-
}), ...(totals ? { totals: true } : {}), ...(
|
|
55
|
+
}), ...(totals ? { totals: true } : {}), ...(withOpeners === undefined ? {} : { rowActions: withOpeners }), ...(create === undefined ? {} : { create }), ...(press === undefined ? {} : { onRowClick: press }) }));
|
|
26
56
|
}
|
|
27
57
|
/** The sheet receives the set by INDEX and not a ready-made matrix: `SheetTable` is
|
|
28
58
|
* virtualized precisely so as not to materialize a million rows, and handing it copies
|
|
@@ -99,5 +129,7 @@ export function SheetPresentation({ spec, entries, ordered, group, }) {
|
|
|
99
129
|
? false
|
|
100
130
|
: (spec.editable?.(item, column, columnIndex) ?? false);
|
|
101
131
|
},
|
|
102
|
-
})
|
|
132
|
+
}), ...(spec.onAddRow === undefined || entries !== null
|
|
133
|
+
? {}
|
|
134
|
+
: { onAddRow: spec.onAddRow }) }));
|
|
103
135
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import type { RecordCalendarProps } from "../../components/calendar/RecordCalendar.js";
|
|
2
|
+
import type { RecordGanttProps } from "../../components/gantt/RecordGantt.js";
|
|
3
|
+
import type { BoardStages } from "../../components/listing/BoardColumns.js";
|
|
1
4
|
import type { ListIdentity } from "../../components/listing/ListingBar.js";
|
|
2
5
|
import type { ListPresent } from "../../components/listing/set.js";
|
|
3
6
|
import type { SortField } from "../../components/listing/SortMenu.js";
|
|
7
|
+
import type { RecordTimelineProps } from "../../components/timeline/RecordTimeline.js";
|
|
8
|
+
import type { GroupableField } from "../../foundations/grouping.js";
|
|
4
9
|
import type { Grouping, GroupLevel } from "../../foundations/grouping.js";
|
|
5
10
|
import type { Pivot, PivotKey, PivotSpec } from "../../foundations/pivot.js";
|
|
6
11
|
import type { Surface, Tone } from "../../foundations/types.js";
|
|
7
|
-
import type { DataColumn } from "../../primitives/table/DataTable.js";
|
|
12
|
+
import type { DataColumn, DataTableCreate } from "../../primitives/table/DataTable.js";
|
|
8
13
|
import type { ReportColumn, ReportRow } from "../../primitives/table/ReportTable.js";
|
|
9
14
|
import type { RowAction } from "../../primitives/table/RowActions.js";
|
|
10
15
|
import type { SheetColumn } from "../../primitives/table/SheetTable.js";
|
|
@@ -23,6 +28,11 @@ export type { ListPresent };
|
|
|
23
28
|
/** What an item looks like when the presentation is rows. */
|
|
24
29
|
export type RowOf = {
|
|
25
30
|
icon?: LucideIcon;
|
|
31
|
+
/** A person or a company: its face in the icon's place — the photo or the initials. */
|
|
32
|
+
avatar?: {
|
|
33
|
+
name: string;
|
|
34
|
+
src?: string;
|
|
35
|
+
};
|
|
26
36
|
name: string;
|
|
27
37
|
tags?: ReactNode;
|
|
28
38
|
meta?: string;
|
|
@@ -87,6 +97,9 @@ export type ListSheet<T> = {
|
|
|
87
97
|
* convertirlo al tipo de la columna es del dominio, no de acá. */
|
|
88
98
|
onCommit?: (item: T, column: SheetColumn, columnIndex: number, next: string) => void;
|
|
89
99
|
editable?: (item: T, column: SheetColumn, columnIndex: number) => boolean;
|
|
100
|
+
/** Present = the sheet adds rows: «add a row» under it, and `Enter` on the last row.
|
|
101
|
+
* The consumer appends the item; the sheet lands on it. Not while grouped. */
|
|
102
|
+
onAddRow?: () => void;
|
|
90
103
|
};
|
|
91
104
|
/**
|
|
92
105
|
* El INFORME de una lista: los períodos y la jerarquía que termina en totales.
|
|
@@ -150,6 +163,12 @@ export type ListPivot<T> = {
|
|
|
150
163
|
/** Qué pasa al tocar un cruce: abrir las filas que cayeron ahí. */
|
|
151
164
|
onCell?: (row: PivotKey, column: PivotKey) => void;
|
|
152
165
|
height?: number | string;
|
|
166
|
+
/** The fields the person may pivot by. With them (and `spec`) the pivot is EXPLORED — axes,
|
|
167
|
+
* measures and download on the grid (`PivotExplorer`) — and its rows follow the search
|
|
168
|
+
* bar's grouping while there is one; `spec.rows` / `spec.columns` are where it starts. */
|
|
169
|
+
fields?: readonly GroupableField[];
|
|
170
|
+
/** Which of `spec.measures` start on. The first one by default. */
|
|
171
|
+
defaultMeasures?: readonly string[];
|
|
153
172
|
};
|
|
154
173
|
export type ListViewProps<T extends object> = {
|
|
155
174
|
items: readonly T[];
|
|
@@ -160,6 +179,11 @@ export type ListViewProps<T extends object> = {
|
|
|
160
179
|
/** The metrics that also NARROW: «2 por confirmar», «41 por entregar». They go
|
|
161
180
|
* below the bar and above the rows — they belong to the set, not to the frame. */
|
|
162
181
|
metrics?: ReactNode;
|
|
182
|
+
/** The list is a FIELD of a record (a one2many / many2many) and not a screen: the bar
|
|
183
|
+
* is one line — search, count, sort, columns, switcher, actions —, it does not stick
|
|
184
|
+
* and it does not move into the frame's header. Identity and crumbs are not drawn: the
|
|
185
|
+
* record around it already says them. See `ListingBar`'s header. */
|
|
186
|
+
embedded?: boolean;
|
|
163
187
|
/** Which surface the BAR sits on. `canvas` (the default) is a light control bar;
|
|
164
188
|
* `chrome` turns it into a dark band — an explicit choice, since the application bar
|
|
165
189
|
* is the screen's one dark band (same as the rail of a record). */
|
|
@@ -212,8 +236,20 @@ export type ListViewProps<T extends object> = {
|
|
|
212
236
|
/** What gets done to ONE row without entering it, in the table presentation.
|
|
213
237
|
* They are drawn hidden and appear on the row being pointed at. */
|
|
214
238
|
rowActions?: (item: T) => readonly RowAction[];
|
|
239
|
+
/** Write a new record as a row of the table presentation — Odoo's editable list. The
|
|
240
|
+
* columns that declare `input` get a control in that row. See `DataTable`'s header.
|
|
241
|
+
* While a record is being written the table shows even if the set is empty. */
|
|
242
|
+
create?: DataTableCreate<T>;
|
|
215
243
|
/** The board presentation. */
|
|
216
244
|
card?: (item: T) => ReactNode;
|
|
245
|
+
/** The board by stages: one column each, cards moved between them. */
|
|
246
|
+
boardStages?: BoardStages<T>;
|
|
247
|
+
/** The calendar presentation: when each record happens. */
|
|
248
|
+
calendar?: ListCalendar<T>;
|
|
249
|
+
/** The Gantt presentation: each record as a span on a timeline. */
|
|
250
|
+
gantt?: ListGantt<T>;
|
|
251
|
+
/** The planning presentation: records grouped in rows across time (Odoo's Gantt). */
|
|
252
|
+
timeline?: ListTimeline<T>;
|
|
217
253
|
/**
|
|
218
254
|
* La PLANILLA. Con esto, `present="sheet"` dibuja un `SheetTable`.
|
|
219
255
|
*
|
|
@@ -254,10 +290,24 @@ export type ListViewProps<T extends object> = {
|
|
|
254
290
|
count: number;
|
|
255
291
|
clear: () => void;
|
|
256
292
|
actions?: ReactNode;
|
|
293
|
+
/** Every record that matches, not just the page: «Elegir los 187 que coinciden». The total
|
|
294
|
+
* is the server's; `onSelect` makes the selection mean «all of them». */
|
|
295
|
+
matching?: {
|
|
296
|
+
total: number;
|
|
297
|
+
onSelect: () => void;
|
|
298
|
+
};
|
|
257
299
|
};
|
|
258
300
|
onOpen?: (item: T) => void;
|
|
259
301
|
onPeek?: (item: T) => void;
|
|
260
302
|
isPeeked?: (item: T) => boolean;
|
|
303
|
+
/** What a press on the row's body does when both ways in exist. `peek` (the default) looks
|
|
304
|
+
* without leaving the list; `open` goes to the record — a workspace whose rule is «a row
|
|
305
|
+
* opens the page» (the composer's) says `open`, and 👁 stays for the look. */
|
|
306
|
+
rowClick?: "peek" | "open";
|
|
307
|
+
/** The list CHOOSES instead of opening — a «Buscar más…», a chooser a workspace asked for:
|
|
308
|
+
* a press on a row (its body, its name, a card) calls this, and the row offers no 👁 / ↗.
|
|
309
|
+
* For several at once, give `selection` too and toggle it here. */
|
|
310
|
+
onChoose?: (item: T) => void;
|
|
261
311
|
/** The three states, in a single place. Every view used to re-assemble them
|
|
262
312
|
* with three nested ternaries, and that is why «empty because of a filter»
|
|
263
313
|
* and «really empty» got mixed up in half the screens. */
|
|
@@ -270,3 +320,9 @@ export type ListViewProps<T extends object> = {
|
|
|
270
320
|
/** The escape hatch. */
|
|
271
321
|
children?: ReactNode;
|
|
272
322
|
};
|
|
323
|
+
/** `List.Calendar`: the calendar's own props; the records, their key and «open» are the list's. */
|
|
324
|
+
export type ListCalendar<T> = Omit<RecordCalendarProps<T>, "items" | "keyOf" | "onOpen">;
|
|
325
|
+
/** `List.Gantt`: the chart's own props; the records, their key and «open» are the list's. */
|
|
326
|
+
export type ListGantt<T> = Omit<RecordGanttProps<T>, "items" | "keyOf" | "onOpen">;
|
|
327
|
+
/** `List.Timeline`: the planning's own props; the records, their key and «open» are the list's. */
|
|
328
|
+
export type ListTimeline<T> = Omit<RecordTimelineProps<T>, "items" | "keyOf" | "onOpen">;
|
|
@@ -9,9 +9,19 @@ import { type RefObject } from "react";
|
|
|
9
9
|
*
|
|
10
10
|
* Attach `frame` to the list's root element; `offered` is what the switcher may show and
|
|
11
11
|
* `present` what to draw (a wide one that was asked for falls back to rows).
|
|
12
|
+
*
|
|
13
|
+
* Measured BEFORE paint: waiting for the observer's first report drew the table and swapped it
|
|
14
|
+
* for rows a frame later, so a click on a row of a list in a panel landed on a detached `<tr>`.
|
|
12
15
|
*/
|
|
13
16
|
export declare function useNarrowList(presents: readonly ListPresent[] | undefined, requested: ListPresent): {
|
|
14
17
|
frame: RefObject<HTMLDivElement | null>;
|
|
15
18
|
offered: readonly ListPresent[];
|
|
16
19
|
present: ListPresent;
|
|
17
20
|
};
|
|
21
|
+
/** What a list offers and draws at its width. Only a list that HAS rows folds into them: one
|
|
22
|
+
* that declares just a table fell back to rows it had no `row` for, and drew empty lines — a
|
|
23
|
+
* table that scrolls sideways says more. */
|
|
24
|
+
export declare function narrowed(presents: readonly ListPresent[] | undefined, requested: ListPresent, narrow: boolean): {
|
|
25
|
+
offered: readonly ListPresent[];
|
|
26
|
+
present: ListPresent;
|
|
27
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { HANDHELD_WIDTH } from "../../foundations/layout.js";
|
|
3
3
|
import { WIDE_PRESENTS } from "./columns.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
5
5
|
/**
|
|
6
6
|
* A narrow LIST — a phone, a drawer, a panel among four — does not offer the presentations
|
|
7
7
|
* that need width: a seven-column table at 360 px is a horizontal scroll nobody reads.
|
|
@@ -11,13 +11,19 @@ import { useEffect, useRef, useState } from "react";
|
|
|
11
11
|
*
|
|
12
12
|
* Attach `frame` to the list's root element; `offered` is what the switcher may show and
|
|
13
13
|
* `present` what to draw (a wide one that was asked for falls back to rows).
|
|
14
|
+
*
|
|
15
|
+
* Measured BEFORE paint: waiting for the observer's first report drew the table and swapped it
|
|
16
|
+
* for rows a frame later, so a click on a row of a list in a panel landed on a detached `<tr>`.
|
|
14
17
|
*/
|
|
15
18
|
export function useNarrowList(presents, requested) {
|
|
16
19
|
const frame = useRef(null);
|
|
17
20
|
const [narrow, setNarrow] = useState(false);
|
|
18
|
-
|
|
21
|
+
useLayoutEffect(() => {
|
|
19
22
|
const el = frame.current;
|
|
20
|
-
if (el === null
|
|
23
|
+
if (el === null)
|
|
24
|
+
return;
|
|
25
|
+
setNarrow(el.getBoundingClientRect().width < HANDHELD_WIDTH);
|
|
26
|
+
if (typeof ResizeObserver === "undefined")
|
|
21
27
|
return;
|
|
22
28
|
const watch = new ResizeObserver(([entry]) => {
|
|
23
29
|
if (entry !== undefined)
|
|
@@ -26,7 +32,15 @@ export function useNarrowList(presents, requested) {
|
|
|
26
32
|
watch.observe(el);
|
|
27
33
|
return () => watch.disconnect();
|
|
28
34
|
}, []);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
return { frame, ...narrowed(presents, requested, narrow) };
|
|
36
|
+
}
|
|
37
|
+
/** What a list offers and draws at its width. Only a list that HAS rows folds into them: one
|
|
38
|
+
* that declares just a table fell back to rows it had no `row` for, and drew empty lines — a
|
|
39
|
+
* table that scrolls sideways says more. */
|
|
40
|
+
export function narrowed(presents, requested, narrow) {
|
|
41
|
+
const folds = narrow && (presents === undefined || presents.includes("rows"));
|
|
42
|
+
return {
|
|
43
|
+
offered: (presents ?? []).filter((p) => !folds || !WIDE_PRESENTS.includes(p)),
|
|
44
|
+
present: folds && WIDE_PRESENTS.includes(requested) ? "rows" : requested,
|
|
45
|
+
};
|
|
32
46
|
}
|
|
@@ -1,12 +1,15 @@
|
|
|
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 RecordStamp } from "../../components/record/RecordAudit.js";
|
|
6
|
+
import { type RecordNoticeSpec } from "../../components/record/RecordNotices.js";
|
|
4
7
|
import { RecordSkeleton } from "../../components/record/RecordSkeleton.js";
|
|
5
8
|
import { type Stage } from "../../components/record/StatusBar.js";
|
|
6
9
|
import type { Surface, Tone } from "../../foundations/types.js";
|
|
7
10
|
import { type TabNotice } from "../../primitives/tabs/Tabs.js";
|
|
8
11
|
import type { LucideIcon } from "lucide-react";
|
|
9
|
-
import type
|
|
12
|
+
import { type ReactNode } from "react";
|
|
10
13
|
export type RecordIdentity = {
|
|
11
14
|
icon?: LucideIcon;
|
|
12
15
|
title: ReactNode;
|
|
@@ -42,6 +45,9 @@ export type RecordPager = {
|
|
|
42
45
|
onNext?: () => void;
|
|
43
46
|
};
|
|
44
47
|
export type { SheetField };
|
|
48
|
+
/** A notice of the record: the props of `Record.Notice` (a `Callout` without its × label,
|
|
49
|
+
* which the record writes from the copy table). */
|
|
50
|
+
export type RecordNotice = RecordNoticeSpec;
|
|
45
51
|
type RailProps = {
|
|
46
52
|
children?: ReactNode;
|
|
47
53
|
/** The rail's surface. `canvas` (the default) is a light control bar; `chrome` is the dark
|
|
@@ -63,6 +69,8 @@ type StatusProps = {
|
|
|
63
69
|
/** Cuál de las etapas es la de ahora. Sin esto, la primera. */
|
|
64
70
|
current?: string;
|
|
65
71
|
failed?: boolean;
|
|
72
|
+
/** The stages can be chosen: pressing one moves the record there (a CRM's pipeline). */
|
|
73
|
+
onSelect?: (id: string) => void;
|
|
66
74
|
/** La escotilla del estado, para lo que no es ninguna de las dos. */
|
|
67
75
|
children?: ReactNode;
|
|
68
76
|
};
|
|
@@ -71,6 +79,9 @@ type PaperProps = {
|
|
|
71
79
|
* valor, que es la forma de Odoo. */
|
|
72
80
|
layout?: SheetLayout;
|
|
73
81
|
columns?: 1 | 2 | 3 | 4;
|
|
82
|
+
/** `reading` (default): the sheet stops at a reading width, centred, with the rail lined
|
|
83
|
+
* up to it. `full`: the whole page, for a record whose body is mostly a wide table. */
|
|
84
|
+
width?: "reading" | "full";
|
|
74
85
|
children?: ReactNode;
|
|
75
86
|
};
|
|
76
87
|
type FactsProps = {
|
|
@@ -95,9 +106,27 @@ type PageProps = {
|
|
|
95
106
|
notice?: TabNotice;
|
|
96
107
|
children?: ReactNode;
|
|
97
108
|
};
|
|
109
|
+
/** The record's ACTIVITY panel, as DATA: its conversation, its history, its composer.
|
|
110
|
+
* The record draws the `Activity` itself and gives it what only the record has — its
|
|
111
|
+
* notices (the ones that are not blocking), and the indicator in the rail that opens the
|
|
112
|
+
* panel on them.
|
|
113
|
+
*
|
|
114
|
+
* Context: it was `<Record.Chatter><Chatter open onToggle …/></Record.Chatter>`, a node
|
|
115
|
+
* the record could only place. Written as data — like `Record.Status` — the record owns
|
|
116
|
+
* the panel's open state (`defaultOpen`, or `open` + `onOpenChange` to control it), so
|
|
117
|
+
* «⚠ 2 avisos» in the rail can open it and move the focus to its notices. */
|
|
118
|
+
export type RecordActivityProps = Omit<ActivityProps, "open" | "onToggle" | "alerts" | "alertsId"> & {
|
|
119
|
+
/** Starts OPEN unless this says otherwise: on a big screen you see what the record has. */
|
|
120
|
+
defaultOpen?: boolean;
|
|
121
|
+
/** Controls the panel: then `onOpenChange` must follow it. Remembering it between
|
|
122
|
+
* records is the app's — the system only reports. */
|
|
123
|
+
open?: boolean;
|
|
124
|
+
onOpenChange?: (open: boolean) => void;
|
|
125
|
+
};
|
|
98
126
|
export type RecordProps = {
|
|
99
127
|
identity: RecordIdentity;
|
|
100
|
-
/** Lo que falló al operar sobre el registro. Va
|
|
128
|
+
/** Lo que falló al operar sobre el registro. Va con los avisos que bloquean, primero:
|
|
129
|
+
* entre el riel y el papel, siempre a la vista (ver `Record.Notice`). */
|
|
101
130
|
error?: string | null;
|
|
102
131
|
/** Hay cambios sin guardar. Su presencia REEMPLAZA los botones de acción por
|
|
103
132
|
* guardar y descartar — ver la nota en `RecordHeader`. */
|
|
@@ -114,13 +143,17 @@ export declare namespace Record {
|
|
|
114
143
|
var Actions: ((props: ActionsProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"actions">;
|
|
115
144
|
var Status: ((props: StatusProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"status">;
|
|
116
145
|
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">;
|
|
146
|
+
var Activity: ((props: RecordActivityProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"activity">;
|
|
123
147
|
var Facts: ((props: FactsProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"facts">;
|
|
124
148
|
var Pages: ((props: PagesProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"pages">;
|
|
125
149
|
var Page: ((props: PageProps) => ReactNode) & import("../../foundations/slots.js").Slotted<"page">;
|
|
150
|
+
var Notice: ((props: RecordNoticeSpec) => ReactNode) & import("../../foundations/slots.js").Slotted<"notice">;
|
|
151
|
+
var Ribbon: ((props: {
|
|
152
|
+
label: string;
|
|
153
|
+
tone?: Tone;
|
|
154
|
+
}) => ReactNode) & import("../../foundations/slots.js").Slotted<"ribbon">;
|
|
155
|
+
var Audit: ((props: {
|
|
156
|
+
created?: RecordStamp;
|
|
157
|
+
updated?: RecordStamp;
|
|
158
|
+
}) => ReactNode) & import("../../foundations/slots.js").Slotted<"audit">;
|
|
126
159
|
}
|