@lotics/ui 12.1.0 → 12.1.2
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 -3
- package/package.json +1 -1
- package/src/choice_list.tsx +47 -36
- package/src/clarify.tsx +14 -24
- package/src/remark_gfm_safe.ts +23 -0
package/docs/catalog.md
CHANGED
|
@@ -934,9 +934,11 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
|
|
|
934
934
|
`ChangeRecord` (THE item card: registers like a Change; tone wash + localized op word;
|
|
935
935
|
verb level follows the decision level) · `ChangeBand` (the raw ± band) ·
|
|
936
936
|
`ChangeValueInput` (the diff-at-rest editor); the `changeReview` locale slice.
|
|
937
|
-
- **`clarify`** — `Clarify`: the agent asks back
|
|
938
|
-
|
|
939
|
-
|
|
937
|
+
- **`clarify`** — `Clarify`: the agent asks back — a borderless block (question + a
|
|
938
|
+
`ChoiceList`), no card wrapper.
|
|
939
|
+
- **`choice_list`** — `ChoiceList` + `ChoiceOption`: selectable answer options as
|
|
940
|
+
divider-separated rows (no bordered cards) with a per-row focus ring + hover wash; the
|
|
941
|
+
agent's quick-reply surface.
|
|
940
942
|
- **`sources`** — `Sources` + `SourceRef`/`SourceKind` (record | document | table | web |
|
|
941
943
|
knowledge): provenance chips, per-kind glyphs.
|
|
942
944
|
- **`finding`** — `Finding` + `FindingComparison` + `FindingSeverity`/`FindingLabels`: one
|
package/package.json
CHANGED
package/src/choice_list.tsx
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Pressable, View } from "react-native";
|
|
2
2
|
import { colors } from "./colors";
|
|
3
3
|
import { Text } from "./text";
|
|
4
4
|
import { Icon } from "./icon";
|
|
5
|
-
import {
|
|
5
|
+
import { Divider } from "./divider";
|
|
6
|
+
import { useFocusRing } from "./use_focus_ring";
|
|
7
|
+
import { FOCUS_RING } from "./control_surface";
|
|
6
8
|
|
|
7
9
|
export interface ChoiceOption {
|
|
8
10
|
label: string;
|
|
@@ -18,46 +20,55 @@ export interface ChoiceListProps {
|
|
|
18
20
|
onSelect: (value: string) => void;
|
|
19
21
|
}
|
|
20
22
|
|
|
23
|
+
/** One selectable option — a role-less-free `Pressable` (its own accessible name
|
|
24
|
+
* + selected state), hover wash + focus ring, no border. */
|
|
25
|
+
function ChoiceRow({ option, selected, onSelect }: { option: ChoiceOption; selected: boolean; onSelect: (value: string) => void }) {
|
|
26
|
+
const { focusVisible, focusProps } = useFocusRing();
|
|
27
|
+
return (
|
|
28
|
+
<Pressable
|
|
29
|
+
accessibilityRole="button"
|
|
30
|
+
accessibilityLabel={option.label}
|
|
31
|
+
accessibilityState={{ selected }}
|
|
32
|
+
onPress={() => onSelect(option.value)}
|
|
33
|
+
{...focusProps}
|
|
34
|
+
style={({ hovered, pressed }) => [
|
|
35
|
+
{ flexDirection: "row", alignItems: "center", gap: 12, paddingVertical: 14, paddingHorizontal: 6, borderRadius: 8 },
|
|
36
|
+
hovered || pressed ? { backgroundColor: colors.zinc[50] } : null,
|
|
37
|
+
focusVisible ? { boxShadow: FOCUS_RING } : null,
|
|
38
|
+
]}
|
|
39
|
+
>
|
|
40
|
+
<View style={{ flex: 1, gap: 3, minWidth: 0 }}>
|
|
41
|
+
<Text size="sm" weight={selected ? "semibold" : "medium"}>
|
|
42
|
+
{option.label}
|
|
43
|
+
</Text>
|
|
44
|
+
{option.description ? (
|
|
45
|
+
<Text size="xs" color="muted">
|
|
46
|
+
{option.description}
|
|
47
|
+
</Text>
|
|
48
|
+
) : null}
|
|
49
|
+
</View>
|
|
50
|
+
{selected ? <Icon name="check" size={17} color={colors.zinc[900]} /> : null}
|
|
51
|
+
</Pressable>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
21
55
|
/**
|
|
22
|
-
* A vertical set of selectable answer options —
|
|
23
|
-
* focus
|
|
24
|
-
* switchable (pick a different option any time). The chosen
|
|
25
|
-
* The agent's quick-reply surface (`Clarify` uses it) and any "pick one"
|
|
56
|
+
* A vertical set of selectable answer options — divider-separated rows (no
|
|
57
|
+
* bordered cards), each with its own focus ring + hover wash, single-select and
|
|
58
|
+
* freely switchable (pick a different option any time). The chosen row shows a
|
|
59
|
+
* check. The agent's quick-reply surface (`Clarify` uses it) and any "pick one"
|
|
26
60
|
* question.
|
|
27
61
|
*/
|
|
28
62
|
export function ChoiceList(props: ChoiceListProps) {
|
|
29
63
|
const { options, value, onSelect } = props;
|
|
30
64
|
return (
|
|
31
|
-
<View
|
|
32
|
-
{options.map((o) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
onPress={() => onSelect(o.value)}
|
|
39
|
-
accessibilityLabel={o.label}
|
|
40
|
-
style={styles.item}
|
|
41
|
-
>
|
|
42
|
-
<View style={styles.text}>
|
|
43
|
-
<Text size="sm" weight="medium">
|
|
44
|
-
{o.label}
|
|
45
|
-
</Text>
|
|
46
|
-
{o.description ? (
|
|
47
|
-
<Text size="xs" color="muted">
|
|
48
|
-
{o.description}
|
|
49
|
-
</Text>
|
|
50
|
-
) : null}
|
|
51
|
-
</View>
|
|
52
|
-
{selected ? <Icon name="check" size={16} color={colors.zinc[900]} /> : null}
|
|
53
|
-
</CardSelectItem>
|
|
54
|
-
);
|
|
55
|
-
})}
|
|
65
|
+
<View>
|
|
66
|
+
{options.map((o, i) => (
|
|
67
|
+
<View key={o.value}>
|
|
68
|
+
{i > 0 ? <Divider /> : null}
|
|
69
|
+
<ChoiceRow option={o} selected={value === o.value} onSelect={onSelect} />
|
|
70
|
+
</View>
|
|
71
|
+
))}
|
|
56
72
|
</View>
|
|
57
73
|
);
|
|
58
74
|
}
|
|
59
|
-
|
|
60
|
-
const styles = StyleSheet.create({
|
|
61
|
-
item: { flexDirection: "row", alignItems: "center", gap: 10, paddingVertical: 11, paddingHorizontal: 14 },
|
|
62
|
-
text: { flex: 1, gap: 2 },
|
|
63
|
-
});
|
package/src/clarify.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { colors } from "./colors";
|
|
1
|
+
import { View } from "react-native";
|
|
3
2
|
import { Text } from "./text";
|
|
4
3
|
import { ChoiceList, type ChoiceOption } from "./choice_list";
|
|
5
4
|
|
|
@@ -16,33 +15,24 @@ export interface ClarifyProps {
|
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
|
-
* The agent asks BACK — a question with selectable answer options
|
|
20
|
-
*
|
|
18
|
+
* The agent asks BACK — a question with selectable answer options the human picks
|
|
19
|
+
* before the run continues, freely switchable until committed. A borderless block
|
|
20
|
+
* (no card): the question, then divider-separated option rows (`ChoiceList`).
|
|
21
21
|
* Human-in-the-loop input: when the agent is unsure, it clarifies instead of
|
|
22
|
-
* guessing wrong.
|
|
23
|
-
* `AgentRun` / `AgentProgress`.
|
|
22
|
+
* guessing wrong. Pair with `AgentRun` / `AgentProgress`.
|
|
24
23
|
*/
|
|
25
24
|
export function Clarify(props: ClarifyProps) {
|
|
26
25
|
return (
|
|
27
|
-
<View style={
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
<View style={{ gap: 14 }}>
|
|
27
|
+
<View style={{ gap: 4 }}>
|
|
28
|
+
<Text size="xs" color="muted" weight="medium">
|
|
29
|
+
Question
|
|
30
|
+
</Text>
|
|
31
|
+
<Text size="sm" weight="medium">
|
|
32
|
+
{props.question}
|
|
33
|
+
</Text>
|
|
34
|
+
</View>
|
|
34
35
|
<ChoiceList options={props.options} value={props.answer} onSelect={props.onAnswer} />
|
|
35
36
|
</View>
|
|
36
37
|
);
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
const styles = StyleSheet.create({
|
|
40
|
-
card: {
|
|
41
|
-
borderWidth: 1,
|
|
42
|
-
borderColor: colors.border,
|
|
43
|
-
backgroundColor: colors.white,
|
|
44
|
-
borderRadius: 12,
|
|
45
|
-
padding: 16,
|
|
46
|
-
gap: 12,
|
|
47
|
-
},
|
|
48
|
-
});
|
package/src/remark_gfm_safe.ts
CHANGED
|
@@ -6,6 +6,29 @@ import { gfmTaskListItemFromMarkdown } from "mdast-util-gfm-task-list-item";
|
|
|
6
6
|
import { gfm } from "micromark-extension-gfm";
|
|
7
7
|
import type { Plugin } from "unified";
|
|
8
8
|
|
|
9
|
+
// A micromark syntax extension is exactly what `gfm()` produces; deriving the type
|
|
10
|
+
// from the imported value keeps this dependency-free (`micromark-util-types` is
|
|
11
|
+
// only a transitive dep) while staying the true type the registry holds.
|
|
12
|
+
type MicromarkExtension = ReturnType<typeof gfm>;
|
|
13
|
+
|
|
14
|
+
// `unified`'s `Data` interface ships bare (`{ settings? }`). `remark-parse` is what
|
|
15
|
+
// normally augments it with the two extension registries a `fromMarkdown` plugin
|
|
16
|
+
// writes into via `this.data()` — but this module composes GFM from its parts
|
|
17
|
+
// precisely so it never imports the `remark-gfm`/autolink-literal graph, and it
|
|
18
|
+
// doesn't import `remark-parse` either, so nothing else in a consumer's compile
|
|
19
|
+
// graph declares them. We restate the ecosystem's canonical augmentation here so
|
|
20
|
+
// the writes below type-check for every app that pulls this file in through
|
|
21
|
+
// `<Markdown>` (without it, `tsc` throws TS2339 on the whole app). Types mirror
|
|
22
|
+
// the consumers: `micromarkExtensions` holds micromark `Extension`s;
|
|
23
|
+
// `fromMarkdownExtensions` mirrors `mdast-util-from-markdown`'s `mdastExtensions`
|
|
24
|
+
// shape (`Extension | Extension[]`), which is what we push a nested list into below.
|
|
25
|
+
declare module "unified" {
|
|
26
|
+
interface Data {
|
|
27
|
+
micromarkExtensions?: MicromarkExtension[];
|
|
28
|
+
fromMarkdownExtensions?: Array<Extension | Extension[]>;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
9
32
|
/**
|
|
10
33
|
* `remark-gfm`, rebuilt so no regex lookbehind reaches the bundle.
|
|
11
34
|
*
|