@lotics/ui 5.7.0 → 5.9.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/AGENTS.md +102 -42
- package/examples/tpl_approvals.tsx +10 -10
- package/examples/tpl_convert.tsx +11 -23
- package/examples/tpl_crm_desk.tsx +3 -3
- package/examples/tpl_dieline.tsx +7 -6
- package/examples/tpl_directory.tsx +3 -3
- package/examples/tpl_dossier.tsx +7 -7
- package/examples/tpl_draft.tsx +4 -4
- package/examples/tpl_extract.tsx +7 -7
- package/examples/tpl_inventory.tsx +3 -3
- package/examples/tpl_lookup.tsx +4 -3
- package/examples/tpl_match.tsx +1 -1
- package/examples/tpl_order.tsx +1 -1
- package/examples/tpl_ratedesk.tsx +12 -12
- package/examples/tpl_record.tsx +1 -1
- package/examples/tpl_report.tsx +3 -3
- package/examples/tpl_stock.tsx +3 -3
- package/examples/tpl_triage.tsx +1 -1
- package/package.json +12 -4
- package/src/agent_progress.tsx +14 -12
- package/src/agent_run.tsx +253 -66
- package/src/back_button.tsx +3 -2
- package/src/badge.tsx +2 -1
- package/src/button.tsx +11 -32
- package/src/button_colors.ts +23 -0
- package/src/calendar/calendar_view.tsx +2 -2
- package/src/card_select_item.tsx +2 -1
- package/src/change_review.tsx +5 -6
- package/src/{pill_button.tsx → chip.tsx} +7 -7
- package/src/chip_group.tsx +2 -2
- package/src/column_filter.tsx +4 -4
- package/src/combobox.tsx +2 -9
- package/src/composer.tsx +4 -3
- package/src/control_surface.ts +15 -15
- package/src/date_field.tsx +2 -1
- package/src/date_filter.tsx +2 -1
- package/src/date_range_filter_field.tsx +2 -1
- package/src/dialog.tsx +2 -2
- package/src/discrepancy.tsx +1 -1
- package/src/drawer.tsx +1 -2
- package/src/file_gallery_modal.tsx +220 -133
- package/src/file_grid.tsx +184 -0
- package/src/file_preview.web.tsx +329 -6
- package/src/file_preview_types.ts +40 -0
- package/src/file_row.tsx +114 -0
- package/src/file_rows.tsx +105 -0
- package/src/file_thumbnail.tsx +121 -79
- package/src/file_thumbnail_grid.tsx +130 -55
- package/src/{filter_pill.tsx → filter_chip.tsx} +8 -8
- package/src/finding.tsx +1 -1
- package/src/gantt/gantt_view.tsx +2 -2
- package/src/icon_button.tsx +49 -14
- package/src/image_gallery.tsx +0 -4
- package/src/inline_edit.tsx +2 -2
- package/src/link_button.tsx +2 -1
- package/src/menu_button.tsx +2 -1
- package/src/menu_list_item.tsx +2 -1
- package/src/number_input.tsx +2 -1
- package/src/pdfjs_worker.d.ts +5 -0
- package/src/picker.tsx +3 -3
- package/src/popover_header.tsx +2 -2
- package/src/radio_picker.tsx +2 -1
- package/src/range_slider.tsx +1 -1
- package/src/review_card.tsx +2 -2
- package/src/scan_field.tsx +2 -1
- package/src/scored_option.tsx +0 -1
- package/src/search_input.tsx +3 -2
- package/src/segmented_control.tsx +2 -1
- package/src/status_badge.tsx +2 -1
- package/src/stepper.tsx +3 -2
- package/src/switch_button.tsx +2 -1
- package/src/switcher.tsx +3 -2
- package/src/tabs.tsx +2 -1
- package/src/tag_input.tsx +2 -1
- package/src/text_input_field.tsx +2 -1
- package/src/time_field.tsx +2 -1
- package/src/time_picker.tsx +2 -1
- package/src/triage_row.tsx +3 -3
- package/src/uploading_thumbnail.tsx +212 -0
- package/src/hover_action.tsx +0 -54
package/src/gantt/gantt_view.tsx
CHANGED
|
@@ -163,8 +163,8 @@ export function GanttView<T = unknown>(props: GanttViewProps<T>) {
|
|
|
163
163
|
const styles = StyleSheet.create({
|
|
164
164
|
root: { flex: 1, backgroundColor: colors.white },
|
|
165
165
|
toolbar: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 14, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.border },
|
|
166
|
-
zoomSwitch: { flexDirection: "row", backgroundColor: colors.zinc[100], borderRadius:
|
|
167
|
-
zoomBtn: { paddingHorizontal: 12, paddingVertical: 5, borderRadius:
|
|
166
|
+
zoomSwitch: { flexDirection: "row", backgroundColor: colors.zinc[100], borderRadius: 10, padding: 2 },
|
|
167
|
+
zoomBtn: { paddingHorizontal: 12, paddingVertical: 5, borderRadius: 8 },
|
|
168
168
|
zoomBtnActive: { backgroundColor: colors.white },
|
|
169
169
|
headerCell: { borderBottomWidth: 1, borderBottomColor: colors.border },
|
|
170
170
|
labelRow: { flexDirection: "row", alignItems: "center", gap: 8, paddingHorizontal: 12, borderBottomWidth: 1, borderBottomColor: colors.zinc[100] },
|
package/src/icon_button.tsx
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { GestureResponderEvent, StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
|
1
|
+
import { ActivityIndicator, GestureResponderEvent, StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
|
2
2
|
import { Icon, IconName } from "./icon";
|
|
3
3
|
import { colors } from "./colors";
|
|
4
4
|
import { PressableHighlight } from "./pressable_highlight";
|
|
5
|
+
import { type ButtonColor } from "./button";
|
|
6
|
+
import { getButtonIconColor } from "./button_colors";
|
|
5
7
|
import { Ref, useCallback } from "react";
|
|
6
8
|
import { TooltipSide } from "./tooltip";
|
|
7
9
|
|
|
@@ -9,16 +11,27 @@ interface IconButtonBase {
|
|
|
9
11
|
ref?: Ref<View>;
|
|
10
12
|
testID?: string;
|
|
11
13
|
icon: IconName;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
/** Matches `Button`'s palette so an icon-only action migrates 1:1 — a filled
|
|
15
|
+
* disc for primary/secondary/danger, a ghost for muted/danger-secondary/none. */
|
|
16
|
+
color?: ButtonColor | "none" | "white";
|
|
17
|
+
/** `lg` (40px, 20px glyph) for a circular primary action at the system control
|
|
18
|
+
* height — a composer send, a drawer/popover back or close; `md` (28px, 18px
|
|
19
|
+
* glyph) for toolbars; `sm` (24px, 14px glyph) for inline affordances next to
|
|
20
|
+
* body/sm text (e.g. the ⓘ in a CardHeader). md/sm keep a 40px touch target via
|
|
21
|
+
* hitSlop; `lg` is already 40. */
|
|
22
|
+
size?: "lg" | "md" | "sm";
|
|
17
23
|
iconColor?: string;
|
|
24
|
+
/** Floating variant: a white fill + hairline border + soft shadow, so the
|
|
25
|
+
* button reads as a distinct, tappable target sitting ON TOP of imagery or a
|
|
26
|
+
* colored surface (a tile's remove ✕, an overlay's retry). */
|
|
27
|
+
elevated?: boolean;
|
|
18
28
|
tooltipSide?: TooltipSide;
|
|
19
29
|
onPress?: (event: GestureResponderEvent) => void;
|
|
20
30
|
style?: StyleProp<ViewStyle>;
|
|
21
31
|
disabled?: boolean;
|
|
32
|
+
/** Show a spinner in place of the icon (and block press) — for an icon action
|
|
33
|
+
* that triggers async work, e.g. a delete. */
|
|
34
|
+
loading?: boolean;
|
|
22
35
|
}
|
|
23
36
|
|
|
24
37
|
/**
|
|
@@ -39,10 +52,12 @@ export function IconButton(props: IconButtonProps) {
|
|
|
39
52
|
onPress,
|
|
40
53
|
color = "none",
|
|
41
54
|
size = "md",
|
|
55
|
+
elevated,
|
|
42
56
|
tooltip,
|
|
43
57
|
tooltipSide,
|
|
44
58
|
accessibilityLabel,
|
|
45
59
|
disabled,
|
|
60
|
+
loading,
|
|
46
61
|
style,
|
|
47
62
|
} = props;
|
|
48
63
|
|
|
@@ -53,6 +68,11 @@ export function IconButton(props: IconButtonProps) {
|
|
|
53
68
|
[onPress],
|
|
54
69
|
);
|
|
55
70
|
|
|
71
|
+
const disabledOrLoading = disabled || loading;
|
|
72
|
+
const tint =
|
|
73
|
+
iconColor ??
|
|
74
|
+
(color === "none" ? colors.zinc[700] : color === "white" ? colors.white : getButtonIconColor(color));
|
|
75
|
+
|
|
56
76
|
return (
|
|
57
77
|
<PressableHighlight
|
|
58
78
|
ref={ref}
|
|
@@ -61,18 +81,18 @@ export function IconButton(props: IconButtonProps) {
|
|
|
61
81
|
tooltipSide={tooltipSide}
|
|
62
82
|
accessibilityRole="button"
|
|
63
83
|
accessibilityLabel={accessibilityLabel ?? tooltip}
|
|
64
|
-
style={[styles.button, styles[size], styles[color],
|
|
84
|
+
style={[styles.button, styles[size], styles[color], elevated && styles.elevated, disabledOrLoading && styles.disabled, style]}
|
|
65
85
|
onPress={handlePress}
|
|
66
|
-
disabled={
|
|
86
|
+
disabled={disabledOrLoading}
|
|
67
87
|
// 40px touch target regardless of visual size (28 + 2×6 / 24 + 2×8)
|
|
68
88
|
// without shifting surrounding layouts.
|
|
69
|
-
hitSlop={size === "sm" ? 8 : 6}
|
|
89
|
+
hitSlop={size === "lg" ? 0 : size === "sm" ? 8 : 6}
|
|
70
90
|
>
|
|
71
|
-
|
|
72
|
-
size=
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
{loading ? (
|
|
92
|
+
<ActivityIndicator size="small" color={tint} />
|
|
93
|
+
) : (
|
|
94
|
+
<Icon size={size === "sm" ? 14 : size === "lg" ? 20 : 18} name={icon} color={tint} />
|
|
95
|
+
)}
|
|
76
96
|
</PressableHighlight>
|
|
77
97
|
);
|
|
78
98
|
}
|
|
@@ -85,6 +105,10 @@ const styles = StyleSheet.create({
|
|
|
85
105
|
justifyContent: "center",
|
|
86
106
|
borderRadius: 999,
|
|
87
107
|
},
|
|
108
|
+
lg: {
|
|
109
|
+
width: 40,
|
|
110
|
+
height: 40,
|
|
111
|
+
},
|
|
88
112
|
md: {
|
|
89
113
|
width: 28,
|
|
90
114
|
height: 28,
|
|
@@ -103,5 +127,16 @@ const styles = StyleSheet.create({
|
|
|
103
127
|
secondary: {
|
|
104
128
|
backgroundColor: colors.zinc[100],
|
|
105
129
|
},
|
|
130
|
+
danger: {
|
|
131
|
+
backgroundColor: colors.red[100],
|
|
132
|
+
},
|
|
133
|
+
muted: {},
|
|
134
|
+
"danger-secondary": {},
|
|
106
135
|
white: {},
|
|
136
|
+
elevated: {
|
|
137
|
+
backgroundColor: colors.white,
|
|
138
|
+
borderWidth: 1,
|
|
139
|
+
borderColor: colors.zinc[200],
|
|
140
|
+
...({ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.18)" } as object),
|
|
141
|
+
},
|
|
107
142
|
});
|
package/src/image_gallery.tsx
CHANGED
|
@@ -36,8 +36,6 @@ export interface ImageGalleryProps {
|
|
|
36
36
|
emptyText?: string;
|
|
37
37
|
/** Optional max width. Omit to fill the container. */
|
|
38
38
|
maxWidth?: number;
|
|
39
|
-
/** Hint shown in the full-screen zoom modal. Pass a translated string. */
|
|
40
|
-
captionHint?: string;
|
|
41
39
|
/** "bottom" stacks thumbnails under the main image; "right" puts the main
|
|
42
40
|
* image (~60% of the width) and the thumbnail grid side by side. */
|
|
43
41
|
thumbnailPosition?: "bottom" | "right";
|
|
@@ -55,7 +53,6 @@ export function ImageGallery({
|
|
|
55
53
|
loading = false,
|
|
56
54
|
emptyText = "No images.",
|
|
57
55
|
maxWidth,
|
|
58
|
-
captionHint = "ESC to close · ←/→ to navigate",
|
|
59
56
|
thumbnailPosition = "bottom",
|
|
60
57
|
mainAspectRatio = 4 / 3,
|
|
61
58
|
mainFraction = 0.6,
|
|
@@ -157,7 +154,6 @@ export function ImageGallery({
|
|
|
157
154
|
files={images}
|
|
158
155
|
activeIndex={zoomIdx}
|
|
159
156
|
onIndexChange={setZoomIdx}
|
|
160
|
-
captionHint={captionHint}
|
|
161
157
|
rotation={rotation}
|
|
162
158
|
rotatable={rotatable}
|
|
163
159
|
/>
|
package/src/inline_edit.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { IconButton } from "./icon_button";
|
|
|
5
5
|
import { ActivityIndicator } from "./activity_indicator";
|
|
6
6
|
import { PressableHighlight } from "./pressable_highlight";
|
|
7
7
|
import { colors } from "./colors";
|
|
8
|
-
import { ACTIVE_RING } from "./control_surface";
|
|
8
|
+
import { ACTIVE_RING, CONTROL_RADIUS } from "./control_surface";
|
|
9
9
|
import { fontFamilyRegular, getInputTextStyle } from "./text_utils";
|
|
10
10
|
|
|
11
11
|
/** The kit's standard control height (TextInputField, NumberInput, Picker, …).
|
|
@@ -221,7 +221,7 @@ const viewTextStyle = [getInputTextStyle(), { flex: 1, fontFamily: fontFamilyReg
|
|
|
221
221
|
const styles = StyleSheet.create({
|
|
222
222
|
view: {
|
|
223
223
|
minHeight: INLINE_CONTROL_HEIGHT,
|
|
224
|
-
borderRadius:
|
|
224
|
+
borderRadius: CONTROL_RADIUS,
|
|
225
225
|
borderWidth: 1,
|
|
226
226
|
borderColor: "transparent",
|
|
227
227
|
paddingHorizontal: 8,
|
package/src/link_button.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from "react-native";
|
|
2
2
|
import { Text } from "./text";
|
|
3
3
|
import { PressableHighlight } from "./pressable_highlight";
|
|
4
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
4
5
|
|
|
5
6
|
export interface LinkButtonProps {
|
|
6
7
|
title: string;
|
|
@@ -44,7 +45,7 @@ const styles = StyleSheet.create({
|
|
|
44
45
|
paddingVertical: 6,
|
|
45
46
|
paddingHorizontal: 8,
|
|
46
47
|
marginHorizontal: -8,
|
|
47
|
-
borderRadius:
|
|
48
|
+
borderRadius: CONTROL_RADIUS,
|
|
48
49
|
alignSelf: "flex-start",
|
|
49
50
|
},
|
|
50
51
|
});
|
package/src/menu_button.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { Ref } from "react";
|
|
|
2
2
|
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
3
|
import { Text } from "./text";
|
|
4
4
|
import { colors } from "./colors";
|
|
5
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
5
6
|
import { Icon, IconName } from "./icon";
|
|
6
7
|
import { PressableHighlight } from "./pressable_highlight";
|
|
7
8
|
export interface MenuButtonProps {
|
|
@@ -126,7 +127,7 @@ const styles = StyleSheet.create({
|
|
|
126
127
|
gap: 8,
|
|
127
128
|
height: 40,
|
|
128
129
|
paddingHorizontal: 8,
|
|
129
|
-
borderRadius:
|
|
130
|
+
borderRadius: CONTROL_RADIUS,
|
|
130
131
|
},
|
|
131
132
|
textContainer: {
|
|
132
133
|
flex: 1,
|
package/src/menu_list_item.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { Ref } from "react";
|
|
|
2
2
|
import { StyleProp, StyleSheet, View, ViewStyle } from "react-native";
|
|
3
3
|
import { Text } from "./text";
|
|
4
4
|
import { colors } from "./colors";
|
|
5
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
5
6
|
import { Icon, IconName } from "./icon";
|
|
6
7
|
import { PressableHighlight } from "./pressable_highlight";
|
|
7
8
|
import type { TextColor } from "./text_utils";
|
|
@@ -111,7 +112,7 @@ const styles = StyleSheet.create({
|
|
|
111
112
|
gap: 8,
|
|
112
113
|
paddingHorizontal: 8,
|
|
113
114
|
paddingVertical: 8,
|
|
114
|
-
borderRadius:
|
|
115
|
+
borderRadius: CONTROL_RADIUS,
|
|
115
116
|
},
|
|
116
117
|
textContainer: {
|
|
117
118
|
flex: 1,
|
package/src/number_input.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { KeyboardEvent } from "react";
|
|
2
2
|
import { colors } from "./colors";
|
|
3
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
3
4
|
import { fontFamilyRegular, inputTextStyleWeb } from "./text_utils";
|
|
4
5
|
import { useFormField } from "./form_field";
|
|
5
6
|
|
|
@@ -50,7 +51,7 @@ export function NumberInput(props: NumberInputProps) {
|
|
|
50
51
|
height: 40,
|
|
51
52
|
paddingLeft: 8,
|
|
52
53
|
paddingRight: 8,
|
|
53
|
-
borderRadius:
|
|
54
|
+
borderRadius: CONTROL_RADIUS,
|
|
54
55
|
borderWidth: 1,
|
|
55
56
|
borderStyle: "solid",
|
|
56
57
|
borderColor: colors.border,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The pdf.js worker entry is imported only for its side effect: it assigns
|
|
2
|
+
// `globalThis.pdfjsWorker`, which lets pdf.js run on the main thread (no Web
|
|
3
|
+
// Worker, no worker-URL resolution) — portable across Vite (apps) and Metro
|
|
4
|
+
// (frontend). The file ships no types; declare it as a side-effect module.
|
|
5
|
+
declare module "pdfjs-dist/build/pdf.worker.min.mjs";
|
package/src/picker.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { Picker as RNPicker } from "@react-native-picker/picker";
|
|
|
2
2
|
import { StyleSheet, View, Pressable, StyleProp, ViewStyle, TextStyle } from "react-native";
|
|
3
3
|
import { useState, useCallback, useMemo, useEffect, useRef } from "react";
|
|
4
4
|
import { colors } from "./colors";
|
|
5
|
-
import { ACTIVE_RING } from "./control_surface";
|
|
5
|
+
import { ACTIVE_RING, CONTROL_RADIUS } from "./control_surface";
|
|
6
6
|
import { Text } from "./text";
|
|
7
7
|
import { fontFamilyRegular, getInputTextStyle } from "./text_utils";
|
|
8
8
|
import { Icon } from "./icon";
|
|
@@ -310,7 +310,7 @@ const styles = StyleSheet.create({
|
|
|
310
310
|
height: 40,
|
|
311
311
|
paddingHorizontal: 6,
|
|
312
312
|
paddingRight: 28,
|
|
313
|
-
borderRadius:
|
|
313
|
+
borderRadius: CONTROL_RADIUS,
|
|
314
314
|
borderWidth: 1,
|
|
315
315
|
borderColor: colors.border,
|
|
316
316
|
fontFamily: fontFamilyRegular,
|
|
@@ -324,7 +324,7 @@ const styles = StyleSheet.create({
|
|
|
324
324
|
paddingHorizontal: 6,
|
|
325
325
|
borderWidth: 1,
|
|
326
326
|
borderColor: colors.border,
|
|
327
|
-
borderRadius:
|
|
327
|
+
borderRadius: CONTROL_RADIUS,
|
|
328
328
|
cursor: "auto",
|
|
329
329
|
height: 40,
|
|
330
330
|
},
|
package/src/popover_header.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { View, StyleSheet } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { IconButton } from "./icon_button";
|
|
4
4
|
import { Text } from "./text";
|
|
5
5
|
import { usePopoverNav } from "./popover_nav";
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@ export function PopoverHeader(props: PopoverHeaderProps) {
|
|
|
18
18
|
return (
|
|
19
19
|
<View style={styles.container}>
|
|
20
20
|
{canGoBack && (
|
|
21
|
-
<
|
|
21
|
+
<IconButton icon="chevron-left" size="lg" color="secondary" accessibilityLabel={backLabel} onPress={goBack} />
|
|
22
22
|
)}
|
|
23
23
|
<Text size="sm" weight="medium" style={{ flex: 1 }}>
|
|
24
24
|
{title}
|
package/src/radio_picker.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useRef } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { colors } from "./colors";
|
|
4
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
4
5
|
import { Text } from "./text";
|
|
5
6
|
import { PressableHighlight } from "./pressable_highlight";
|
|
6
7
|
import { Icon } from "./icon";
|
|
@@ -120,7 +121,7 @@ function RadioOption<T extends string | number | symbol>(
|
|
|
120
121
|
flexDirection: "row",
|
|
121
122
|
alignItems: "center",
|
|
122
123
|
padding: compact ? 8 : 12,
|
|
123
|
-
borderRadius:
|
|
124
|
+
borderRadius: CONTROL_RADIUS,
|
|
124
125
|
gap: compact ? 8 : 16,
|
|
125
126
|
}}
|
|
126
127
|
onPress={handlePress}
|
package/src/range_slider.tsx
CHANGED
|
@@ -24,7 +24,7 @@ export interface RangeSliderProps {
|
|
|
24
24
|
type Thumb = "low" | "high";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* A short human summary of a range selection for a `
|
|
27
|
+
* A short human summary of a range selection for a `FilterChip` preview —
|
|
28
28
|
* "5tr–10tr", or "≥ 5tr" / "≤ 10tr" when one end sits at its bound, and
|
|
29
29
|
* `undefined` at the full range (no active filter). Mirrors `columnFilterSummary`.
|
|
30
30
|
*/
|
package/src/review_card.tsx
CHANGED
|
@@ -79,7 +79,7 @@ export function ReviewCard(props: ReviewCardProps) {
|
|
|
79
79
|
<Text size="sm" weight="medium" color="muted" numberOfLines={1}>
|
|
80
80
|
{accepted ? props.acceptedLabel ?? "Accepted" : props.dismissedLabel ?? "Dismissed"}
|
|
81
81
|
</Text>
|
|
82
|
-
{props.onUndo ? <Button title="Undo" color="muted"
|
|
82
|
+
{props.onUndo ? <Button title="Undo" color="muted" onPress={props.onUndo} /> : null}
|
|
83
83
|
</View>
|
|
84
84
|
);
|
|
85
85
|
}
|
|
@@ -132,7 +132,7 @@ export function ReviewCard(props: ReviewCardProps) {
|
|
|
132
132
|
<View style={styles.footer}>
|
|
133
133
|
{actions.map((a, i) => {
|
|
134
134
|
const kind = a.kind ?? (i === actions.length - 1 ? "primary" : "muted");
|
|
135
|
-
return <Button key={a.label} title={a.label} color={kind}
|
|
135
|
+
return <Button key={a.label} title={a.label} color={kind} onPress={a.onPress} />;
|
|
136
136
|
})}
|
|
137
137
|
</View>
|
|
138
138
|
) : null}
|
package/src/scan_field.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StyleSheet, View } from "react-native";
|
|
2
2
|
import { colors, solid } from "./colors";
|
|
3
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
3
4
|
import { Text } from "./text";
|
|
4
5
|
import { TextInputField } from "./text_input_field";
|
|
5
6
|
|
|
@@ -52,7 +53,7 @@ export function ScanField(props: ScanFieldProps) {
|
|
|
52
53
|
|
|
53
54
|
const styles = StyleSheet.create({
|
|
54
55
|
field: {
|
|
55
|
-
borderRadius:
|
|
56
|
+
borderRadius: CONTROL_RADIUS,
|
|
56
57
|
backgroundColor: colors.white,
|
|
57
58
|
},
|
|
58
59
|
});
|
package/src/scored_option.tsx
CHANGED
package/src/search_input.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type ViewStyle,
|
|
10
10
|
} from "react-native";
|
|
11
11
|
import { colors } from "./colors";
|
|
12
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
12
13
|
import { TextInputField } from "./text_input_field";
|
|
13
14
|
|
|
14
15
|
type SearchInputProps = Omit<
|
|
@@ -57,7 +58,7 @@ export function SearchInput(props: SearchInputProps) {
|
|
|
57
58
|
|
|
58
59
|
const styles = StyleSheet.create({
|
|
59
60
|
// Search reads as a view-control by its leading search glyph + white fill —
|
|
60
|
-
// NOT by a distinct shape. It shares the
|
|
61
|
+
// NOT by a distinct shape. It shares the kit-wide `CONTROL_RADIUS` of every other
|
|
61
62
|
// input/picker (TextInputField, Combobox, the date filter), so a toolbar of
|
|
62
63
|
// controls reads as one consistent band. The white fill still pops against
|
|
63
64
|
// the zinc-50 canvas where most toolbars live; a zinc-300 border (one step up
|
|
@@ -65,7 +66,7 @@ const styles = StyleSheet.create({
|
|
|
65
66
|
// the fill alone would vanish. 40px (TextInputField default) — the system
|
|
66
67
|
// control height every band aligns to.
|
|
67
68
|
search: {
|
|
68
|
-
borderRadius:
|
|
69
|
+
borderRadius: CONTROL_RADIUS,
|
|
69
70
|
backgroundColor: colors.white,
|
|
70
71
|
// A thin 1px resting border (TextInputField's default width) — interaction
|
|
71
72
|
// emphasis comes from the input's own focus outline, so it stays quiet at
|
|
@@ -3,6 +3,7 @@ import { StyleSheet, View, type StyleProp, type ViewStyle } from "react-native";
|
|
|
3
3
|
import { PressableHighlight } from "./pressable_highlight";
|
|
4
4
|
import { Text } from "./text";
|
|
5
5
|
import { colors, withAlpha } from "./colors";
|
|
6
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
6
7
|
|
|
7
8
|
export interface SegmentOption<T extends string> {
|
|
8
9
|
label: string;
|
|
@@ -183,7 +184,7 @@ const styles = StyleSheet.create({
|
|
|
183
184
|
height: 40,
|
|
184
185
|
gap: 2,
|
|
185
186
|
padding: 3,
|
|
186
|
-
borderRadius:
|
|
187
|
+
borderRadius: CONTROL_RADIUS,
|
|
187
188
|
backgroundColor: colors.zinc["100"],
|
|
188
189
|
},
|
|
189
190
|
trackDisabled: {
|
package/src/status_badge.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import { useEffect, useRef } from "react";
|
|
|
2
2
|
import { View, StyleSheet, Animated, Easing } from "react-native";
|
|
3
3
|
import { Text } from "./text";
|
|
4
4
|
import { colors } from "./colors";
|
|
5
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
5
6
|
|
|
6
7
|
interface StatusBadgeProps {
|
|
7
8
|
enabled: boolean;
|
|
@@ -69,7 +70,7 @@ const styles = StyleSheet.create({
|
|
|
69
70
|
gap: 8,
|
|
70
71
|
paddingVertical: 4,
|
|
71
72
|
paddingHorizontal: 8,
|
|
72
|
-
borderRadius:
|
|
73
|
+
borderRadius: CONTROL_RADIUS,
|
|
73
74
|
},
|
|
74
75
|
dotWrapper: {
|
|
75
76
|
width: 10,
|
package/src/stepper.tsx
CHANGED
|
@@ -155,8 +155,9 @@ export function Step(props: StepProps) {
|
|
|
155
155
|
|
|
156
156
|
// The node — status drives fill, never size. Monochrome: reached fills with ink,
|
|
157
157
|
// the current step is a ring around white (pulsing when live), what's ahead is a
|
|
158
|
-
// faint grey ring, the terminal is a checked fill.
|
|
159
|
-
|
|
158
|
+
// faint grey ring, the terminal is a checked fill. Exported so `AgentRun` reuses
|
|
159
|
+
// the exact same dot in its flat activity rows.
|
|
160
|
+
export function Marker({ status, color, live }: { status: StepStatus; color: string; live: boolean }) {
|
|
160
161
|
if (status === "done") {
|
|
161
162
|
// A passed step: filled in the accent ink with a white check.
|
|
162
163
|
return (
|
package/src/switch_button.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { Text } from "./text";
|
|
|
3
3
|
import { Switch, type SwitchProps } from "./switch";
|
|
4
4
|
import { PressableHighlight } from "./pressable_highlight";
|
|
5
5
|
import { Icon, type IconName } from "./icon";
|
|
6
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
6
7
|
|
|
7
8
|
export interface SwitchButtonProps extends SwitchProps {
|
|
8
9
|
icon?: IconName;
|
|
@@ -22,7 +23,7 @@ export function SwitchButton(props: SwitchButtonProps) {
|
|
|
22
23
|
paddingVertical: 4,
|
|
23
24
|
paddingLeft: 8,
|
|
24
25
|
paddingRight: 6,
|
|
25
|
-
borderRadius:
|
|
26
|
+
borderRadius: CONTROL_RADIUS,
|
|
26
27
|
}}
|
|
27
28
|
onPress={() => onChange?.(!value)}
|
|
28
29
|
tooltip={tooltip}
|
package/src/switcher.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
|
|
7
7
|
import { Stack } from "./stack";
|
|
8
8
|
import { Text } from "./text";
|
|
9
9
|
import { colors } from "./colors";
|
|
10
|
+
import { CONTROL_HEIGHT, CONTROL_RADIUS } from "./control_surface";
|
|
10
11
|
|
|
11
12
|
export interface SwitcherItem {
|
|
12
13
|
id: string;
|
|
@@ -100,9 +101,9 @@ const styles = StyleSheet.create({
|
|
|
100
101
|
flexDirection: "row",
|
|
101
102
|
alignItems: "center",
|
|
102
103
|
gap: 6,
|
|
104
|
+
height: CONTROL_HEIGHT,
|
|
103
105
|
paddingHorizontal: 10,
|
|
104
|
-
|
|
105
|
-
borderRadius: 8,
|
|
106
|
+
borderRadius: CONTROL_RADIUS,
|
|
106
107
|
},
|
|
107
108
|
popoverBody: {
|
|
108
109
|
minWidth: 220,
|
package/src/tabs.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { View } from "react-native";
|
|
|
3
3
|
import { PressableHighlight } from "./pressable_highlight";
|
|
4
4
|
import { Text } from "./text";
|
|
5
5
|
import { colors } from "./colors";
|
|
6
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
6
7
|
|
|
7
8
|
export interface TabOption<T extends string> {
|
|
8
9
|
label: string;
|
|
@@ -138,7 +139,7 @@ function TabButton<T extends string>(props: TabButtonProps<T>) {
|
|
|
138
139
|
style={{
|
|
139
140
|
paddingVertical: 8,
|
|
140
141
|
paddingHorizontal: 16,
|
|
141
|
-
borderRadius:
|
|
142
|
+
borderRadius: CONTROL_RADIUS,
|
|
142
143
|
backgroundColor: pressed
|
|
143
144
|
? colors.zinc["100"]
|
|
144
145
|
: hovered
|
package/src/tag_input.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Pressable, ScrollView, StyleSheet, View, type StyleProp, type ViewStyle } from "react-native";
|
|
3
3
|
import { colors } from "./colors";
|
|
4
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
4
5
|
import { Text } from "./text";
|
|
5
6
|
import { Icon } from "./icon";
|
|
6
7
|
import { TextInputField } from "./text_input_field";
|
|
@@ -161,7 +162,7 @@ const styles = StyleSheet.create({
|
|
|
161
162
|
paddingVertical: 5,
|
|
162
163
|
borderWidth: 1,
|
|
163
164
|
borderColor: colors.border,
|
|
164
|
-
borderRadius:
|
|
165
|
+
borderRadius: CONTROL_RADIUS,
|
|
165
166
|
backgroundColor: colors.background,
|
|
166
167
|
},
|
|
167
168
|
chip: {
|
package/src/text_input_field.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
View,
|
|
6
6
|
} from "react-native";
|
|
7
7
|
import { colors } from "./colors";
|
|
8
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
8
9
|
import { Ref, useCallback } from "react";
|
|
9
10
|
import { Icon, IconName } from "./icon";
|
|
10
11
|
import { IconButton } from "./icon_button";
|
|
@@ -163,7 +164,7 @@ export function TextInputField(props: TextInputFieldProps) {
|
|
|
163
164
|
|
|
164
165
|
const styles = StyleSheet.create({
|
|
165
166
|
input: {
|
|
166
|
-
borderRadius:
|
|
167
|
+
borderRadius: CONTROL_RADIUS,
|
|
167
168
|
borderWidth: 1,
|
|
168
169
|
borderColor: colors.border,
|
|
169
170
|
height: 40,
|
package/src/time_field.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { Pressable, ScrollView, StyleSheet, View } from "react-native";
|
|
3
3
|
import { colors } from "./colors";
|
|
4
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
4
5
|
import { Text } from "./text";
|
|
5
6
|
import { Icon } from "./icon";
|
|
6
7
|
import { Popover, PopoverContent } from "./popover";
|
|
@@ -266,7 +267,7 @@ const styles = StyleSheet.create({
|
|
|
266
267
|
height: 40,
|
|
267
268
|
paddingHorizontal: 8,
|
|
268
269
|
gap: 2,
|
|
269
|
-
borderRadius:
|
|
270
|
+
borderRadius: CONTROL_RADIUS,
|
|
270
271
|
borderWidth: 1,
|
|
271
272
|
borderColor: colors.border,
|
|
272
273
|
backgroundColor: colors.background,
|
package/src/time_picker.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { KeyboardEvent } from "react";
|
|
2
2
|
import { colors } from "@lotics/ui/colors";
|
|
3
3
|
import { fontFamilyRegular, inputTextStyleWeb } from "@lotics/ui/text_utils";
|
|
4
|
+
import { CONTROL_RADIUS } from "./control_surface";
|
|
4
5
|
export interface TimePickerProps {
|
|
5
6
|
value?: string;
|
|
6
7
|
onValueChange: (value: string) => void;
|
|
@@ -31,7 +32,7 @@ export function TimePicker(props: TimePickerProps) {
|
|
|
31
32
|
height: 40,
|
|
32
33
|
paddingLeft: 8,
|
|
33
34
|
paddingRight: 8,
|
|
34
|
-
borderRadius:
|
|
35
|
+
borderRadius: CONTROL_RADIUS,
|
|
35
36
|
borderWidth: 1,
|
|
36
37
|
borderStyle: "solid",
|
|
37
38
|
borderColor: colors.border,
|
package/src/triage_row.tsx
CHANGED
|
@@ -74,9 +74,9 @@ export function TriageRow(props: TriageRowProps) {
|
|
|
74
74
|
</Text>
|
|
75
75
|
) : (
|
|
76
76
|
<View style={styles.footer}>
|
|
77
|
-
{props.onOverride ? <Button title="Reclassify" color="muted"
|
|
78
|
-
{props.onDismiss ? <Button title="Dismiss" color="muted"
|
|
79
|
-
{props.onAccept ? <Button title="Accept" color="primary"
|
|
77
|
+
{props.onOverride ? <Button title="Reclassify" color="muted" onPress={props.onOverride} /> : null}
|
|
78
|
+
{props.onDismiss ? <Button title="Dismiss" color="muted" onPress={props.onDismiss} /> : null}
|
|
79
|
+
{props.onAccept ? <Button title="Accept" color="primary" onPress={props.onAccept} /> : null}
|
|
80
80
|
</View>
|
|
81
81
|
)}
|
|
82
82
|
</View>
|