@cat-factory/app 0.237.0 → 0.237.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.
@@ -1,76 +0,0 @@
1
- import type { TaskSourceKind, TaskSourceState } from '~/types/domain'
2
-
3
- /**
4
- * Pure tracker-selection logic shared by every surface that picks a task source: which
5
- * tracker is selected, and what its menu offers. Kept out of the components so their
6
- * `computed`s and the unit spec call the same code.
7
- *
8
- * The menu is deliberately two-tier — pick an already-offered tracker, or go and add
9
- * one — because a tracker-picking surface is exactly where a user discovers the tracker
10
- * they want is missing, and sending them off to the Integrations hub loses whatever they
11
- * had in progress. Today `<ContextIssuePicker>` (attach a context issue) and
12
- * `<BugHuntModal>` (scan a board for bugs) both render it.
13
- */
14
-
15
- /** One row of a tracker menu. */
16
- export type SourceChoice =
17
- /** An offered tracker the surface can use right now. */
18
- | { action: 'select'; source: TaskSourceKind; label: string; icon: string; active: boolean }
19
- /**
20
- * A configured tracker that is not offered yet, so it can be added from here. `connect`
21
- * has no credential/App behind it; `enable` is connected but toggled off for the
22
- * workspace. Both open the same connect modal, which serves either case — only the
23
- * wording differs, so the user isn't told to "connect" something already connected.
24
- */
25
- | { action: 'connect' | 'enable'; source: TaskSourceKind; label: string; icon: string }
26
-
27
- /**
28
- * A tracker menu, as non-empty groups (the offered trackers, then the ones the user could
29
- * add). Empty groups are dropped so the menu never renders a stray separator.
30
- */
31
- export function buildSourceChoices(
32
- sources: TaskSourceState[],
33
- selected: TaskSourceKind | undefined,
34
- ): SourceChoice[][] {
35
- const offered: SourceChoice[] = []
36
- const addable: SourceChoice[] = []
37
- for (const s of sources) {
38
- if (s.available && s.enabled) {
39
- offered.push({
40
- action: 'select',
41
- source: s.source,
42
- label: s.label,
43
- icon: s.icon,
44
- active: s.source === selected,
45
- })
46
- } else {
47
- addable.push({
48
- action: s.available ? 'enable' : 'connect',
49
- source: s.source,
50
- label: s.label,
51
- icon: s.icon,
52
- })
53
- }
54
- }
55
- return [offered, addable].filter((group) => group.length > 0)
56
- }
57
-
58
- /**
59
- * The source a surface should hold once the offered set changes — after a connect, a
60
- * disconnect, or the per-workspace toggle flipping elsewhere.
61
- *
62
- * `awaiting` is the tracker the user just left to connect: the moment it becomes offered
63
- * it wins, so they land back on the source they went to add rather than on whatever was
64
- * selected before. Otherwise a still-offered selection is kept, and a selection that
65
- * stopped being offered falls back to the first one (reading a tracker the workspace no
66
- * longer offers only yields errors).
67
- */
68
- export function reconcileSource(
69
- offered: TaskSourceKind[],
70
- selected: TaskSourceKind | undefined,
71
- awaiting: TaskSourceKind | null,
72
- ): TaskSourceKind | undefined {
73
- if (awaiting && offered.includes(awaiting)) return awaiting
74
- if (selected && offered.includes(selected)) return selected
75
- return offered[0]
76
- }