@xpufx/paseo-top 0.4.4 → 0.4.5
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/OVERVIEW.md +17 -0
- package/client/host-ui.tsx +184 -0
- package/client/multi-host-view.tsx +57 -43
- package/client/multi-host.ts +36 -13
- package/client/pill-labels.ts +94 -1
- package/client/pill.tsx +690 -614
- package/client/resources-query.ts +1 -1
- package/client/settings-events.ts +1 -1
- package/client/settings-ui.tsx +86 -9
- package/client/surface.tsx +308 -276
- package/client/telemetry-copy.ts +8 -2
- package/client/telemetry.tsx +372 -321
- package/client/turn-panel.tsx +126 -104
- package/client/vendor/paseo-plugin-helper/{host.ts → core/host.ts} +9 -3
- package/client/vendor/paseo-plugin-helper/core/index.ts +76 -0
- package/client/vendor/paseo-plugin-helper/core/plugin-load-count.ts +89 -0
- package/client/vendor/paseo-plugin-helper/{query-refresh.ts → core/query-refresh.ts} +2 -2
- package/client/vendor/paseo-plugin-helper/{query.ts → core/query.ts} +2 -2
- package/client/vendor/paseo-plugin-helper/{settings.ts → core/settings.ts} +1 -1
- package/client/vendor/paseo-plugin-helper/{shared-settings.ts → core/shared-settings.ts} +2 -2
- package/client/vendor/paseo-plugin-helper/{utils → lifecycle}/clipboard.ts +2 -2
- package/client/vendor/paseo-plugin-helper/lifecycle/flair.ts +26 -0
- package/client/vendor/paseo-plugin-helper/{theme/color-utils.ts → lifecycle/host-color.ts} +95 -38
- package/client/vendor/paseo-plugin-helper/lifecycle/host-theme.tsx +109 -0
- package/client/vendor/paseo-plugin-helper/lifecycle/index.ts +23 -0
- package/client/vendor/paseo-plugin-helper/lifecycle/multi-host.ts +66 -0
- package/client/vendor/paseo-plugin-helper/{panel.tsx → lifecycle/panel.tsx} +7 -7
- package/client/vendor/paseo-plugin-helper/{pill.tsx → lifecycle/pill.tsx} +51 -18
- package/client/vendor/paseo-plugin-helper/lifecycle/providers.tsx +46 -0
- package/client/vendor/paseo-plugin-helper/lifecycle/scroll-owner.ts +26 -0
- package/client/vendor/paseo-plugin-helper/{surface.tsx → lifecycle/surface.tsx} +6 -6
- package/client/vendor/paseo-plugin-helper/ui/color.ts +1 -0
- package/client/vendor/paseo-plugin-helper/ui/content.tsx +1326 -0
- package/client/vendor/paseo-plugin-helper/ui/controls.tsx +1018 -0
- package/client/vendor/paseo-plugin-helper/{components/DataTable.tsx → ui/data.tsx} +50 -58
- package/client/vendor/paseo-plugin-helper/ui/index.ts +44 -0
- package/client/vendor/paseo-plugin-helper/ui/layout.tsx +263 -0
- package/client/vendor/paseo-plugin-helper/ui/modal.tsx +111 -0
- package/client/vendor/paseo-plugin-helper/ui/plugin-reload-banner.tsx +119 -0
- package/client/vendor/paseo-plugin-helper/{settings-screen.tsx → ui/settings-screen.tsx} +3 -3
- package/client/vendor/paseo-plugin-helper/ui/settings.ts +36 -0
- package/client/vendor/paseo-plugin-helper/ui/text.tsx +821 -0
- package/client/vendor/paseo-plugin-helper/ui/theme.tsx +1 -0
- package/client/vendor/permission-audit/client.tsx +706 -0
- package/client/vendor/permission-audit/index.tsx +1 -0
- package/index.client.tsx +58 -37
- package/index.server.ts +256 -234
- package/package.json +7 -4
- package/paseo-plugin.json +2 -0
- package/screenshots/1-paseo-top-modal-system.jpg +0 -0
- package/screenshots/2-paseo-top-modal-workspace.jpg +0 -0
- package/screenshots/3-paseo-top-modal-settings.jpg +0 -0
- package/screenshots/4-paseo-top-modal-about.jpg +0 -0
- package/screenshots/paseo-top-dashboard.jpg +0 -0
- package/screenshots/paseo-top-general-view.jpg +0 -0
- package/server/resources.ts +98 -0
- package/server/vendor/paseo-plugin-helper/custom-pills.ts +70 -0
- package/server/vendor/paseo-plugin-helper/index.ts +2 -0
- package/server/vendor/paseo-plugin-helper/logger.ts +5 -16
- package/server/vendor/paseo-plugin-helper/rpc-guard.ts +2 -2
- package/server/vendor/paseo-plugin-helper/storage-guard.ts +294 -0
- package/server/vendor/paseo-plugin-helper/storage.ts +36 -2
- package/server/vendor/paseo-plugin-helper/telemetry.ts +486 -0
- package/server/vendor/paseo-plugin-helper/tickets.ts +18 -67
- package/server/vendor/permission-audit/index.ts +1 -0
- package/server/vendor/permission-audit/server.ts +839 -0
- package/shared/helper-version.ts +1 -1
- package/shared/multi-host.ts +153 -159
- package/shared/resources.ts +145 -0
- package/shared/vendor/paseo-plugin-helper/async.ts +14 -7
- package/shared/vendor/paseo-plugin-helper/features.ts +244 -0
- package/shared/vendor/paseo-plugin-helper/forge.ts +27 -0
- package/shared/vendor/paseo-plugin-helper/index.ts +1 -0
- package/shared/vendor/paseo-plugin-helper/tickets.ts +122 -28
- package/shared/vendor/permission-audit/filter.ts +61 -0
- package/shared/vendor/permission-audit/index.ts +2 -0
- package/shared/vendor/permission-audit/shared.ts +119 -0
- package/shared/version.ts +1 -1
- package/client/vendor/paseo-plugin-helper/components/AboutSection.tsx +0 -493
- package/client/vendor/paseo-plugin-helper/components/AttentionBeacon.tsx +0 -250
- package/client/vendor/paseo-plugin-helper/components/Badge.tsx +0 -168
- package/client/vendor/paseo-plugin-helper/components/Button.tsx +0 -204
- package/client/vendor/paseo-plugin-helper/components/Card.tsx +0 -257
- package/client/vendor/paseo-plugin-helper/components/CodeBlock.tsx +0 -196
- package/client/vendor/paseo-plugin-helper/components/Collapsible.tsx +0 -277
- package/client/vendor/paseo-plugin-helper/components/CommandBox.tsx +0 -172
- package/client/vendor/paseo-plugin-helper/components/CopyButton.tsx +0 -180
- package/client/vendor/paseo-plugin-helper/components/EmptyState.tsx +0 -97
- package/client/vendor/paseo-plugin-helper/components/HighlightedText.tsx +0 -70
- package/client/vendor/paseo-plugin-helper/components/InlineButton.tsx +0 -88
- package/client/vendor/paseo-plugin-helper/components/InteractiveRow.tsx +0 -142
- package/client/vendor/paseo-plugin-helper/components/KeyValue.tsx +0 -446
- package/client/vendor/paseo-plugin-helper/components/MetricGauge.tsx +0 -247
- package/client/vendor/paseo-plugin-helper/components/ProgressBar.tsx +0 -117
- package/client/vendor/paseo-plugin-helper/components/Responsive.tsx +0 -53
- package/client/vendor/paseo-plugin-helper/components/SearchInput.tsx +0 -132
- package/client/vendor/paseo-plugin-helper/components/SectionHeader.tsx +0 -87
- package/client/vendor/paseo-plugin-helper/components/Select.tsx +0 -283
- package/client/vendor/paseo-plugin-helper/components/StatusDot.tsx +0 -80
- package/client/vendor/paseo-plugin-helper/components/Tabs.tsx +0 -319
- package/client/vendor/paseo-plugin-helper/components/TextInput.tsx +0 -150
- package/client/vendor/paseo-plugin-helper/components/Toggle.tsx +0 -163
- package/client/vendor/paseo-plugin-helper/components/TruncatedText.tsx +0 -157
- package/client/vendor/paseo-plugin-helper/components/index.ts +0 -26
- package/client/vendor/paseo-plugin-helper/custom-pills.tsx +0 -225
- package/client/vendor/paseo-plugin-helper/forge-icon.tsx +0 -79
- package/client/vendor/paseo-plugin-helper/icon.tsx +0 -39
- package/client/vendor/paseo-plugin-helper/index.ts +0 -30
- package/client/vendor/paseo-plugin-helper/layout/ActionBar.tsx +0 -49
- package/client/vendor/paseo-plugin-helper/layout/FormRow.tsx +0 -103
- package/client/vendor/paseo-plugin-helper/layout/Grid.tsx +0 -65
- package/client/vendor/paseo-plugin-helper/layout/ModalBody.tsx +0 -368
- package/client/vendor/paseo-plugin-helper/layout/ModalContent.tsx +0 -51
- package/client/vendor/paseo-plugin-helper/layout/Row.tsx +0 -39
- package/client/vendor/paseo-plugin-helper/layout/Stack.tsx +0 -39
- package/client/vendor/paseo-plugin-helper/layout/index.ts +0 -7
- package/client/vendor/paseo-plugin-helper/styles/index.ts +0 -1
- package/client/vendor/paseo-plugin-helper/styles/recipes.ts +0 -550
- package/client/vendor/paseo-plugin-helper/theme/flair.ts +0 -76
- package/client/vendor/paseo-plugin-helper/theme/host-variables.ts +0 -121
- package/client/vendor/paseo-plugin-helper/theme/index.ts +0 -7
- package/client/vendor/paseo-plugin-helper/theme/provider.tsx +0 -178
- package/client/vendor/paseo-plugin-helper/theme/responsive.ts +0 -213
- package/client/vendor/paseo-plugin-helper/theme/tokens.ts +0 -200
- package/client/vendor/paseo-plugin-helper/theme/useResponsive.ts +0 -57
- package/client/vendor/paseo-plugin-helper/tickets.tsx +0 -766
- /package/client/vendor/paseo-plugin-helper/{command-center.ts → core/command-center.ts} +0 -0
- /package/client/vendor/paseo-plugin-helper/{snapshot.ts → core/snapshot.ts} +0 -0
- /package/client/vendor/paseo-plugin-helper/{utils → lifecycle}/haptics.ts +0 -0
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import React, { type ReactNode } from "react";
|
|
2
2
|
import { StyleSheet, Text, View, type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { useHostTheme, useHostLayout } from "./theme";
|
|
4
|
+
import { spacing } from "./layout";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Paseo Plugin Helper — UI data adapters (`paseo-plugin-helper/ui`).
|
|
8
|
+
*
|
|
9
|
+
* Thin, host-delegating data adapters
|
|
10
|
+
* (DataTable). Same contract: host theme colors only, no scroll ownership, no
|
|
11
|
+
* design-system machinery.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface HostDataColumn<T> {
|
|
6
15
|
key: string;
|
|
7
16
|
header: string;
|
|
8
17
|
flex?: number;
|
|
@@ -11,33 +20,33 @@ export interface DataColumn<T> {
|
|
|
11
20
|
render: (item: T) => ReactNode;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
|
-
export interface
|
|
23
|
+
export interface HostDataTableProps<T> {
|
|
15
24
|
data: T[];
|
|
16
|
-
columns:
|
|
25
|
+
columns: HostDataColumn<T>[];
|
|
17
26
|
keyExtractor: (item: T, index: number) => string;
|
|
18
27
|
emptyState?: ReactNode;
|
|
19
28
|
style?: StyleProp<ViewStyle>;
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
/**
|
|
23
|
-
* Responsive data table that
|
|
24
|
-
*
|
|
32
|
+
* Responsive data table that reflows between a traditional table on wide
|
|
33
|
+
* surfaces and a structured card list on compact/mobile layouts.
|
|
25
34
|
*/
|
|
26
|
-
export function
|
|
35
|
+
export function HostDataTable<T>({
|
|
27
36
|
data,
|
|
28
37
|
columns,
|
|
29
38
|
keyExtractor,
|
|
30
39
|
emptyState,
|
|
31
40
|
style,
|
|
32
|
-
}:
|
|
33
|
-
const { colors
|
|
34
|
-
const
|
|
41
|
+
}: HostDataTableProps<T>) {
|
|
42
|
+
const { colors } = useHostTheme();
|
|
43
|
+
const layout = useHostLayout();
|
|
44
|
+
const isCompact = layout.compact || layout.platform === "ios" || layout.platform === "android";
|
|
35
45
|
|
|
36
46
|
if (!data || data.length === 0) {
|
|
37
47
|
return emptyState ? <View style={style}>{emptyState}</View> : null;
|
|
38
48
|
}
|
|
39
49
|
|
|
40
|
-
// Mobile / compact card-list layout
|
|
41
50
|
if (isCompact) {
|
|
42
51
|
return (
|
|
43
52
|
<View style={[styles.compactContainer, style]}>
|
|
@@ -49,7 +58,6 @@ export function DataTable<T>({
|
|
|
49
58
|
{
|
|
50
59
|
backgroundColor: colors.surface1,
|
|
51
60
|
borderColor: colors.border,
|
|
52
|
-
borderRadius: radius,
|
|
53
61
|
},
|
|
54
62
|
]}
|
|
55
63
|
>
|
|
@@ -67,20 +75,17 @@ export function DataTable<T>({
|
|
|
67
75
|
);
|
|
68
76
|
}
|
|
69
77
|
|
|
70
|
-
// Desktop tabular layout
|
|
71
78
|
return (
|
|
72
79
|
<View
|
|
73
80
|
style={[
|
|
74
81
|
styles.table,
|
|
75
82
|
{
|
|
76
83
|
borderColor: colors.border,
|
|
77
|
-
borderRadius: radius,
|
|
78
84
|
backgroundColor: colors.surface0,
|
|
79
85
|
},
|
|
80
86
|
style,
|
|
81
87
|
]}
|
|
82
88
|
>
|
|
83
|
-
{/* Header Row */}
|
|
84
89
|
<View
|
|
85
90
|
style={[
|
|
86
91
|
styles.headerRow,
|
|
@@ -100,8 +105,8 @@ export function DataTable<T>({
|
|
|
100
105
|
col.align === "right"
|
|
101
106
|
? styles.alignRight
|
|
102
107
|
: col.align === "center"
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
? styles.alignCenter
|
|
109
|
+
: styles.alignLeft,
|
|
105
110
|
]}
|
|
106
111
|
>
|
|
107
112
|
<Text
|
|
@@ -115,7 +120,6 @@ export function DataTable<T>({
|
|
|
115
120
|
))}
|
|
116
121
|
</View>
|
|
117
122
|
|
|
118
|
-
{/* Rows */}
|
|
119
123
|
{data.map((item, idx) => (
|
|
120
124
|
<View
|
|
121
125
|
key={keyExtractor(item, idx)}
|
|
@@ -134,8 +138,8 @@ export function DataTable<T>({
|
|
|
134
138
|
col.align === "right"
|
|
135
139
|
? styles.alignRight
|
|
136
140
|
: col.align === "center"
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
? styles.alignCenter
|
|
142
|
+
: styles.alignLeft,
|
|
139
143
|
]}
|
|
140
144
|
>
|
|
141
145
|
{col.render(item)}
|
|
@@ -148,29 +152,43 @@ export function DataTable<T>({
|
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
const styles = StyleSheet.create({
|
|
155
|
+
compactContainer: {
|
|
156
|
+
gap: spacing.sm,
|
|
157
|
+
},
|
|
158
|
+
compactCard: {
|
|
159
|
+
borderWidth: 1,
|
|
160
|
+
borderRadius: 10,
|
|
161
|
+
padding: spacing.md,
|
|
162
|
+
gap: spacing.xs,
|
|
163
|
+
},
|
|
164
|
+
compactRow: {
|
|
165
|
+
flexDirection: "row",
|
|
166
|
+
justifyContent: "space-between",
|
|
167
|
+
gap: spacing.sm,
|
|
168
|
+
},
|
|
169
|
+
compactHeader: {
|
|
170
|
+
fontSize: 11,
|
|
171
|
+
flexShrink: 1,
|
|
172
|
+
},
|
|
173
|
+
compactValue: {
|
|
174
|
+
flexShrink: 1,
|
|
175
|
+
minWidth: 0,
|
|
176
|
+
},
|
|
151
177
|
table: {
|
|
152
178
|
borderWidth: 1,
|
|
179
|
+
borderRadius: 10,
|
|
153
180
|
overflow: "hidden",
|
|
154
181
|
},
|
|
155
182
|
headerRow: {
|
|
156
183
|
flexDirection: "row",
|
|
157
184
|
borderBottomWidth: 1,
|
|
158
|
-
paddingVertical: 8,
|
|
159
|
-
paddingHorizontal: 12,
|
|
160
185
|
},
|
|
161
186
|
row: {
|
|
162
187
|
flexDirection: "row",
|
|
163
|
-
paddingVertical: 10,
|
|
164
|
-
paddingHorizontal: 12,
|
|
165
|
-
alignItems: "center",
|
|
166
188
|
},
|
|
167
189
|
cell: {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// carries a long string (a title, a path) refuses to give up width and
|
|
171
|
-
// squeezes its sibling columns instead of truncating.
|
|
172
|
-
flexShrink: 1,
|
|
173
|
-
maxWidth: "100%",
|
|
190
|
+
paddingHorizontal: spacing.md,
|
|
191
|
+
paddingVertical: spacing.sm,
|
|
174
192
|
},
|
|
175
193
|
alignLeft: {
|
|
176
194
|
alignItems: "flex-start",
|
|
@@ -184,33 +202,7 @@ const styles = StyleSheet.create({
|
|
|
184
202
|
headerText: {
|
|
185
203
|
fontSize: 11,
|
|
186
204
|
fontWeight: "600",
|
|
205
|
+
letterSpacing: 0.3,
|
|
187
206
|
textTransform: "uppercase",
|
|
188
|
-
letterSpacing: 0.5,
|
|
189
|
-
flexShrink: 1,
|
|
190
|
-
},
|
|
191
|
-
compactContainer: {
|
|
192
|
-
gap: 8,
|
|
193
|
-
},
|
|
194
|
-
compactCard: {
|
|
195
|
-
borderWidth: 1,
|
|
196
|
-
padding: 12,
|
|
197
|
-
gap: 6,
|
|
198
|
-
},
|
|
199
|
-
compactRow: {
|
|
200
|
-
flexDirection: "row",
|
|
201
|
-
justifyContent: "space-between",
|
|
202
|
-
alignItems: "center",
|
|
203
|
-
gap: 8,
|
|
204
|
-
},
|
|
205
|
-
compactHeader: {
|
|
206
|
-
fontSize: 12,
|
|
207
|
-
flexShrink: 1,
|
|
208
|
-
},
|
|
209
|
-
compactValue: {
|
|
210
|
-
alignItems: "flex-end",
|
|
211
|
-
// The value side carries the actual data, so it takes the compressible
|
|
212
|
-
// slot and the fixed label beside it keeps its intrinsic width.
|
|
213
|
-
flexShrink: 1,
|
|
214
|
-
maxWidth: "100%",
|
|
215
207
|
},
|
|
216
208
|
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paseo Plugin Helper — UI Kit / Adapters (`paseo-plugin-helper/ui`).
|
|
3
|
+
*
|
|
4
|
+
* Thin, composable adapters strictly conforming to upstream native
|
|
5
|
+
* primitives. Rules for everything in this entry:
|
|
6
|
+
*
|
|
7
|
+
* - Scroll ownership stays with the host (`Modal.Content` default
|
|
8
|
+
* `scrollable`; explicit host `ScrollView` only where the host supplies
|
|
9
|
+
* no scroller). Never force `scrollable={false}` plus a helper-owned
|
|
10
|
+
* replacement scroller. No scroll-ownership state machine.
|
|
11
|
+
* - No artificial width caps: no `maxContentWidth`, no `size="large"` with
|
|
12
|
+
* hardcoded `minWidth`. Fill the host-allocated frame fluidly.
|
|
13
|
+
* - No DOM CSS variable scrapers: colors arrive via the host `theme` prop
|
|
14
|
+
* through `HostThemeProvider` — never from `getComputedStyle`.
|
|
15
|
+
* - Upstream settings primitives come from the host bundle
|
|
16
|
+
* (`@getpaseo/plugin/client/ui`), injected by the plugin — never
|
|
17
|
+
* re-implemented here.
|
|
18
|
+
*
|
|
19
|
+
* This is the only UI the package ships: the legacy bespoke kit was removed
|
|
20
|
+
* in #938, and the CLI audit flags new `maxContentWidth` / `scrollable={false}`
|
|
21
|
+
* uses with pointers here.
|
|
22
|
+
*
|
|
23
|
+
* Module map:
|
|
24
|
+
* - `ui/theme.tsx` — `HostThemeProvider` / `useHostTheme` (host colors only)
|
|
25
|
+
* - `ui/color.ts` — `alpha()` and status color helpers (pure)
|
|
26
|
+
* - `ui/modal.tsx` — `HostModalContent` / `HostScroll` / `HostModalSection`
|
|
27
|
+
* - `ui/layout.tsx` — `HostStack` / `HostRow` / `HostGrid` / `HostActionBar` / `HostFormRow`
|
|
28
|
+
* - `ui/content.tsx` — `HostCard` / `HostTabs` / `HostBadge` / `HostKeyValue` / …
|
|
29
|
+
* - `ui/controls.tsx` — `HostButton` / `HostToggle` / `HostSelect` / `HostTextInput` / …
|
|
30
|
+
* - `ui/text.tsx` — `HostCodeBlock` / `HostCommandBox` / `HostTruncatedText` / …
|
|
31
|
+
* - `ui/data.tsx` — `HostDataTable`
|
|
32
|
+
* - `ui/settings.ts` — settings screen adapters over the host ui bundle
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
export * from "./theme";
|
|
36
|
+
export * from "./color";
|
|
37
|
+
export * from "./modal";
|
|
38
|
+
export * from "./layout";
|
|
39
|
+
export * from "./content";
|
|
40
|
+
export * from "./controls";
|
|
41
|
+
export * from "./text";
|
|
42
|
+
export * from "./data";
|
|
43
|
+
export * from "./settings";
|
|
44
|
+
export { PluginReloadBanner } from "./plugin-reload-banner";
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import { StyleSheet, Text, View, type StyleProp, type ViewStyle } from "react-native";
|
|
3
|
+
import { useHostTheme } from "./theme";
|
|
4
|
+
|
|
5
|
+
/** Static spacing scale (px). The host owns the design language; this is just layout. */
|
|
6
|
+
export const spacing = {
|
|
7
|
+
xs: 4,
|
|
8
|
+
sm: 8,
|
|
9
|
+
md: 12,
|
|
10
|
+
lg: 16,
|
|
11
|
+
xl: 24,
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export type SpacingValue = keyof typeof spacing | number;
|
|
15
|
+
|
|
16
|
+
export function resolveSpacing(value: SpacingValue | undefined, fallback: number): number {
|
|
17
|
+
if (value === undefined) return fallback;
|
|
18
|
+
if (typeof value === "number") return value;
|
|
19
|
+
return spacing[value] ?? fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface HostRowProps {
|
|
23
|
+
children: ReactNode;
|
|
24
|
+
gap?: number;
|
|
25
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
26
|
+
justify?: "start" | "center" | "end" | "between";
|
|
27
|
+
wrap?: boolean;
|
|
28
|
+
style?: StyleProp<ViewStyle>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Host-delegating horizontal row for `paseo-plugin-helper/ui`.
|
|
33
|
+
*
|
|
34
|
+
* Colors come from `useHostTheme()` (provided by `HostThemeProvider`) — no
|
|
35
|
+
* theme scraping.
|
|
36
|
+
*/
|
|
37
|
+
export function HostRow({
|
|
38
|
+
children,
|
|
39
|
+
gap = 8,
|
|
40
|
+
align = "center",
|
|
41
|
+
justify = "start",
|
|
42
|
+
wrap = false,
|
|
43
|
+
style,
|
|
44
|
+
}: HostRowProps) {
|
|
45
|
+
return (
|
|
46
|
+
<View
|
|
47
|
+
style={[
|
|
48
|
+
styles.row,
|
|
49
|
+
{
|
|
50
|
+
gap,
|
|
51
|
+
alignItems: alignMap[align],
|
|
52
|
+
justifyContent: justifyMap[justify],
|
|
53
|
+
flexWrap: wrap ? "wrap" : "nowrap",
|
|
54
|
+
},
|
|
55
|
+
style,
|
|
56
|
+
]}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</View>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface HostStackProps {
|
|
64
|
+
children: ReactNode;
|
|
65
|
+
gap?: number;
|
|
66
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
67
|
+
justify?: "start" | "center" | "end" | "between";
|
|
68
|
+
grow?: boolean;
|
|
69
|
+
style?: StyleProp<ViewStyle>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Host-delegating vertical stack for `paseo-plugin-helper/ui`.
|
|
74
|
+
*
|
|
75
|
+
* Colors come from `useHostTheme()` (provided by `HostThemeProvider`) — no
|
|
76
|
+
* theme scraping.
|
|
77
|
+
*/
|
|
78
|
+
export function HostStack({
|
|
79
|
+
children,
|
|
80
|
+
gap = 8,
|
|
81
|
+
align = "stretch",
|
|
82
|
+
justify = "start",
|
|
83
|
+
grow = false,
|
|
84
|
+
style,
|
|
85
|
+
}: HostStackProps) {
|
|
86
|
+
return (
|
|
87
|
+
<View
|
|
88
|
+
style={[
|
|
89
|
+
styles.stack,
|
|
90
|
+
{
|
|
91
|
+
gap,
|
|
92
|
+
alignItems: alignMap[align],
|
|
93
|
+
justifyContent: justifyMap[justify],
|
|
94
|
+
...(grow ? { flex: 1, minHeight: 0 } : null),
|
|
95
|
+
},
|
|
96
|
+
style,
|
|
97
|
+
]}
|
|
98
|
+
>
|
|
99
|
+
{children}
|
|
100
|
+
</View>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface HostGridProps {
|
|
105
|
+
children: ReactNode;
|
|
106
|
+
columns?: number;
|
|
107
|
+
gap?: number;
|
|
108
|
+
style?: StyleProp<ViewStyle>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Host-delegating wrapping grid for `paseo-plugin-helper/ui`.
|
|
113
|
+
*
|
|
114
|
+
* Colors come from `useHostTheme()` (provided by `HostThemeProvider`) — no
|
|
115
|
+
* theme scraping.
|
|
116
|
+
*/
|
|
117
|
+
export function HostGrid({
|
|
118
|
+
children,
|
|
119
|
+
columns = 2,
|
|
120
|
+
gap = 8,
|
|
121
|
+
style,
|
|
122
|
+
}: HostGridProps) {
|
|
123
|
+
return (
|
|
124
|
+
<View style={[styles.grid, { gap }, style]}>
|
|
125
|
+
{React.Children.map(children, (child) => (
|
|
126
|
+
<View style={{ flexBasis: `${100 / columns}%`, flexGrow: 0, flexShrink: 1, minWidth: 0 }}>
|
|
127
|
+
{child}
|
|
128
|
+
</View>
|
|
129
|
+
))}
|
|
130
|
+
</View>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface HostActionBarProps {
|
|
135
|
+
children: ReactNode;
|
|
136
|
+
style?: StyleProp<ViewStyle>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Host-delegating action bar for `paseo-plugin-helper/ui`.
|
|
141
|
+
*
|
|
142
|
+
* Colors come from `useHostTheme()` (provided by `HostThemeProvider`) — no
|
|
143
|
+
* theme scraping.
|
|
144
|
+
*/
|
|
145
|
+
export function HostActionBar({
|
|
146
|
+
children,
|
|
147
|
+
style,
|
|
148
|
+
}: HostActionBarProps) {
|
|
149
|
+
return (
|
|
150
|
+
<View style={[styles.actionBar, style]}>
|
|
151
|
+
{children}
|
|
152
|
+
</View>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface HostFormRowProps {
|
|
157
|
+
label: string;
|
|
158
|
+
description?: string;
|
|
159
|
+
children: ReactNode;
|
|
160
|
+
layout?: "stacked" | "inline";
|
|
161
|
+
style?: StyleProp<ViewStyle>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Host-delegating form row for `paseo-plugin-helper/ui`.
|
|
166
|
+
*
|
|
167
|
+
* Colors come from `useHostTheme()` (provided by `HostThemeProvider`) — no
|
|
168
|
+
* theme scraping.
|
|
169
|
+
*/
|
|
170
|
+
export function HostFormRow({
|
|
171
|
+
label,
|
|
172
|
+
description,
|
|
173
|
+
children,
|
|
174
|
+
layout = "stacked",
|
|
175
|
+
style,
|
|
176
|
+
}: HostFormRowProps) {
|
|
177
|
+
const { colors } = useHostTheme();
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<View
|
|
181
|
+
style={[
|
|
182
|
+
styles.formRow,
|
|
183
|
+
layout === "inline" ? styles.formRowInline : styles.formRowStacked,
|
|
184
|
+
style,
|
|
185
|
+
]}
|
|
186
|
+
>
|
|
187
|
+
<View style={styles.formLabel}>
|
|
188
|
+
<Text style={[styles.formLabelText, { color: colors.foreground }]}>{label}</Text>
|
|
189
|
+
{description ? (
|
|
190
|
+
<Text style={[styles.formDescription, { color: colors.foregroundMuted }]}>
|
|
191
|
+
{description}
|
|
192
|
+
</Text>
|
|
193
|
+
) : null}
|
|
194
|
+
</View>
|
|
195
|
+
<View style={styles.formControl}>{children}</View>
|
|
196
|
+
</View>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const alignMap = {
|
|
201
|
+
start: "flex-start",
|
|
202
|
+
center: "center",
|
|
203
|
+
end: "flex-end",
|
|
204
|
+
stretch: "stretch",
|
|
205
|
+
} as const;
|
|
206
|
+
|
|
207
|
+
const justifyMap = {
|
|
208
|
+
start: "flex-start",
|
|
209
|
+
center: "center",
|
|
210
|
+
end: "flex-end",
|
|
211
|
+
between: "space-between",
|
|
212
|
+
} as const;
|
|
213
|
+
|
|
214
|
+
const styles = StyleSheet.create({
|
|
215
|
+
row: {
|
|
216
|
+
flexDirection: "row",
|
|
217
|
+
width: "100%",
|
|
218
|
+
},
|
|
219
|
+
stack: {
|
|
220
|
+
flexDirection: "column",
|
|
221
|
+
width: "100%",
|
|
222
|
+
},
|
|
223
|
+
grid: {
|
|
224
|
+
flexDirection: "row",
|
|
225
|
+
flexWrap: "wrap",
|
|
226
|
+
width: "100%",
|
|
227
|
+
},
|
|
228
|
+
actionBar: {
|
|
229
|
+
flexDirection: "row",
|
|
230
|
+
alignItems: "center",
|
|
231
|
+
justifyContent: "flex-end",
|
|
232
|
+
gap: 8,
|
|
233
|
+
width: "100%",
|
|
234
|
+
flexWrap: "wrap",
|
|
235
|
+
},
|
|
236
|
+
formRow: {
|
|
237
|
+
gap: 4,
|
|
238
|
+
width: "100%",
|
|
239
|
+
},
|
|
240
|
+
formRowStacked: {
|
|
241
|
+
flexDirection: "column",
|
|
242
|
+
},
|
|
243
|
+
formRowInline: {
|
|
244
|
+
flexDirection: "row",
|
|
245
|
+
alignItems: "center",
|
|
246
|
+
justifyContent: "space-between",
|
|
247
|
+
},
|
|
248
|
+
formLabel: {
|
|
249
|
+
gap: 2,
|
|
250
|
+
flexShrink: 1,
|
|
251
|
+
},
|
|
252
|
+
formLabelText: {
|
|
253
|
+
fontSize: 13,
|
|
254
|
+
fontWeight: "600",
|
|
255
|
+
},
|
|
256
|
+
formDescription: {
|
|
257
|
+
fontSize: 11,
|
|
258
|
+
},
|
|
259
|
+
formControl: {
|
|
260
|
+
flexShrink: 1,
|
|
261
|
+
minWidth: 0,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ScrollView as FallbackScrollView,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
View,
|
|
6
|
+
type ScrollViewProps,
|
|
7
|
+
type StyleProp,
|
|
8
|
+
type ViewStyle,
|
|
9
|
+
} from "react-native";
|
|
10
|
+
import {
|
|
11
|
+
getClientHost,
|
|
12
|
+
getOptionalClientHost,
|
|
13
|
+
selectHostScrollView,
|
|
14
|
+
type HostScrollView,
|
|
15
|
+
} from "../core/host";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Host-delegating modal content for `paseo-plugin-helper/ui`.
|
|
19
|
+
*
|
|
20
|
+
* Contract — ONLY for content rendered directly inside your OWN host
|
|
21
|
+
* `<Modal>` (e.g. x-comms style own-modal surfaces):
|
|
22
|
+
* - Scroll ownership stays with the host: renders the injected host
|
|
23
|
+
* `<Modal.Content>` with its default `scrollable` behavior and adds NO
|
|
24
|
+
* helper-owned scroller, so sheet gestures, keyboard avoidance, and
|
|
25
|
+
* safe-area clearance keep working on compact/mobile and desktop alike.
|
|
26
|
+
* - No width opinions: there is deliberately NO `maxContentWidth` /
|
|
27
|
+
* `size="large"` prop. The host allocates the dialog frame; this wrapper
|
|
28
|
+
* fills it fluidly (`width: "100%"`).
|
|
29
|
+
* - No theme scraping: colors come from the host `theme` prop via
|
|
30
|
+
* `PluginThemeProvider`, never from DOM CSS variables.
|
|
31
|
+
* - NEVER render this inside `registerComposerPill` `renderModal`: the pill
|
|
32
|
+
* host already provides the one `<Modal.Content>` (or no modal at all on
|
|
33
|
+
* 0.8 popovers), so a nested `<Modal.Content>` violates the host contract
|
|
34
|
+
* and crashes the plugin. Use `HostModalSection` there instead.
|
|
35
|
+
*/
|
|
36
|
+
export function HostModalContent({
|
|
37
|
+
children,
|
|
38
|
+
style,
|
|
39
|
+
contentContainerStyle,
|
|
40
|
+
}: {
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
style?: StyleProp<ViewStyle>;
|
|
43
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
44
|
+
}) {
|
|
45
|
+
const { Modal } = getClientHost();
|
|
46
|
+
return (
|
|
47
|
+
<Modal.Content>
|
|
48
|
+
<View style={[styles.fluid, style, contentContainerStyle]}>{children}</View>
|
|
49
|
+
</Modal.Content>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Explicit single scroll owner for surfaces where the host supplies NO
|
|
55
|
+
* scroller (sidebar surfaces, settings screens). Prefers the injected host
|
|
56
|
+
* ScrollView (sheet-gesture integrated on Paseo v0.8) and falls back to plain
|
|
57
|
+
* React Native ScrollView. Callers own the decision to scroll; this component
|
|
58
|
+
* never nests itself inside another scroller.
|
|
59
|
+
*/
|
|
60
|
+
export function HostScroll({
|
|
61
|
+
children,
|
|
62
|
+
style,
|
|
63
|
+
contentContainerStyle,
|
|
64
|
+
...props
|
|
65
|
+
}: {
|
|
66
|
+
children: ReactNode;
|
|
67
|
+
style?: StyleProp<ViewStyle>;
|
|
68
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
69
|
+
} & ScrollViewProps) {
|
|
70
|
+
const ResolvedScrollView = selectHostScrollView(
|
|
71
|
+
getOptionalClientHost(),
|
|
72
|
+
FallbackScrollView as unknown as HostScrollView,
|
|
73
|
+
);
|
|
74
|
+
return (
|
|
75
|
+
<ResolvedScrollView
|
|
76
|
+
{...(props as ScrollViewProps)}
|
|
77
|
+
style={[styles.fluid, style]}
|
|
78
|
+
contentContainerStyle={contentContainerStyle}
|
|
79
|
+
>
|
|
80
|
+
{children}
|
|
81
|
+
</ResolvedScrollView>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const styles = StyleSheet.create({
|
|
86
|
+
fluid: {
|
|
87
|
+
width: "100%",
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Fluid inner content for pill-embedded modals (`registerComposerPill`
|
|
93
|
+
* `renderModal`).
|
|
94
|
+
*
|
|
95
|
+
* The pill host already provides the one `<Modal.Content>` (legacy/centered
|
|
96
|
+
* modal paths) or no modal at all (0.8 popover path, where the host owns the
|
|
97
|
+
* outer scroll). This renders a plain fluid `<View>` — no `<Modal.Content>`,
|
|
98
|
+
* no scroller, no width caps — so exactly one `<Modal.Content>` exists and
|
|
99
|
+
* nothing nests. Pair with `hostScroll: true` on the pill registration so
|
|
100
|
+
* the wrapper leaves scrolling to the host; without it the wrapper bounds
|
|
101
|
+
* the dialog (`scrollable={false}`) for legacy `ModalBody` content.
|
|
102
|
+
*/
|
|
103
|
+
export function HostModalSection({
|
|
104
|
+
children,
|
|
105
|
+
style,
|
|
106
|
+
}: {
|
|
107
|
+
children: ReactNode;
|
|
108
|
+
style?: StyleProp<ViewStyle>;
|
|
109
|
+
}) {
|
|
110
|
+
return <View style={[styles.fluid, style]}>{children}</View>;
|
|
111
|
+
}
|