@agimon-ai/po-template-advanced 0.0.0-alpha.1 → 0.0.0-alpha.3

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.
@@ -3,9 +3,308 @@ import { View } from "react-native-unistyles/components/native/View";
3
3
  import { Text } from "react-native-unistyles/components/native/Text";
4
4
  import { ScrollView } from "react-native-unistyles/components/native/ScrollView";
5
5
  import { Pressable } from "react-native-unistyles/components/native/Pressable";
6
- import { AlertIcon, BranchIcon, EmptyState, FolderIcon, Spinner, fontOf } from "@agimon-ai/po-native-components";
6
+ import { AlertIcon, Badge, BranchIcon, Button, EmptyState, FolderIcon, Input, KebabIcon, PlusIcon, Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle, Spinner, UsersIcon, fontOf } from "@agimon-ai/po-native-components";
7
+ import { useState } from "react";
7
8
  import { StyleSheet } from "react-native-unistyles";
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ //#region src/extensions/(frontend)/template/_components/AdvancedSessionMenus.native.tsx
11
+ function Items({ items }) {
12
+ return /* @__PURE__ */ jsx(View, {
13
+ style: styles$1.list,
14
+ children: items.map((item, index) => /* @__PURE__ */ jsxs(Pressable, {
15
+ accessibilityRole: "button",
16
+ accessibilityState: { disabled: item.disabled === true },
17
+ disabled: item.disabled,
18
+ onPress: item.onPress,
19
+ style: ({ pressed }) => [
20
+ styles$1.item,
21
+ index > 0 && styles$1.divider,
22
+ pressed && styles$1.pressed
23
+ ],
24
+ children: [/* @__PURE__ */ jsx(Text, {
25
+ style: styles$1.itemLabel(item.danger === true, item.disabled === true),
26
+ children: item.label
27
+ }), item.hint ? /* @__PURE__ */ jsx(Text, {
28
+ style: styles$1.meta,
29
+ children: item.hint
30
+ }) : null]
31
+ }, item.label))
32
+ });
33
+ }
34
+ /** A session card's ⋮: the cockpit's rename, resume, restart and remove, with remove confirmed first. */
35
+ function SessionMenuSheet({ session, actions, onClose }) {
36
+ const [step, setStep] = useState("menu");
37
+ const [draft, setDraft] = useState("");
38
+ const [busy, setBusy] = useState(false);
39
+ const [error, setError] = useState("");
40
+ const close = () => {
41
+ if (busy) return;
42
+ setStep("menu");
43
+ setError("");
44
+ onClose();
45
+ };
46
+ const name = session?.name || "Untitled";
47
+ const remove = async () => {
48
+ if (session === null) return;
49
+ setBusy(true);
50
+ setError("");
51
+ const result = await actions.removeSession(session.id);
52
+ setBusy(false);
53
+ if (result !== void 0) {
54
+ setError(result.error);
55
+ return;
56
+ }
57
+ setStep("menu");
58
+ onClose();
59
+ };
60
+ return /* @__PURE__ */ jsx(Sheet, {
61
+ open: session !== null,
62
+ onOpenChange: (open) => !open && close(),
63
+ children: /* @__PURE__ */ jsx(SheetContent, { children: session === null ? null : step === "rename" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, { children: "Rename session" }) }), /* @__PURE__ */ jsxs(SheetBody, {
64
+ style: styles$1.body,
65
+ children: [/* @__PURE__ */ jsx(Input, {
66
+ value: draft,
67
+ onChangeText: setDraft,
68
+ autoFocus: true,
69
+ accessibilityLabel: "Session name"
70
+ }), /* @__PURE__ */ jsx(Button, {
71
+ variant: "primary",
72
+ size: "lg",
73
+ disabled: draft.trim() === "",
74
+ onPress: () => {
75
+ actions.renameSession(session.id, draft);
76
+ close();
77
+ },
78
+ children: "Rename"
79
+ })]
80
+ })] }) : step === "confirm" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, { children: "Remove session" }) }), /* @__PURE__ */ jsxs(SheetBody, {
81
+ style: styles$1.body,
82
+ children: [
83
+ /* @__PURE__ */ jsxs(Text, {
84
+ style: styles$1.text,
85
+ children: [
86
+ "This stops ",
87
+ /* @__PURE__ */ jsx(Text, {
88
+ style: styles$1.strong,
89
+ children: name
90
+ }),
91
+ " and removes it from the list. Anything it is running ends now, but its saved history remains available to resume."
92
+ ]
93
+ }),
94
+ error ? /* @__PURE__ */ jsx(Text, {
95
+ style: styles$1.error,
96
+ accessibilityRole: "alert",
97
+ children: error
98
+ }) : null,
99
+ /* @__PURE__ */ jsx(Button, {
100
+ variant: "danger",
101
+ size: "lg",
102
+ loading: busy,
103
+ loadingLabel: "Removing",
104
+ onPress: () => void remove(),
105
+ children: "Remove"
106
+ }),
107
+ /* @__PURE__ */ jsx(Button, {
108
+ variant: "ghost",
109
+ size: "lg",
110
+ disabled: busy,
111
+ onPress: () => setStep("menu"),
112
+ children: "Cancel"
113
+ })
114
+ ]
115
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, {
116
+ numberOfLines: 1,
117
+ children: name
118
+ }) }), /* @__PURE__ */ jsx(SheetBody, {
119
+ style: styles$1.body,
120
+ children: /* @__PURE__ */ jsx(Items, { items: [
121
+ {
122
+ label: "Rename",
123
+ onPress: () => {
124
+ setDraft(session.name);
125
+ setStep("rename");
126
+ }
127
+ },
128
+ {
129
+ label: "Resume",
130
+ hint: "Open an earlier conversation in this session",
131
+ onPress: () => {
132
+ close();
133
+ actions.resumeSession(session.id);
134
+ }
135
+ },
136
+ {
137
+ label: "Restart",
138
+ hint: session.restartBlocked ? "Not while a turn runs" : "Reloads extensions",
139
+ disabled: session.restarting || session.restartBlocked === true,
140
+ onPress: () => {
141
+ close();
142
+ actions.restartSession(session.id);
143
+ }
144
+ },
145
+ {
146
+ label: "Remove",
147
+ danger: true,
148
+ onPress: () => setStep("confirm")
149
+ }
150
+ ] })
151
+ })] }) })
152
+ });
153
+ }
154
+ /** A workspace's ⋮: resume a saved conversation here, or remove the workspace after confirming. */
155
+ function WorkspaceMenuSheet({ workspace, actions, onClose }) {
156
+ const [confirming, setConfirming] = useState(false);
157
+ const [busy, setBusy] = useState(false);
158
+ const [error, setError] = useState("");
159
+ const close = () => {
160
+ if (busy) return;
161
+ setConfirming(false);
162
+ setError("");
163
+ onClose();
164
+ };
165
+ const remove = async () => {
166
+ if (workspace === null) return;
167
+ setBusy(true);
168
+ setError("");
169
+ const result = await actions.deleteWorkspace(workspace.id);
170
+ setBusy(false);
171
+ if (result !== void 0) {
172
+ setError(result.error);
173
+ return;
174
+ }
175
+ setConfirming(false);
176
+ onClose();
177
+ };
178
+ return /* @__PURE__ */ jsx(Sheet, {
179
+ open: workspace !== null,
180
+ onOpenChange: (open) => !open && close(),
181
+ children: /* @__PURE__ */ jsx(SheetContent, { children: workspace === null ? null : confirming ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, { children: "Remove workspace" }) }), /* @__PURE__ */ jsxs(SheetBody, {
182
+ style: styles$1.body,
183
+ children: [
184
+ /* @__PURE__ */ jsxs(Text, {
185
+ style: styles$1.text,
186
+ children: [
187
+ "This unregisters ",
188
+ /* @__PURE__ */ jsx(Text, {
189
+ style: styles$1.strong,
190
+ children: workspace.name
191
+ }),
192
+ " from Po only. Files at",
193
+ " ",
194
+ /* @__PURE__ */ jsx(Text, {
195
+ style: styles$1.mono,
196
+ children: workspace.root
197
+ }),
198
+ " stay on disk. Its sessions must be removed first."
199
+ ]
200
+ }),
201
+ error ? /* @__PURE__ */ jsx(Text, {
202
+ style: styles$1.error,
203
+ accessibilityRole: "alert",
204
+ children: error
205
+ }) : null,
206
+ /* @__PURE__ */ jsx(Button, {
207
+ variant: "danger",
208
+ size: "lg",
209
+ loading: busy,
210
+ loadingLabel: "Removing",
211
+ onPress: () => void remove(),
212
+ children: "Remove"
213
+ }),
214
+ /* @__PURE__ */ jsx(Button, {
215
+ variant: "ghost",
216
+ size: "lg",
217
+ disabled: busy,
218
+ onPress: () => setConfirming(false),
219
+ children: "Cancel"
220
+ })
221
+ ]
222
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, {
223
+ numberOfLines: 1,
224
+ children: workspace.name
225
+ }) }), /* @__PURE__ */ jsx(SheetBody, {
226
+ style: styles$1.body,
227
+ children: /* @__PURE__ */ jsx(Items, { items: [{
228
+ label: "Resume session",
229
+ disabled: !workspace.available,
230
+ onPress: () => {
231
+ close();
232
+ actions.resumeInWorkspace(workspace.id);
233
+ }
234
+ }, {
235
+ label: "Remove workspace",
236
+ danger: true,
237
+ onPress: () => setConfirming(true)
238
+ }] })
239
+ })] }) })
240
+ });
241
+ }
242
+ const styles$1 = StyleSheet.create((theme) => {
243
+ const sans = fontOf(theme.fontFamily.sans);
244
+ const text = (size, color) => ({
245
+ fontFamily: sans,
246
+ fontSize: theme.fontSize[size],
247
+ lineHeight: theme.lineHeight[size],
248
+ color
249
+ });
250
+ return {
251
+ body: {
252
+ gap: theme.spacing(3),
253
+ uni__dependencies: [0]
254
+ },
255
+ list: {
256
+ borderRadius: theme.borderRadius.lg,
257
+ borderWidth: 1,
258
+ borderColor: theme.colors["border-soft"],
259
+ overflow: "hidden",
260
+ uni__dependencies: [0]
261
+ },
262
+ item: {
263
+ minHeight: 48,
264
+ justifyContent: "center",
265
+ gap: 2,
266
+ paddingHorizontal: theme.spacing(4),
267
+ paddingVertical: theme.spacing(2.5),
268
+ uni__dependencies: [0]
269
+ },
270
+ divider: {
271
+ borderTopWidth: StyleSheet.hairlineWidth,
272
+ borderTopColor: theme.colors["border-soft"],
273
+ uni__dependencies: [0]
274
+ },
275
+ pressed: {
276
+ backgroundColor: theme.colors["tint-green"],
277
+ uni__dependencies: [0]
278
+ },
279
+ itemLabel: (danger, disabled) => ({
280
+ ...text("base", disabled ? theme.colors.faint : danger ? theme.colors.red : theme.colors.hi),
281
+ fontWeight: theme.fontWeight.medium,
282
+ uni__dependencies: [0]
283
+ }),
284
+ meta: text("sm", theme.colors.dim),
285
+ text: {
286
+ ...text("base", theme.colors.text),
287
+ lineHeight: theme.lineHeightRelaxed.base,
288
+ uni__dependencies: [0]
289
+ },
290
+ strong: {
291
+ fontWeight: theme.fontWeight.semibold,
292
+ color: theme.colors.hi,
293
+ uni__dependencies: [0]
294
+ },
295
+ mono: {
296
+ fontFamily: fontOf(theme.fontFamily.mono),
297
+ color: theme.colors.hi,
298
+ uni__dependencies: [0]
299
+ },
300
+ error: {
301
+ ...text("sm", theme.colors.red),
302
+ lineHeight: theme.lineHeightRelaxed.sm,
303
+ uni__dependencies: [0]
304
+ }
305
+ };
306
+ });
307
+ //#endregion
9
308
  //#region src/extensions/(frontend)/template/_components/AdvancedSessions.native.tsx
10
309
  /** The same reading of the status line as the cockpit card. */
11
310
  function statusTone(status) {
@@ -13,7 +312,18 @@ function statusTone(status) {
13
312
  if (status.startsWith("running")) return "running";
14
313
  return "quiet";
15
314
  }
16
- function SessionCard({ session, onOpen }) {
315
+ /** A 44 point icon target, as the cockpit's ghost icon buttons. */
316
+ function IconButton({ label, onPress, children }) {
317
+ return /* @__PURE__ */ jsx(Pressable, {
318
+ accessibilityRole: "button",
319
+ accessibilityLabel: label,
320
+ hitSlop: 6,
321
+ onPress,
322
+ style: ({ pressed }) => [styles.iconButton, pressed && styles.iconPressed],
323
+ children
324
+ });
325
+ }
326
+ function SessionCard({ session, onOpen, onMenu }) {
17
327
  const tone = statusTone(session.status);
18
328
  const name = session.name || "Untitled";
19
329
  return /* @__PURE__ */ jsxs(Pressable, {
@@ -29,38 +339,57 @@ function SessionCard({ session, onOpen }) {
29
339
  children: [
30
340
  /* @__PURE__ */ jsxs(View, {
31
341
  style: styles.cardHead,
32
- children: [session.profile ? /* @__PURE__ */ jsx(View, {
33
- style: styles.avatar,
34
- accessibilityLabel: session.profile.label,
35
- children: /* @__PURE__ */ jsx(Text, {
36
- style: styles.initials,
37
- children: session.profile.initials
38
- })
39
- }) : null, /* @__PURE__ */ jsxs(View, {
40
- style: styles.cardText,
41
- children: [/* @__PURE__ */ jsx(Text, {
42
- style: styles.name,
43
- numberOfLines: 2,
44
- children: name
45
- }), /* @__PURE__ */ jsxs(View, {
46
- style: styles.statusRow,
47
- children: [session.awaitingInput ? /* @__PURE__ */ jsx(AlertIcon, {
48
- size: 12,
49
- color: "magenta",
50
- accessibilityLabel: "Waiting for your input"
51
- }) : tone === "running" ? /* @__PURE__ */ jsx(Spinner, {
52
- size: "small",
53
- color: "yellow"
54
- }) : tone === "failed" ? /* @__PURE__ */ jsx(AlertIcon, {
55
- size: 12,
56
- color: "red"
57
- }) : null, /* @__PURE__ */ jsx(Text, {
58
- style: styles.status(tone),
59
- numberOfLines: 1,
60
- children: session.status
342
+ children: [
343
+ session.profile ? /* @__PURE__ */ jsx(View, {
344
+ style: styles.avatar,
345
+ accessibilityLabel: session.profile.label,
346
+ children: /* @__PURE__ */ jsx(Text, {
347
+ style: styles.initials,
348
+ children: session.profile.initials
349
+ })
350
+ }) : null,
351
+ /* @__PURE__ */ jsxs(View, {
352
+ style: styles.cardText,
353
+ children: [/* @__PURE__ */ jsx(Text, {
354
+ style: styles.name,
355
+ numberOfLines: 2,
356
+ children: name
357
+ }), /* @__PURE__ */ jsxs(View, {
358
+ style: styles.statusRow,
359
+ children: [
360
+ session.restarting ? /* @__PURE__ */ jsx(Spinner, {
361
+ size: "small",
362
+ color: "dim",
363
+ label: "Restarting"
364
+ }) : null,
365
+ session.awaitingInput ? /* @__PURE__ */ jsx(AlertIcon, {
366
+ size: 12,
367
+ color: "magenta",
368
+ accessibilityLabel: "Waiting for your input"
369
+ }) : tone === "running" ? /* @__PURE__ */ jsx(Spinner, {
370
+ size: "small",
371
+ color: "yellow"
372
+ }) : tone === "failed" ? /* @__PURE__ */ jsx(AlertIcon, {
373
+ size: 12,
374
+ color: "red"
375
+ }) : null,
376
+ /* @__PURE__ */ jsx(Text, {
377
+ style: styles.status(tone),
378
+ numberOfLines: 1,
379
+ children: session.status
380
+ })
381
+ ]
61
382
  })]
62
- })]
63
- })]
383
+ }),
384
+ /* @__PURE__ */ jsx(IconButton, {
385
+ label: `${name} actions`,
386
+ onPress: () => onMenu(session),
387
+ children: /* @__PURE__ */ jsx(KebabIcon, {
388
+ size: 16,
389
+ color: "dim"
390
+ })
391
+ })
392
+ ]
64
393
  }),
65
394
  session.git ? /* @__PURE__ */ jsxs(View, {
66
395
  style: [styles.branchRow, session.profile && styles.underAvatar],
@@ -80,6 +409,21 @@ function SessionCard({ session, onOpen }) {
80
409
  }) : null
81
410
  ]
82
411
  }) : null,
412
+ session.groups !== void 0 && session.groups.length > 0 ? /* @__PURE__ */ jsxs(View, {
413
+ style: [styles.groupsRow, session.profile && styles.underAvatar],
414
+ accessibilityLabel: "groups",
415
+ children: [/* @__PURE__ */ jsx(UsersIcon, {
416
+ size: 13,
417
+ color: "dim"
418
+ }), /* @__PURE__ */ jsx(View, {
419
+ style: styles.groups,
420
+ children: session.groups.map((group) => /* @__PURE__ */ jsx(Badge, {
421
+ tone: "magenta",
422
+ size: "xs",
423
+ children: group
424
+ }, group))
425
+ })]
426
+ }) : null,
83
427
  session.pendingSetups.map((setup) => /* @__PURE__ */ jsxs(View, {
84
428
  style: [styles.setup, session.profile && styles.underAvatar],
85
429
  children: [/* @__PURE__ */ jsxs(Text, {
@@ -103,29 +447,47 @@ function SessionCard({ session, onOpen }) {
103
447
  ]
104
448
  });
105
449
  }
106
- function WorkspaceGroup({ workspace, onOpen }) {
450
+ function WorkspaceGroup({ workspace, onOpen, actions, onSessionMenu, onWorkspaceMenu }) {
107
451
  return /* @__PURE__ */ jsxs(View, {
108
452
  style: styles.group,
109
453
  children: [
110
454
  /* @__PURE__ */ jsxs(View, {
111
455
  style: styles.groupHead,
112
456
  accessibilityRole: "header",
113
- children: [/* @__PURE__ */ jsx(FolderIcon, {
114
- size: 16,
115
- color: "dim"
116
- }), /* @__PURE__ */ jsxs(View, {
117
- style: styles.groupText,
118
- children: [/* @__PURE__ */ jsx(Text, {
119
- style: styles.groupName,
120
- numberOfLines: 1,
121
- children: workspace.name
122
- }), /* @__PURE__ */ jsx(Text, {
123
- style: styles.groupRoot,
124
- numberOfLines: 1,
125
- ellipsizeMode: "middle",
126
- children: workspace.root
127
- })]
128
- })]
457
+ children: [
458
+ /* @__PURE__ */ jsx(FolderIcon, {
459
+ size: 16,
460
+ color: "dim"
461
+ }),
462
+ /* @__PURE__ */ jsxs(View, {
463
+ style: styles.groupText,
464
+ children: [/* @__PURE__ */ jsx(Text, {
465
+ style: styles.groupName,
466
+ numberOfLines: 1,
467
+ children: workspace.name
468
+ }), /* @__PURE__ */ jsx(Text, {
469
+ style: styles.groupRoot,
470
+ numberOfLines: 1,
471
+ ellipsizeMode: "middle",
472
+ children: workspace.root
473
+ })]
474
+ }),
475
+ workspace.legacy ? null : /* @__PURE__ */ jsxs(Fragment, { children: [workspace.available ? /* @__PURE__ */ jsx(IconButton, {
476
+ label: `New session in ${workspace.name}`,
477
+ onPress: () => actions.createSession(workspace.id),
478
+ children: /* @__PURE__ */ jsx(PlusIcon, {
479
+ size: 18,
480
+ color: "dim"
481
+ })
482
+ }) : null, /* @__PURE__ */ jsx(IconButton, {
483
+ label: `${workspace.name} actions`,
484
+ onPress: () => onWorkspaceMenu(workspace),
485
+ children: /* @__PURE__ */ jsx(KebabIcon, {
486
+ size: 16,
487
+ color: "dim"
488
+ })
489
+ })] })
490
+ ]
129
491
  }),
130
492
  !workspace.available ? /* @__PURE__ */ jsx(Text, {
131
493
  style: styles.unavailable,
@@ -136,26 +498,45 @@ function WorkspaceGroup({ workspace, onOpen }) {
136
498
  children: "No sessions yet. Start or resume one."
137
499
  }) : workspace.sessions.map((session) => /* @__PURE__ */ jsx(SessionCard, {
138
500
  session,
139
- onOpen
501
+ onOpen,
502
+ onMenu: onSessionMenu
140
503
  }, session.id))
141
504
  ]
142
505
  });
143
506
  }
144
507
  /** The Advanced template's session list: the cockpit rail's workspace groups and cards, sized for a phone. */
145
- function AdvancedSessions({ workspaces, openSession }) {
508
+ function AdvancedSessions({ workspaces, openSession, actions }) {
509
+ const [sessionMenu, setSessionMenu] = useState(null);
510
+ const [workspaceMenu, setWorkspaceMenu] = useState(null);
146
511
  if (workspaces.length === 0) return /* @__PURE__ */ jsx(EmptyState, {
147
512
  title: "No sessions yet.",
148
513
  description: "Start one in Po on your computer."
149
514
  });
150
- return /* @__PURE__ */ jsx(ScrollView, {
151
- style: styles.screen,
152
- contentContainerStyle: styles.content,
153
- contentInsetAdjustmentBehavior: "automatic",
154
- children: workspaces.map((workspace) => /* @__PURE__ */ jsx(WorkspaceGroup, {
155
- workspace,
156
- onOpen: openSession
157
- }, workspace.id))
158
- });
515
+ const sessions = workspaces.flatMap((workspace) => workspace.sessions);
516
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
517
+ /* @__PURE__ */ jsx(ScrollView, {
518
+ style: styles.screen,
519
+ contentContainerStyle: styles.content,
520
+ contentInsetAdjustmentBehavior: "automatic",
521
+ children: workspaces.map((workspace) => /* @__PURE__ */ jsx(WorkspaceGroup, {
522
+ workspace,
523
+ onOpen: openSession,
524
+ actions,
525
+ onSessionMenu: (session) => setSessionMenu(session.id),
526
+ onWorkspaceMenu: (entry) => setWorkspaceMenu(entry.id)
527
+ }, workspace.id))
528
+ }),
529
+ /* @__PURE__ */ jsx(SessionMenuSheet, {
530
+ session: sessions.find((session) => session.id === sessionMenu) ?? null,
531
+ actions,
532
+ onClose: () => setSessionMenu(null)
533
+ }),
534
+ /* @__PURE__ */ jsx(WorkspaceMenuSheet, {
535
+ workspace: workspaces.find((workspace) => workspace.id === workspaceMenu) ?? null,
536
+ actions,
537
+ onClose: () => setWorkspaceMenu(null)
538
+ })
539
+ ] });
159
540
  }
160
541
  const styles = StyleSheet.create((theme) => {
161
542
  const sans = fontOf(theme.fontFamily.sans);
@@ -234,6 +615,17 @@ const styles = StyleSheet.create((theme) => {
234
615
  marginLeft: theme.spacing(5),
235
616
  uni__dependencies: [0]
236
617
  },
618
+ iconButton: {
619
+ width: 36,
620
+ height: 36,
621
+ borderRadius: 18,
622
+ alignItems: "center",
623
+ justifyContent: "center"
624
+ },
625
+ iconPressed: {
626
+ backgroundColor: theme.colors.panel,
627
+ uni__dependencies: [0]
628
+ },
237
629
  cardHead: {
238
630
  flexDirection: "row",
239
631
  alignItems: "flex-start",
@@ -293,6 +685,19 @@ const styles = StyleSheet.create((theme) => {
293
685
  uni__dependencies: [0]
294
686
  },
295
687
  modified: text("sm", theme.colors.yellow),
688
+ groupsRow: {
689
+ flexDirection: "row",
690
+ alignItems: "flex-start",
691
+ gap: theme.spacing(1.5),
692
+ uni__dependencies: [0]
693
+ },
694
+ groups: {
695
+ flex: 1,
696
+ flexDirection: "row",
697
+ flexWrap: "wrap",
698
+ gap: theme.spacing(1),
699
+ uni__dependencies: [0]
700
+ },
296
701
  setup: {
297
702
  gap: theme.spacing(.5),
298
703
  uni__dependencies: [0]