@webappwiz/arbor 0.0.30 → 0.0.32

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.
Files changed (120) hide show
  1. package/README.md +2 -2
  2. package/add.d.ts +23 -0
  3. package/age.d.ts +2 -0
  4. package/arbor.d.ts +11 -0
  5. package/attachments.d.ts +36 -0
  6. package/claim.d.ts +11 -0
  7. package/config.d.ts +55 -0
  8. package/config.js +7 -0
  9. package/dev/assets.d.ts +11 -0
  10. package/dev.d.ts +48 -0
  11. package/escalate.d.ts +28 -0
  12. package/exit.d.ts +42 -0
  13. package/git.d.ts +82 -0
  14. package/index.d.ts +2 -0
  15. package/index.js +4763 -0
  16. package/journal.d.ts +29 -0
  17. package/list.d.ts +18 -0
  18. package/load-config.d.ts +15 -0
  19. package/log.d.ts +14 -0
  20. package/merge.d.ts +24 -0
  21. package/package.json +15 -32
  22. package/path.d.ts +13 -0
  23. package/plan.d.ts +83 -0
  24. package/remove.d.ts +19 -0
  25. package/repository.d.ts +25 -0
  26. package/retry.d.ts +17 -0
  27. package/shell.d.ts +17 -0
  28. package/show.d.ts +53 -0
  29. package/snapshot.d.ts +36 -0
  30. package/table.d.ts +5 -0
  31. package/todo.d.ts +202 -0
  32. package/todos.d.ts +75 -0
  33. package/wait.d.ts +22 -0
  34. package/worktree-service.d.ts +51 -0
  35. package/worktree.d.ts +95 -0
  36. package/AGENTS.md +0 -7
  37. package/add.test.ts +0 -125
  38. package/add.ts +0 -192
  39. package/age.ts +0 -11
  40. package/arbor.test.ts +0 -145
  41. package/arbor.ts +0 -429
  42. package/assets.d.ts +0 -9
  43. package/attachments.ts +0 -87
  44. package/build.ts +0 -98
  45. package/claim.test.ts +0 -89
  46. package/claim.ts +0 -73
  47. package/components.json +0 -21
  48. package/config.ts +0 -58
  49. package/dev/api.ts +0 -120
  50. package/dev/app.test.tsx +0 -645
  51. package/dev/app.tsx +0 -80
  52. package/dev/assets.ts +0 -16
  53. package/dev/build/main.txt +0 -68
  54. package/dev/build/shell.txt +0 -21
  55. package/dev/build/styles.txt +0 -2263
  56. package/dev/components/ui/badge.tsx +0 -51
  57. package/dev/components/ui/button.tsx +0 -57
  58. package/dev/components/ui/dialog.tsx +0 -154
  59. package/dev/components/ui/empty.tsx +0 -100
  60. package/dev/components/ui/input-group.tsx +0 -155
  61. package/dev/components/ui/input.tsx +0 -19
  62. package/dev/components/ui/progress.tsx +0 -80
  63. package/dev/components/ui/textarea.tsx +0 -17
  64. package/dev/components/ui/toast.tsx +0 -227
  65. package/dev/feed.ts +0 -69
  66. package/dev/files.tsx +0 -191
  67. package/dev/index.html +0 -21
  68. package/dev/lib/utils.ts +0 -7
  69. package/dev/main.tsx +0 -22
  70. package/dev/markdown.test.tsx +0 -133
  71. package/dev/markdown.tsx +0 -124
  72. package/dev/mentions.tsx +0 -319
  73. package/dev/shadcn.css +0 -649
  74. package/dev/styles.css +0 -107
  75. package/dev/tags.tsx +0 -44
  76. package/dev/tasks.tsx +0 -151
  77. package/dev/todos.tsx +0 -759
  78. package/dev.test.ts +0 -439
  79. package/dev.ts +0 -386
  80. package/e2e.test.ts +0 -256
  81. package/escalate.test.ts +0 -76
  82. package/escalate.ts +0 -112
  83. package/exit.test.ts +0 -71
  84. package/exit.ts +0 -74
  85. package/git.ts +0 -294
  86. package/index.ts +0 -9
  87. package/journal.ts +0 -89
  88. package/list.test.ts +0 -82
  89. package/list.ts +0 -137
  90. package/load-config.test.ts +0 -121
  91. package/load-config.ts +0 -62
  92. package/log.test.ts +0 -65
  93. package/log.ts +0 -40
  94. package/merge.test.ts +0 -332
  95. package/merge.ts +0 -283
  96. package/path.test.ts +0 -35
  97. package/path.ts +0 -38
  98. package/plan.test.ts +0 -318
  99. package/plan.ts +0 -302
  100. package/progress.test.ts +0 -54
  101. package/progress.ts +0 -31
  102. package/remove.test.ts +0 -68
  103. package/remove.ts +0 -88
  104. package/repository.ts +0 -83
  105. package/retry.test.ts +0 -43
  106. package/retry.ts +0 -48
  107. package/shell.ts +0 -44
  108. package/show.test.ts +0 -91
  109. package/show.ts +0 -151
  110. package/snapshot.test.ts +0 -33
  111. package/snapshot.ts +0 -84
  112. package/table.ts +0 -20
  113. package/testing.ts +0 -229
  114. package/todo.test.ts +0 -490
  115. package/todo.ts +0 -834
  116. package/wait.test.ts +0 -61
  117. package/wait.ts +0 -77
  118. package/worktree-service.test.ts +0 -158
  119. package/worktree-service.ts +0 -193
  120. package/worktree.ts +0 -239
package/dev/styles.css DELETED
@@ -1,107 +0,0 @@
1
- @import "tailwindcss";
2
- @import "tw-animate-css";
3
- @import "./shadcn.css";
4
-
5
- /* Tailwind only emits the utilities it can actually see, and its automatic
6
- detection does not find them from here. Every file holding a class the page
7
- renders has to be listed: one that nobody lists comes out of the compiler as
8
- nothing at all. */
9
- @source "./app.tsx";
10
- @source "./todos.tsx";
11
- @source "./tasks.tsx";
12
- @source "./markdown.tsx";
13
- @source "./files.tsx";
14
- @source "./mentions.tsx";
15
- @source "./tags.tsx";
16
- @source "./components/ui";
17
-
18
- @custom-variant dark (&:is(.dark *));
19
-
20
- /* shadcn's neutral theme. The page follows whatever the device it is opened
21
- on is set to, so `dark` is toggled by main.tsx off prefers-color-scheme. */
22
- :root {
23
- color-scheme: light;
24
- --radius: 0.625rem;
25
- --background: oklch(1 0 0);
26
- --foreground: oklch(0.145 0 0);
27
- --card: oklch(1 0 0);
28
- --card-foreground: oklch(0.145 0 0);
29
- --popover: oklch(1 0 0);
30
- --popover-foreground: oklch(0.145 0 0);
31
- --primary: oklch(0.205 0 0);
32
- --primary-foreground: oklch(0.985 0 0);
33
- --secondary: oklch(0.97 0 0);
34
- --secondary-foreground: oklch(0.205 0 0);
35
- --muted: oklch(0.97 0 0);
36
- --muted-foreground: oklch(0.556 0 0);
37
- --accent: oklch(0.97 0 0);
38
- --accent-foreground: oklch(0.205 0 0);
39
- --destructive: oklch(0.577 0.245 27.325);
40
- --success: oklch(0.627 0.17 149.2);
41
- --warning: oklch(0.666 0.157 58.3);
42
- --border: oklch(0.922 0 0);
43
- --input: oklch(0.922 0 0);
44
- --ring: oklch(0.708 0 0);
45
- }
46
-
47
- .dark {
48
- color-scheme: dark;
49
- --background: oklch(0.145 0 0);
50
- --foreground: oklch(0.985 0 0);
51
- --card: oklch(0.205 0 0);
52
- --card-foreground: oklch(0.985 0 0);
53
- --popover: oklch(0.205 0 0);
54
- --popover-foreground: oklch(0.985 0 0);
55
- --primary: oklch(0.922 0 0);
56
- --primary-foreground: oklch(0.205 0 0);
57
- --secondary: oklch(0.269 0 0);
58
- --secondary-foreground: oklch(0.985 0 0);
59
- --muted: oklch(0.269 0 0);
60
- --muted-foreground: oklch(0.708 0 0);
61
- --accent: oklch(0.269 0 0);
62
- --accent-foreground: oklch(0.985 0 0);
63
- --destructive: oklch(0.704 0.191 22.216);
64
- --success: oklch(0.723 0.192 149.6);
65
- --warning: oklch(0.769 0.165 70.1);
66
- --border: oklch(1 0 0 / 10%);
67
- --input: oklch(1 0 0 / 15%);
68
- --ring: oklch(0.556 0 0);
69
- }
70
-
71
- @theme inline {
72
- --color-background: var(--background);
73
- --color-foreground: var(--foreground);
74
- --color-card: var(--card);
75
- --color-card-foreground: var(--card-foreground);
76
- --color-popover: var(--popover);
77
- --color-popover-foreground: var(--popover-foreground);
78
- --color-primary: var(--primary);
79
- --color-primary-foreground: var(--primary-foreground);
80
- --color-secondary: var(--secondary);
81
- --color-secondary-foreground: var(--secondary-foreground);
82
- --color-muted: var(--muted);
83
- --color-muted-foreground: var(--muted-foreground);
84
- --color-accent: var(--accent);
85
- --color-accent-foreground: var(--accent-foreground);
86
- --color-destructive: var(--destructive);
87
- --color-success: var(--success);
88
- --color-warning: var(--warning);
89
- --color-border: var(--border);
90
- --color-input: var(--input);
91
- --color-ring: var(--ring);
92
- --radius-sm: calc(var(--radius) - 4px);
93
- --radius-md: calc(var(--radius) - 2px);
94
- --radius-lg: var(--radius);
95
- --radius-xl: calc(var(--radius) + 4px);
96
- }
97
-
98
- @layer base {
99
- * {
100
- @apply border-border outline-ring/50;
101
- }
102
- /* A long URL or path breaks rather than pushing the page wider; lines
103
- meant to stay on one line truncate instead. */
104
- body {
105
- @apply bg-background text-foreground antialiased wrap-anywhere;
106
- }
107
- }
package/dev/tags.tsx DELETED
@@ -1,44 +0,0 @@
1
- import { TagIcon } from "lucide-react";
2
- import type { JSX } from "react";
3
- import { cn } from "#dev/lib/utils.ts";
4
-
5
- /**
6
- * A row of tags over the list, the way a mail client filters by label: All,
7
- * then every tag a todo has. Tapping one shows only its todos.
8
- */
9
- export function TagFilter({
10
- tags,
11
- selected,
12
- onSelect,
13
- }: {
14
- tags: string[];
15
- selected: string | null;
16
- onSelect: (tag: string | null) => void;
17
- }): JSX.Element {
18
- const chip = (label: string, value: string | null) => (
19
- <button
20
- key={label}
21
- type="button"
22
- aria-pressed={selected === value}
23
- onClick={() => onSelect(value)}
24
- className={cn(
25
- "inline-flex cursor-pointer items-center gap-1 rounded-full border px-2.5 py-0.5 text-xs outline-none focus-visible:ring-2 focus-visible:ring-ring",
26
- selected === value
27
- ? "border-primary bg-primary text-primary-foreground"
28
- : "text-muted-foreground hover:bg-muted hover:text-foreground",
29
- )}
30
- >
31
- {value !== null && <TagIcon aria-hidden className="size-3" />}
32
- {label}
33
- </button>
34
- );
35
- return (
36
- <fieldset
37
- aria-label="filter by tag"
38
- className="m-0 flex flex-wrap gap-1.5 border-0 p-0"
39
- >
40
- {chip("All", null)}
41
- {tags.map((tag) => chip(tag, tag))}
42
- </fieldset>
43
- );
44
- }
package/dev/tasks.tsx DELETED
@@ -1,151 +0,0 @@
1
- import { type JSX, type ReactNode, useState } from "react";
2
- import { Badge } from "#dev/components/ui/badge.tsx";
3
- import {
4
- Dialog,
5
- DialogContent,
6
- DialogDescription,
7
- DialogHeader,
8
- DialogTitle,
9
- } from "#dev/components/ui/dialog.tsx";
10
- import { Progress as Bar } from "#dev/components/ui/progress.tsx";
11
- import { type Progress as Counted, progress } from "../progress";
12
- import type { Details } from "../show";
13
- import { Markdown } from "./markdown";
14
-
15
- /** A tree in one of these needs fixing rather than driving. */
16
- const BROKEN = new Set(["orphaned", "stray", "unrecorded", "unknown"]);
17
-
18
- /**
19
- * Every task in a line: its name, a bar for how far along its plan is, and a status only
20
- * when the status is news. The rest (branch, paths, the whole plan) waits
21
- * behind a tap.
22
- */
23
- export function Tasks({ tasks }: { tasks: Details[] }): JSX.Element {
24
- const [opened, setOpened] = useState<Details | null>(null);
25
-
26
- // One line, not a big empty state: the todos below it are the page then.
27
- if (tasks.length === 0) {
28
- return (
29
- <p className="text-muted-foreground text-sm">
30
- No tasks: <code>arbor add &lt;task&gt;</code> starts one.
31
- </p>
32
- );
33
- }
34
-
35
- return (
36
- <>
37
- <ul className="flex flex-col">
38
- {tasks.map((task) => (
39
- <li key={task.task}>
40
- <button
41
- type="button"
42
- onClick={() => setOpened(task)}
43
- className="-mx-2 flex w-[calc(100%+1rem)] items-center gap-3 rounded-lg px-2 py-2 text-left hover:bg-muted"
44
- >
45
- <span className="min-w-0 flex-1 truncate text-sm">
46
- {task.task}
47
- </span>
48
- <Status status={task.status} />
49
- <PlanProgress plan={task.plan} />
50
- </button>
51
- </li>
52
- ))}
53
- </ul>
54
- <Dialog
55
- open={opened !== null}
56
- onOpenChange={(open) => {
57
- if (!open) {
58
- setOpened(null);
59
- }
60
- }}
61
- >
62
- {opened && <Task task={opened} />}
63
- </Dialog>
64
- </>
65
- );
66
- }
67
-
68
- /** Working and merging are the normal case, so they say nothing. */
69
- function Status({ status }: { status: string }): JSX.Element | null {
70
- if (status === "escalated") {
71
- return <Badge variant="secondary">escalated</Badge>;
72
- }
73
- if (BROKEN.has(status)) {
74
- return <Badge variant="destructive">{status}</Badge>;
75
- }
76
- return null;
77
- }
78
-
79
- function PlanProgress({ plan }: { plan: string | null }): JSX.Element | null {
80
- const counted = plan === null ? null : progress(plan);
81
- return counted && <Progress {...counted} />;
82
- }
83
-
84
- /** A bar and its count, the end of a task's or a tag's row. */
85
- export function Progress({ done, total }: Counted): JSX.Element {
86
- return (
87
- <span className="flex w-28 shrink-0 items-center gap-2">
88
- <Bar value={done} max={total} aria-label="progress" className="flex-1" />
89
- <span className="w-8 text-right text-muted-foreground text-xs tabular-nums">
90
- {done}/{total}
91
- </span>
92
- </span>
93
- );
94
- }
95
-
96
- /** One task, all of it, in a dialog over the task list or a todo that names it. */
97
- export function Task({ task }: { task: Details }): JSX.Element {
98
- const fields: [string, ReactNode][] = [
99
- ["status", task.status],
100
- ["branch", task.branch],
101
- ["base", task.base],
102
- ["worktree", task.worktree],
103
- ["lease", task.lease],
104
- ["commits", String(task.ahead ?? "?")],
105
-
106
- [
107
- "diff",
108
- task.added === null ? (
109
- "?"
110
- ) : (
111
- <span key="diff" className="tabular-nums">
112
- <span className="text-success">+{task.added}</span>{" "}
113
- <span className="text-destructive">-{task.removed ?? 0}</span>
114
- </span>
115
- ),
116
- ],
117
- ["age", task.age ?? "?"],
118
- ];
119
- return (
120
- <DialogContent className="max-h-[85dvh] grid-cols-[minmax(0,1fr)] overflow-y-auto sm:max-w-xl">
121
- <DialogHeader>
122
- <DialogTitle>{task.task}</DialogTitle>
123
- <DialogDescription>{task.escalation ?? task.status}</DialogDescription>
124
- </DialogHeader>
125
- <div className="flex min-w-0 flex-col gap-6 text-sm">
126
- <dl className="grid grid-cols-[max-content_minmax(0,1fr)] gap-x-4 gap-y-1">
127
- {fields.map(([name, value]) => (
128
- <div key={name} className="contents">
129
- <dt className="text-muted-foreground">{name}</dt>
130
- <dd className="truncate">{value}</dd>
131
- </div>
132
- ))}
133
- </dl>
134
- {task.plan === null ? (
135
- <p className="text-muted-foreground">
136
- No ARBOR.md: whoever picks this up starts from the diff.
137
- </p>
138
- ) : (
139
- <Markdown text={task.plan.replace(/^\s*#\s[^\n]*/, "")} />
140
- )}
141
- {task.planProblems.length > 0 && (
142
- <ul className="flex flex-col gap-1 text-muted-foreground text-xs">
143
- {task.planProblems.map((problem) => (
144
- <li key={problem}>{problem}</li>
145
- ))}
146
- </ul>
147
- )}
148
- </div>
149
- </DialogContent>
150
- );
151
- }