@lotics/ui 27.15.0 → 27.15.1
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 +2 -0
- package/package.json +1 -1
- package/src/date_stamp.tsx +34 -11
package/docs/catalog.md
CHANGED
|
@@ -1056,6 +1056,8 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
1056
1056
|
empty — and a ladder of fields is a form with invisible borders. Reach for `InlineDatePicker`
|
|
1057
1057
|
when a person is expected to ENTER the date, and this when the system already knows it.
|
|
1058
1058
|
Empty renders a thin rule, not a placeholder; read-only (omit `onChange`) renders text alone.
|
|
1059
|
+
`onChange` fires on CLOSE, not on each pick — one commit per visit, and a dismissed panel
|
|
1060
|
+
still writes whatever was picked in it, which is what makes a single tap enough.
|
|
1059
1061
|
Worked screen: `examples/tpl_record.tsx` § Progress.
|
|
1060
1062
|
- **`check_circle`** — `CheckCircle`: the completion ring — `state="none" | "partial" | "done"`,
|
|
1061
1063
|
springing to a filled check when done, distinct from the square checkbox; the
|
package/package.json
CHANGED
package/src/date_stamp.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useRef, useState } from "react";
|
|
2
2
|
import { Pressable, View } from "react-native";
|
|
3
3
|
import { Text } from "./text";
|
|
4
4
|
import { Icon } from "./icon";
|
|
@@ -50,6 +50,10 @@ export function DateStamp(props: DateStampProps) {
|
|
|
50
50
|
const [hovered, setHovered] = useState(false);
|
|
51
51
|
const [open, setOpen] = useState(false);
|
|
52
52
|
const [draft, setDraft] = useState<string | null>(value);
|
|
53
|
+
// The panel emits its pick and asks to close in the SAME event, so a commit
|
|
54
|
+
// that read `draft` off render state would still see the value the pick just
|
|
55
|
+
// replaced. This is what the close path reads instead.
|
|
56
|
+
const picked = useRef<string | null>(value);
|
|
53
57
|
|
|
54
58
|
const shown = value ? formatDate(value, { locale: tag }) : "";
|
|
55
59
|
|
|
@@ -57,21 +61,34 @@ export function DateStamp(props: DateStampProps) {
|
|
|
57
61
|
// so a caller can drop this into a column without a conditional.
|
|
58
62
|
if (!onChange) return shown ? <Text size="xs" color="muted">{shown}</Text> : null;
|
|
59
63
|
|
|
64
|
+
// Commit on CLOSE, matching `InlineDatePicker`: a single pick and the panel's
|
|
65
|
+
// Today button both auto-close, so committing on CHANGE instead would fire
|
|
66
|
+
// twice and a dismissed panel would still write.
|
|
67
|
+
//
|
|
68
|
+
// It has to be THIS function rather than `onOpenChange`, and every close has to
|
|
69
|
+
// route through it: a day press closes the panel via `onRequestClose`, which
|
|
70
|
+
// never reaches `onOpenChange`, so a commit living there is skipped by the one
|
|
71
|
+
// path this component exists for — picking a date. The popover shuts, the
|
|
72
|
+
// correction is discarded, and nothing says so. A stamp that silently drops the
|
|
73
|
+
// correction is worse than a read-only one.
|
|
74
|
+
const commit = () => {
|
|
75
|
+
setOpen(false);
|
|
76
|
+
if (picked.current !== value) onChange(picked.current ?? "");
|
|
77
|
+
};
|
|
78
|
+
const reopen = () => {
|
|
79
|
+
picked.current = value;
|
|
80
|
+
setDraft(value);
|
|
81
|
+
setOpen(true);
|
|
82
|
+
};
|
|
83
|
+
|
|
60
84
|
return (
|
|
61
85
|
<Popover
|
|
62
86
|
open={open}
|
|
63
|
-
onOpenChange={(next) => {
|
|
64
|
-
setOpen(next);
|
|
65
|
-
// Commit on CLOSE, matching `InlineDatePicker`: a single pick and the
|
|
66
|
-
// panel's Today button both auto-close through here, so committing on
|
|
67
|
-
// change instead would fire twice and a dismissed panel would still write.
|
|
68
|
-
if (!next && draft !== value) onChange(draft ?? "");
|
|
69
|
-
if (next) setDraft(value);
|
|
70
|
-
}}
|
|
87
|
+
onOpenChange={(next) => { if (next) reopen(); else commit(); }}
|
|
71
88
|
>
|
|
72
89
|
<PopoverTrigger>
|
|
73
90
|
<Pressable
|
|
74
|
-
onPress={
|
|
91
|
+
onPress={reopen}
|
|
75
92
|
onHoverIn={() => setHovered(true)}
|
|
76
93
|
onHoverOut={() => setHovered(false)}
|
|
77
94
|
accessibilityRole="button"
|
|
@@ -114,7 +131,13 @@ export function DateStamp(props: DateStampProps) {
|
|
|
114
131
|
</Pressable>
|
|
115
132
|
</PopoverTrigger>
|
|
116
133
|
<PopoverContent>
|
|
117
|
-
<DatePickerPanel
|
|
134
|
+
<DatePickerPanel
|
|
135
|
+
value={draft}
|
|
136
|
+
onValueChange={(iso) => { picked.current = iso; setDraft(iso); }}
|
|
137
|
+
format="date"
|
|
138
|
+
locale={tag}
|
|
139
|
+
onRequestClose={commit}
|
|
140
|
+
/>
|
|
118
141
|
</PopoverContent>
|
|
119
142
|
</Popover>
|
|
120
143
|
);
|