@lotics/ui 28.2.0 → 28.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/docs/catalog.md +5 -0
- package/docs/composition.md +4 -1
- package/examples/tpl_record.tsx +13 -10
- package/package.json +1 -1
- package/src/record_summary.tsx +29 -5
package/docs/catalog.md
CHANGED
|
@@ -922,6 +922,11 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
922
922
|
`metric` {label,value,tone,note} pinned right, the band's ONE accent. The record's FIELDS
|
|
923
923
|
never live in the header: compose them as `DetailTable`s in the sections below. Replaces
|
|
924
924
|
hand-rolled record headers (mixed scales, several competing figures, color noise).
|
|
925
|
+
`metric.value` also takes a NODE, for the one case of a figure that has not loaded yet — pass
|
|
926
|
+
a `Skeleton` and it renders in place of the styled figure, in a slot holding that figure's own
|
|
927
|
+
line box, so the band is the same height either way and a loading record's header does not
|
|
928
|
+
move when the number lands. Still ONE number: a node is a stand-in for it, not a licence to
|
|
929
|
+
put a control in the slot.
|
|
925
930
|
- **`ledger`** — `Ledger` + `LedgerGroup` + `LedgerBasis` + `LedgerRow` + `LedgerTotal` — the
|
|
926
931
|
record-level money list: every figure on ONE right-aligned tabular column, `peek` turns a row
|
|
927
932
|
into a pressable door floating its particulars in an anchored popover (put links INSIDE the
|
package/docs/composition.md
CHANGED
|
@@ -46,7 +46,10 @@ restyle a heading level per-page.
|
|
|
46
46
|
(`##` — xl semibold, optional muted `description` and `info` popover), everything left-aligned
|
|
47
47
|
at the column edge; `SectionHeadingMeta`, any VIEW control, and the section's own ADD ride the
|
|
48
48
|
heading row's right edge (the title's `flex: 1` pushes them) — see the add-placement law
|
|
49
|
-
below.
|
|
49
|
+
below. A COUNT earns that slot only when what it counts is not fully on screen — collapsed,
|
|
50
|
+
paged, or long enough that the reader would have to scan to know. Over a list or thread
|
|
51
|
+
rendered whole directly beneath its own heading it restates what is already in view, and the
|
|
52
|
+
heading reads busier for it. The page column is a **`SectionStack`** — it owns the
|
|
50
53
|
between-section law (a fixed 56px beat + a bare hairline separating one section from the NEXT;
|
|
51
54
|
null/false children are skipped so a conditional section never leaves a stray hairline). The
|
|
52
55
|
`Divider` NEVER goes directly under a heading — that orphans the title from its own content.
|
package/examples/tpl_record.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import type { PickerOption } from "@lotics/ui/picker";
|
|
|
12
12
|
import { Combobox, ComboboxInput, ComboboxContent } from "@lotics/ui/combobox";
|
|
13
13
|
import { DetailRow, DetailTable } from "@lotics/ui/detail_row";
|
|
14
14
|
import { Callout, CalloutText } from "@lotics/ui/callout";
|
|
15
|
-
import { Section, SectionHeading,
|
|
15
|
+
import { Section, SectionHeading, SectionHeadingTitle, Subsection, SubsectionHeading, SubsectionHeadingTitle } from "@lotics/ui/section_heading";
|
|
16
16
|
import { SectionStack, SubsectionStack } from "@lotics/ui/section_stack";
|
|
17
17
|
import { Checklist, ChecklistActions, ChecklistGroup, ChecklistItem, ChecklistNote } from "@lotics/ui/checklist";
|
|
18
18
|
import { DateStamp } from "@lotics/ui/date_stamp";
|
|
@@ -2381,9 +2381,13 @@ export function TplRecord({ chrome = "page", code = "RC-2026-0418", openSection
|
|
|
2381
2381
|
{!wide ? (
|
|
2382
2382
|
<View onLayout={nav.register("comments")}>
|
|
2383
2383
|
<Section>
|
|
2384
|
+
{/* No count. The thread is RIGHT THERE — the number restates what
|
|
2385
|
+
the reader is already looking at, and it is the kind of meta that
|
|
2386
|
+
earns its place only when the thing it counts is collapsed, or
|
|
2387
|
+
off-screen, or expensive to scan. None of those hold for a
|
|
2388
|
+
discussion rendered in full directly beneath its own heading. */}
|
|
2384
2389
|
<SectionHeading>
|
|
2385
2390
|
<SectionHeadingTitle description="Notes on this record — everyone with access sees them.">Comments</SectionHeadingTitle>
|
|
2386
|
-
<SectionHeadingMeta>{`${comments.length} ${comments.length === 1 ? "comment" : "comments"}`}</SectionHeadingMeta>
|
|
2387
2391
|
</SectionHeading>
|
|
2388
2392
|
{commentsThread}
|
|
2389
2393
|
</Section>
|
|
@@ -2626,9 +2630,9 @@ export function TplRecord({ chrome = "page", code = "RC-2026-0418", openSection
|
|
|
2626
2630
|
the verb is off-screen entirely, and on an empty list there is no
|
|
2627
2631
|
last row to sit under, so it had to be a SECOND button inside the
|
|
2628
2632
|
`EmptyState`. One verb, two renderings, neither findable without
|
|
2629
|
-
scanning. The heading row is the section's control line —
|
|
2630
|
-
|
|
2631
|
-
|
|
2633
|
+
scanning. The heading row is the section's control line — where a
|
|
2634
|
+
section's meta and verbs sit, with the title growing to push its
|
|
2635
|
+
siblings right — so the add belongs on it, in the same spot
|
|
2632
2636
|
whether the list holds nought or forty. */}
|
|
2633
2637
|
<Button title="Add fee" color="primary" onPress={addFee} />
|
|
2634
2638
|
</SectionHeading>
|
|
@@ -3632,13 +3636,12 @@ export function TplRecord({ chrome = "page", code = "RC-2026-0418", openSection
|
|
|
3632
3636
|
{/* The panel is a PEER of the sections beside it, not a widget, so its
|
|
3633
3637
|
title takes the ramp's section rung rather than a hand-picked size —
|
|
3634
3638
|
and it takes the WHOLE construct. `SectionHeadingTitle` carries
|
|
3635
|
-
`flex: 1` so it can push
|
|
3636
|
-
straight into this column it grows VERTICALLY instead
|
|
3637
|
-
thread beneath it. The row wrapper is what makes that
|
|
3638
|
-
it was written to mean. */}
|
|
3639
|
+
`flex: 1` so it can push a heading row's trailing content to the right
|
|
3640
|
+
edge; dropped straight into this column it grows VERTICALLY instead
|
|
3641
|
+
and starves the thread beneath it. The row wrapper is what makes that
|
|
3642
|
+
flex mean what it was written to mean. */}
|
|
3639
3643
|
<SectionHeading>
|
|
3640
3644
|
<SectionHeadingTitle>Comments</SectionHeadingTitle>
|
|
3641
|
-
<SectionHeadingMeta>{`${comments.length} ${comments.length === 1 ? "comment" : "comments"}`}</SectionHeadingMeta>
|
|
3642
3645
|
</SectionHeading>
|
|
3643
3646
|
{/* The panel's OWN scroller, so a long thread scrolls inside itself and
|
|
3644
3647
|
never lengthens the record. The thread inside it is the same one the
|
package/package.json
CHANGED
package/src/record_summary.tsx
CHANGED
|
@@ -5,8 +5,20 @@ import { Text } from "./text";
|
|
|
5
5
|
export interface RecordSummaryMetric {
|
|
6
6
|
/** Caption above the number ("Outstanding", "Total value"). */
|
|
7
7
|
label: string;
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The headline figure — rendered lg semibold tabular.
|
|
10
|
+
*
|
|
11
|
+
* A NODE is accepted for one reason: the figure is not known yet, and the
|
|
12
|
+
* surface wants a placeholder (a `Skeleton`) in its place while the record
|
|
13
|
+
* loads. It is rendered INSTEAD of the styled `Text`, not inside it — a `View`
|
|
14
|
+
* nested in a `Text` is not a thing React Native supports — into a slot that
|
|
15
|
+
* reserves the figure's own line box, so a placeholder cannot change the
|
|
16
|
+
* band's height and the caller never has to know what that height is.
|
|
17
|
+
*
|
|
18
|
+
* It is still ONE headline number. A node here is a stand-in for the number,
|
|
19
|
+
* never a licence to put a control or a second figure in the slot.
|
|
20
|
+
*/
|
|
21
|
+
value: ReactNode;
|
|
10
22
|
/** Valence of the figure (and its note) — the summary's ONE permitted accent. */
|
|
11
23
|
tone?: "default" | "danger" | "warning" | "success";
|
|
12
24
|
/** One short qualifier under the number ("Overdue 25 days"). */
|
|
@@ -65,9 +77,13 @@ export function RecordSummary(props: RecordSummaryProps) {
|
|
|
65
77
|
<Text size="xs" color="muted" weight="medium" align="right">
|
|
66
78
|
{metric.label}
|
|
67
79
|
</Text>
|
|
68
|
-
|
|
69
|
-
{metric.
|
|
70
|
-
|
|
80
|
+
{typeof metric.value === "string" ? (
|
|
81
|
+
<Text size="lg" weight="semibold" tabular align="right" color={metric.tone === "default" ? undefined : metric.tone}>
|
|
82
|
+
{metric.value}
|
|
83
|
+
</Text>
|
|
84
|
+
) : (
|
|
85
|
+
<View style={styles.metricSlot}>{metric.value}</View>
|
|
86
|
+
)}
|
|
71
87
|
{metric.note ? (
|
|
72
88
|
<Text size="xs" align="right" weight={metric.tone && metric.tone !== "default" ? "medium" : "regular"} color={metric.tone && metric.tone !== "default" ? metric.tone : "muted"}>
|
|
73
89
|
{metric.note}
|
|
@@ -100,4 +116,12 @@ const styles = StyleSheet.create({
|
|
|
100
116
|
alignItems: "flex-end",
|
|
101
117
|
gap: 1,
|
|
102
118
|
},
|
|
119
|
+
// The figure's line box, held open for a non-string value so the band is the
|
|
120
|
+
// same height whether it holds the number or a placeholder. 30 is `Text` size
|
|
121
|
+
// `lg`'s lineHeight (src/text.tsx) — the height the styled figure occupies.
|
|
122
|
+
metricSlot: {
|
|
123
|
+
height: 30,
|
|
124
|
+
justifyContent: "center",
|
|
125
|
+
alignItems: "flex-end",
|
|
126
|
+
},
|
|
103
127
|
});
|