@jinion/cli 0.0.0-stage → 0.3.491

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 (171) hide show
  1. package/bin/jinion.js +4 -0
  2. package/dist/app/activity.js +50 -0
  3. package/dist/app/activity.js.map +1 -0
  4. package/dist/app/announcements.js +21 -0
  5. package/dist/app/announcements.js.map +1 -0
  6. package/dist/app/api.js +26 -0
  7. package/dist/app/api.js.map +1 -0
  8. package/dist/app/app.js +91 -0
  9. package/dist/app/app.js.map +1 -0
  10. package/dist/app/aside.js +52 -0
  11. package/dist/app/aside.js.map +1 -0
  12. package/dist/app/dialogs.js +43 -0
  13. package/dist/app/dialogs.js.map +1 -0
  14. package/dist/app/keys.js +79 -0
  15. package/dist/app/keys.js.map +1 -0
  16. package/dist/app/prompt-area.js +56 -0
  17. package/dist/app/prompt-area.js.map +1 -0
  18. package/dist/app/shortcuts.js +31 -0
  19. package/dist/app/shortcuts.js.map +1 -0
  20. package/dist/app/sidebar.js +50 -0
  21. package/dist/app/sidebar.js.map +1 -0
  22. package/dist/app/status-line.js +23 -0
  23. package/dist/app/status-line.js.map +1 -0
  24. package/dist/app/task-line.js +19 -0
  25. package/dist/app/task-line.js.map +1 -0
  26. package/dist/app/use-screen.js +24 -0
  27. package/dist/app/use-screen.js.map +1 -0
  28. package/dist/app/views.js +62 -0
  29. package/dist/app/views.js.map +1 -0
  30. package/dist/main.js +122 -0
  31. package/dist/main.js.map +1 -0
  32. package/dist/panels/account/account-picker.js +118 -0
  33. package/dist/panels/account/account-picker.js.map +1 -0
  34. package/dist/panels/account/describe.js +14 -0
  35. package/dist/panels/account/describe.js.map +1 -0
  36. package/dist/panels/account/sign-in-view.js +8 -0
  37. package/dist/panels/account/sign-in-view.js.map +1 -0
  38. package/dist/panels/account/use-sign-in.js +46 -0
  39. package/dist/panels/account/use-sign-in.js.map +1 -0
  40. package/dist/panels/context.js +55 -0
  41. package/dist/panels/context.js.map +1 -0
  42. package/dist/panels/diff/change-list.js +48 -0
  43. package/dist/panels/diff/change-list.js.map +1 -0
  44. package/dist/panels/diff/current-view.js +47 -0
  45. package/dist/panels/diff/current-view.js.map +1 -0
  46. package/dist/panels/diff/diff-panel.js +22 -0
  47. package/dist/panels/diff/diff-panel.js.map +1 -0
  48. package/dist/panels/diff/file-diff.js +19 -0
  49. package/dist/panels/diff/file-diff.js.map +1 -0
  50. package/dist/panels/diff/views.js +29 -0
  51. package/dist/panels/diff/views.js.map +1 -0
  52. package/dist/panels/feedback.js +67 -0
  53. package/dist/panels/feedback.js.map +1 -0
  54. package/dist/panels/help.js +79 -0
  55. package/dist/panels/help.js.map +1 -0
  56. package/dist/panels/mcp.js +129 -0
  57. package/dist/panels/mcp.js.map +1 -0
  58. package/dist/panels/memory.js +55 -0
  59. package/dist/panels/memory.js.map +1 -0
  60. package/dist/panels/mode.js +36 -0
  61. package/dist/panels/mode.js.map +1 -0
  62. package/dist/panels/model.js +20 -0
  63. package/dist/panels/model.js.map +1 -0
  64. package/dist/panels/onboarding/onboarding-panel.js +56 -0
  65. package/dist/panels/onboarding/onboarding-panel.js.map +1 -0
  66. package/dist/panels/onboarding/use-onboarding.js +65 -0
  67. package/dist/panels/onboarding/use-onboarding.js.map +1 -0
  68. package/dist/panels/profile.js +31 -0
  69. package/dist/panels/profile.js.map +1 -0
  70. package/dist/panels/resume.js +52 -0
  71. package/dist/panels/resume.js.map +1 -0
  72. package/dist/panels/rewind/changes.js +20 -0
  73. package/dist/panels/rewind/changes.js.map +1 -0
  74. package/dist/panels/rewind/rewind-panel.js +93 -0
  75. package/dist/panels/rewind/rewind-panel.js.map +1 -0
  76. package/dist/panels/sign-in/sign-in-panel.js +56 -0
  77. package/dist/panels/sign-in/sign-in-panel.js.map +1 -0
  78. package/dist/panels/sign-in/use-jinion-sign-in.js +69 -0
  79. package/dist/panels/sign-in/use-jinion-sign-in.js.map +1 -0
  80. package/dist/panels/statusline.js +94 -0
  81. package/dist/panels/statusline.js.map +1 -0
  82. package/dist/panels/tasks/output.js +23 -0
  83. package/dist/panels/tasks/output.js.map +1 -0
  84. package/dist/panels/tasks/task-output.js +29 -0
  85. package/dist/panels/tasks/task-output.js.map +1 -0
  86. package/dist/panels/tasks/tasks-panel.js +75 -0
  87. package/dist/panels/tasks/tasks-panel.js.map +1 -0
  88. package/dist/panels/terminal-setup.js +41 -0
  89. package/dist/panels/terminal-setup.js.map +1 -0
  90. package/dist/panels/usage/section.js +16 -0
  91. package/dist/panels/usage/section.js.map +1 -0
  92. package/dist/panels/usage/stats-view.js +52 -0
  93. package/dist/panels/usage/stats-view.js.map +1 -0
  94. package/dist/panels/usage/usage-panel.js +68 -0
  95. package/dist/panels/usage/usage-panel.js.map +1 -0
  96. package/dist/panels/usage/usage-view.js +51 -0
  97. package/dist/panels/usage/usage-view.js.map +1 -0
  98. package/dist/prompt/attachments.js +91 -0
  99. package/dist/prompt/attachments.js.map +1 -0
  100. package/dist/prompt/draft.js +24 -0
  101. package/dist/prompt/draft.js.map +1 -0
  102. package/dist/prompt/images.js +84 -0
  103. package/dist/prompt/images.js.map +1 -0
  104. package/dist/prompt/pasted-path.js +19 -0
  105. package/dist/prompt/pasted-path.js.map +1 -0
  106. package/dist/prompt/use-prompt.js +62 -0
  107. package/dist/prompt/use-prompt.js.map +1 -0
  108. package/dist/serve.js +38 -0
  109. package/dist/serve.js.map +1 -0
  110. package/dist/state/session.js +91 -0
  111. package/dist/state/session.js.map +1 -0
  112. package/dist/status/data.js +39 -0
  113. package/dist/status/data.js.map +1 -0
  114. package/dist/status/git.js +18 -0
  115. package/dist/status/git.js.map +1 -0
  116. package/dist/status/items.js +8 -0
  117. package/dist/status/items.js.map +1 -0
  118. package/dist/status/line.js +25 -0
  119. package/dist/status/line.js.map +1 -0
  120. package/dist/status/saved.js +8 -0
  121. package/dist/status/saved.js.map +1 -0
  122. package/dist/status/segment.js +2 -0
  123. package/dist/status/segment.js.map +1 -0
  124. package/dist/status/segments/conversation.js +71 -0
  125. package/dist/status/segments/conversation.js.map +1 -0
  126. package/dist/status/segments/git.js +33 -0
  127. package/dist/status/segments/git.js.map +1 -0
  128. package/dist/status/segments/identity.js +71 -0
  129. package/dist/status/segments/identity.js.map +1 -0
  130. package/dist/status/segments/index.js +27 -0
  131. package/dist/status/segments/index.js.map +1 -0
  132. package/dist/status/segments/usage.js +61 -0
  133. package/dist/status/segments/usage.js.map +1 -0
  134. package/dist/terminal/apple-terminal.js +68 -0
  135. package/dist/terminal/apple-terminal.js.map +1 -0
  136. package/dist/ui/banner.js +24 -0
  137. package/dist/ui/banner.js.map +1 -0
  138. package/dist/ui/entries/changes-card.js +27 -0
  139. package/dist/ui/entries/changes-card.js.map +1 -0
  140. package/dist/ui/entries/entry-view.js +82 -0
  141. package/dist/ui/entries/entry-view.js.map +1 -0
  142. package/dist/ui/entries/status-entries.js +33 -0
  143. package/dist/ui/entries/status-entries.js.map +1 -0
  144. package/dist/ui/entries/tools/agent-view.js +39 -0
  145. package/dist/ui/entries/tools/agent-view.js.map +1 -0
  146. package/dist/ui/entries/tools/mcp-view.js +10 -0
  147. package/dist/ui/entries/tools/mcp-view.js.map +1 -0
  148. package/dist/ui/entries/tools/result-preview.js +19 -0
  149. package/dist/ui/entries/tools/result-preview.js.map +1 -0
  150. package/dist/ui/entries/tools/search.js +42 -0
  151. package/dist/ui/entries/tools/search.js.map +1 -0
  152. package/dist/ui/entries/tools/shell-footer.js +36 -0
  153. package/dist/ui/entries/tools/shell-footer.js.map +1 -0
  154. package/dist/ui/entries/tools/tool-view.js +47 -0
  155. package/dist/ui/entries/tools/tool-view.js.map +1 -0
  156. package/dist/ui/entries/tools/web.js +41 -0
  157. package/dist/ui/entries/tools/web.js.map +1 -0
  158. package/dist/ui/modes.js +13 -0
  159. package/dist/ui/modes.js.map +1 -0
  160. package/dist/ui/task-marks.js +7 -0
  161. package/dist/ui/task-marks.js.map +1 -0
  162. package/dist/ui/use-async.js +17 -0
  163. package/dist/ui/use-async.js.map +1 -0
  164. package/dist/ui/use-pager.js +25 -0
  165. package/dist/ui/use-pager.js.map +1 -0
  166. package/dist/ui/use-project-files.js +18 -0
  167. package/dist/ui/use-project-files.js.map +1 -0
  168. package/dist/ui/use-workdir.js +9 -0
  169. package/dist/ui/use-workdir.js.map +1 -0
  170. package/package.json +34 -3
  171. package/README.md +0 -3
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, ChoiceList, Panel, PromptInput, Text, useChoiceList, useInput, useTheme } from '@jinion/tui';
3
+ import { useApi } from '../../app/api.js';
4
+ import { useOnboarding } from './use-onboarding.js';
5
+ /** In the prompt's place once someone signed in, until their account is active. */
6
+ export function OnboardingPanel() {
7
+ const api = useApi();
8
+ const theme = useTheme();
9
+ const onboarding = useOnboarding();
10
+ const { questions, step } = onboarding;
11
+ const question = step.kind === 'question' ? questions?.[step.index] : undefined;
12
+ useInput((input, key) => {
13
+ if (key.ctrl && input === 'c')
14
+ return api.quit();
15
+ if (key.escape)
16
+ onboarding.back();
17
+ });
18
+ if (step.kind === 'code' || !questions) {
19
+ return (_jsxs(Panel, { title: "You\u2019re almost in", header: _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.muted, children: "Jinion is invite-only during the beta. Enter the invite code you were given." }), _jsx(Text, { color: theme.muted, children: "While you use it, Jinion sends how your turns go and the errors it hits, never your conversations. /telemetry turns this off." })] }), hints: [
20
+ ['Enter', 'continue'],
21
+ ['Ctrl+C', 'quit'],
22
+ ], children: [step.kind === 'code' && step.problem && _jsx(Text, { color: theme.error, children: step.problem }), step.kind === 'code' && step.checking ? (_jsx(Text, { color: theme.muted, children: "Checking your invite\u2026" })) : (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "invite code: " }), _jsx(PromptInput, { value: step.kind === 'code' ? step.code : '', onChange: onboarding.typeCode, onSubmit: onboarding.checkCode, placeholder: "JIN-XXXX-XXXX", paddingX: 0 })] }))] }));
23
+ }
24
+ if (step.kind === 'finishing' || !question) {
25
+ return (_jsx(Panel, { title: "You\u2019re almost in", children: _jsx(Text, { color: theme.muted, children: "Setting up your account\u2026" }) }));
26
+ }
27
+ return (_jsxs(Panel, { title: "A few questions", subtitle: `${step.index + 1} of ${questions.length}`, header: _jsx(Text, { color: theme.muted, children: "They help us make Jinion better for you." }), hints: hintsOf(question), children: [_jsxs(Text, { bold: true, children: [question.prompt, !question.required && _jsx(Text, { color: theme.muted, children: " (optional)" })] }), question.hint && _jsx(Text, { color: theme.muted, children: question.hint }), step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: question.kind === 'text' ? (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: '> ' }), _jsx(PromptInput, { value: String(onboarding.answers[question.id] ?? ''), onChange: (value) => onboarding.typeAnswer(question, value), onSubmit: (value) => onboarding.answer(question, step.index, value.trim()), placeholder: question.required ? 'Your answer' : 'Your answer, or Enter to skip', paddingX: 0 })] })) : (_jsx(Options, { question: question, chosen: onboarding.answers[question.id], onAnswer: (value) => onboarding.answer(question, step.index, value) }, question.id)) })] }));
28
+ }
29
+ /** One of the options for `choice`, any of them for `choices`; keyed by its question, so each starts afresh. */
30
+ function Options({ question, chosen, onAnswer }) {
31
+ const multiple = question.kind === 'choices';
32
+ const list = useChoiceList({
33
+ keys: question.options,
34
+ mode: multiple ? 'multiple' : 'single',
35
+ initialFocus: typeof chosen === 'string' ? chosen : undefined,
36
+ initialChecked: Array.isArray(chosen) ? chosen : [],
37
+ onCancel: () => { },
38
+ onSubmit: (picked) => onAnswer(multiple ? picked : (picked[0] ?? '')),
39
+ });
40
+ return _jsx(ChoiceList, { list: list, limit: question.options.length, choices: question.options.map((option) => ({ key: option, label: option })) });
41
+ }
42
+ function hintsOf(question) {
43
+ if (question.kind === 'choices') {
44
+ return [
45
+ ['Space', 'pick'],
46
+ ['Enter', 'continue'],
47
+ ['Esc', 'back'],
48
+ ];
49
+ }
50
+ return [
51
+ ['Enter', 'continue'],
52
+ ...(question.kind === 'choice' ? [['Up/Down', 'move']] : []),
53
+ ['Esc', 'back'],
54
+ ];
55
+ }
56
+ //# sourceMappingURL=onboarding-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-panel.js","sourceRoot":"","sources":["../../../src/panels/onboarding/onboarding-panel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { errorMessage } from '@jinion/core/lib/errors';
3
+ import { useApi } from '../../app/api.js';
4
+ /**
5
+ * An account signed in but not active yet goes through here: an invite code, then the questions the dashboard asks.
6
+ * Nothing here says it worked: the app's `jinionUser` field turns active, and the app draws itself in its place.
7
+ */
8
+ export function useOnboarding() {
9
+ const api = useApi();
10
+ const [questions, setQuestions] = useState();
11
+ const [step, setStep] = useState({ kind: 'code', code: '' });
12
+ const [answers, setAnswers] = useState({});
13
+ const [code, setCode] = useState('');
14
+ useEffect(() => {
15
+ api.request('jinion/onboarding', {}).then(setQuestions, () => setQuestions([]));
16
+ }, []);
17
+ const finish = (all, withCode) => {
18
+ setStep({ kind: 'finishing' });
19
+ void api.request('jinion/activate', { code: withCode, answers: all }).catch((error) => {
20
+ const last = (questions?.length ?? 0) - 1;
21
+ setStep(last < 0 ? { kind: 'code', code: withCode, problem: errorMessage(error) } : { kind: 'question', index: last, problem: errorMessage(error) });
22
+ });
23
+ };
24
+ // The code comes along: state set a moment before isn't read back yet.
25
+ const next = (index, all = answers, withCode = code) => {
26
+ if (questions && index < questions.length)
27
+ return setStep({ kind: 'question', index });
28
+ finish(all, withCode);
29
+ };
30
+ const checkCode = (typed) => {
31
+ const trimmed = typed.trim();
32
+ // Without the questions yet, an empty set of answers would go along.
33
+ if (!trimmed || !questions)
34
+ return;
35
+ setStep({ kind: 'code', code: trimmed, checking: true });
36
+ void api.request('jinion/check-invite', { code: trimmed }).then(() => {
37
+ setCode(trimmed);
38
+ next(0, answers, trimmed);
39
+ }, (error) => setStep({ kind: 'code', code: trimmed, problem: errorMessage(error) }));
40
+ };
41
+ /** Moves on once a required question has its answer. */
42
+ const answer = (question, index, value) => {
43
+ const all = { ...answers, [question.id]: value };
44
+ setAnswers(all);
45
+ if (question.required && value.length === 0)
46
+ return setStep({ kind: 'question', index, problem: 'Please answer this one to continue.' });
47
+ next(index + 1, all);
48
+ };
49
+ const back = () => {
50
+ if (step.kind !== 'question')
51
+ return;
52
+ setStep(step.index === 0 ? { kind: 'code', code } : { kind: 'question', index: step.index - 1 });
53
+ };
54
+ return {
55
+ questions,
56
+ step,
57
+ answers,
58
+ typeCode: (typed) => setStep({ kind: 'code', code: typed }),
59
+ checkCode,
60
+ typeAnswer: (question, value) => setAnswers({ ...answers, [question.id]: value }),
61
+ answer,
62
+ back,
63
+ };
64
+ }
65
+ //# sourceMappingURL=use-onboarding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-onboarding.js","sourceRoot":"","sources":["../../../src/panels/onboarding/use-onboarding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, ChoiceList, Panel, Text, useChoiceList, usePanel, useTheme } from '@jinion/tui';
3
+ import { useAtomValue } from 'jotai';
4
+ import { useApi } from '../app/api.js';
5
+ import { jinionUserAtom } from '../state/session.js';
6
+ import { useAsync } from '../ui/use-async.js';
7
+ export function ProfilePanel() {
8
+ const api = useApi();
9
+ const theme = useTheme();
10
+ const { close } = usePanel();
11
+ const user = useAtomValue(jinionUserAtom);
12
+ const invites = useAsync(() => api.request('jinion/invites', {}), []);
13
+ // Closed first: signing out puts the app's sign-in in place of everything, and this panel shouldn't wait under it.
14
+ const list = useChoiceList({
15
+ keys: ['sign-out'],
16
+ mode: 'single',
17
+ onCancel: close,
18
+ onSubmit: () => {
19
+ close();
20
+ api.act(api.request('jinion/sign-out', {}));
21
+ },
22
+ });
23
+ if (!user)
24
+ return null;
25
+ return (_jsxs(Panel, { title: "Profile", hints: [
26
+ ['Enter', 'sign out'],
27
+ ['Esc', 'close'],
28
+ ], children: [_jsxs(Text, { children: ["Signed in as ", _jsx(Text, { bold: true, children: user.name ?? user.email }), user.name && _jsxs(Text, { color: theme.muted, children: [" (", user.email, ")"] })] }), _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Invites" }), _jsx(Text, { color: theme.muted, children: "Jinion is invite-only during the beta. Each of your codes lets one person in." }), invites.state === 'pending' && _jsx(Text, { color: theme.muted, children: "Getting your codes\u2026" }), invites.state === 'failed' && _jsxs(Text, { color: theme.muted, children: ["Couldn\u2019t get your codes: ", invites.error] }), invites.state === 'done' &&
29
+ invites.value.map((invite) => (_jsx(Text, { children: invite.status === 'active' ? (invite.code) : (_jsxs(Text, { color: theme.muted, children: [invite.code, " ", invite.status === 'used' ? (invite.usedBy ? `used by ${invite.usedBy}` : 'used') : 'no longer works'] })) }, invite.code)))] }), _jsx(ChoiceList, { list: list, limit: 1, choices: [{ key: 'sign-out', label: 'Sign out', description: 'You’ll need to sign in again to keep using Jinion' }] })] }));
30
+ }
31
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/panels/profile.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ import { Box, fuzzyFilter, Highlight, ListRow, Panel, PromptInput, SelectList, Text, useInput, useListNavigation, usePanel, useTheme, useWindowSize } from '@jinion/tui';
4
+ import { useAtomValue } from 'jotai';
5
+ import { ago } from '@jinion/core/lib/format';
6
+ import { useApi } from '../app/api.js';
7
+ import { sessionAtom } from '../state/session.js';
8
+ import { useAsync } from '../ui/use-async.js';
9
+ const CHROME_ROWS = 9;
10
+ const ROWS_PER_SESSION = 2;
11
+ export function ResumePanel({ query: initialQuery = '' }) {
12
+ const theme = useTheme();
13
+ const api = useApi();
14
+ const { close } = usePanel();
15
+ const { rows } = useWindowSize();
16
+ const { id: current } = useAtomValue(sessionAtom);
17
+ const [query, setQuery] = useState(initialQuery.trim());
18
+ const saved = useAsync(() => api.request('saved/list', {}), [current]);
19
+ const sessions = useMemo(() => (saved.state === 'done' ? saved.value.filter((session) => session.id !== current) : []), [saved, current]);
20
+ const matches = useMemo(() => fuzzyFilter(sessions, query, (session) => session.title), [sessions, query]);
21
+ const limit = Math.max(1, Math.floor((rows - CHROME_ROWS) / ROWS_PER_SESSION));
22
+ const [selected, setSelected] = useListNavigation(matches.length, { wrap: false, pageSize: limit });
23
+ useEffect(() => setSelected(0), [query, setSelected]);
24
+ useInput((_, key) => {
25
+ if (key.escape)
26
+ close();
27
+ });
28
+ const choose = () => {
29
+ const match = matches[selected];
30
+ if (!match)
31
+ return;
32
+ close();
33
+ // The conversation shown stays open in its tab.
34
+ api.act(api.request('sessions/open', { resume: match.item.id, activate: true }));
35
+ };
36
+ return (_jsx(Panel, { title: "Resume", subtitle: `${sessions.length} conversations`, grow: true, header: _jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "search " }), _jsx(PromptInput, { value: query, onChange: setQuery, onSubmit: choose, placeholder: "Type to filter", paddingX: 0 })] }), hints: [
37
+ ['Enter', 'resume'],
38
+ ['Up/Down', 'move'],
39
+ ['PgUp/PgDn', 'page'],
40
+ ['Esc', 'close'],
41
+ ], children: _jsx(SelectList, { items: matches, selected: selected, limit: limit, empty: saved.state === 'pending'
42
+ ? 'Reading saved conversations…'
43
+ : saved.state === 'failed'
44
+ ? `Couldn't read saved conversations: ${saved.error}`
45
+ : sessions.length === 0
46
+ ? 'No saved conversations yet'
47
+ : 'No conversations match', renderItem: ({ item, positions }, state) => (_jsx(ListRow, { selected: state.selected, label: _jsx(Highlight, { text: item.title, positions: positions }), aside: ago(item.updatedAt), detail: describe(item) })) }) }));
48
+ }
49
+ function describe({ openElsewhere, worktree, messages, firstPrompt = '' }) {
50
+ return `${openElsewhere ? 'open in another jinion · ' : ''}${worktree ? `worktree ${worktree} · ` : ''}${messages} messages · "${firstPrompt}"`;
51
+ }
52
+ //# sourceMappingURL=resume.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/panels/resume.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { relative } from 'node:path';
3
+ import { Box, Text, useTheme } from '@jinion/tui';
4
+ import { plural } from '@jinion/core/lib/format';
5
+ import { useAsync } from '../../ui/use-async.js';
6
+ import { useWorkdir } from '../../ui/use-workdir.js';
7
+ const FILES_SHOWN = 3;
8
+ export function Changes({ changes, indent }) {
9
+ const cwd = useWorkdir();
10
+ const theme = useTheme();
11
+ const known = useAsync(() => changes, [changes]);
12
+ if (known.state !== 'done' || !known.value) {
13
+ return (_jsx(Box, { paddingLeft: indent, children: _jsx(Text, { color: theme.muted, children: known.state === 'pending' ? 'Checking what would change…' : 'No file changes since then' }) }));
14
+ }
15
+ const { files, insertions, deletions } = known.value;
16
+ const names = files.slice(0, FILES_SHOWN).map((file) => relative(cwd, file) || file);
17
+ const more = files.length - names.length;
18
+ return (_jsxs(Box, { paddingLeft: indent, flexDirection: "column", children: [_jsxs(Text, { children: [files.length === 1 ? '1 file changes' : `${plural(files.length, 'file')} change`, _jsxs(Text, { color: theme.diff.added, children: [" +", insertions] }), _jsxs(Text, { color: theme.diff.removed, children: [" -", deletions] })] }), _jsxs(Text, { color: theme.muted, wrap: "truncate-end", children: [names.join(', '), more > 0 ? ` … ${more} more` : ''] })] }));
19
+ }
20
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../../src/panels/rewind/changes.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,MAAM,UAAU,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAiE;IACxG,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjD,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3C,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAE,MAAM,YACtB,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,YAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,4BAA4B,GAAQ,GACvH,CACP,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IACrF,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAEzC,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAC,QAAQ,aAC9C,MAAC,IAAI,eACF,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,EACjF,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,mBAAK,UAAU,IAAQ,EACpD,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,mBAAK,SAAS,IAAQ,IAChD,EACP,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAC,cAAc,aAC1C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAChB,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,IAC7B,IACH,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,93 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useState } from 'react';
3
+ import { ChoiceList, choiceIndent, Panel, Text, useChoiceList, usePanel, useTheme } from '@jinion/tui';
4
+ import { plural } from '@jinion/core/lib/format';
5
+ import { firstFilledLine as firstLine } from '@jinion/core/lib/text';
6
+ import { useAsync } from '../../ui/use-async.js';
7
+ import { Changes } from './changes.js';
8
+ const VISIBLE = 8;
9
+ export function RewindPanel({ points, preview, onRewind }) {
10
+ const [picked, setPicked] = useState();
11
+ // Each preview asks the agent once, however often the focus comes back to it.
12
+ const previews = useRef(new Map());
13
+ const previewOf = (point) => {
14
+ let changes = previews.current.get(point.promptId);
15
+ if (!changes) {
16
+ changes = preview(point).catch(() => undefined);
17
+ previews.current.set(point.promptId, changes);
18
+ }
19
+ return changes;
20
+ };
21
+ return picked ? (_jsx(ScopeStep, { point: picked, changes: previewOf(picked), onBack: () => setPicked(undefined), onPick: (scope) => onRewind(picked, scope) })) : (_jsx(PointStep, { points: points, previewOf: previewOf, onPick: setPicked }));
22
+ }
23
+ function PointStep({ points, previewOf, onPick }) {
24
+ const { close } = usePanel();
25
+ const list = useChoiceList({
26
+ keys: points.map((point) => point.entry),
27
+ mode: 'single',
28
+ onCancel: close,
29
+ onSubmit: ([entry]) => {
30
+ const point = points.find((candidate) => candidate.entry === entry);
31
+ if (point)
32
+ onPick(point);
33
+ },
34
+ });
35
+ // Only the focused message is previewed, so moving through the list asks the agent one message at a time.
36
+ const choices = points.map((point) => ({
37
+ key: point.entry,
38
+ label: firstLine(point.text),
39
+ editor: point.entry === list.focus ? _jsx(Changes, { changes: previewOf(point), indent: choiceIndent(list) }) : undefined,
40
+ }));
41
+ return (_jsx(Panel, { title: "Rewind", subtitle: plural(points.length, 'message'), hints: [
42
+ ['Enter', 'pick'],
43
+ ['Up/Down', 'move'],
44
+ ['Esc', 'cancel'],
45
+ ], children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE }) }));
46
+ }
47
+ /** Claude Code's choices, in its words, so they read the same as there. */
48
+ const SCOPES = [
49
+ {
50
+ key: 'both',
51
+ label: 'Restore code and conversation',
52
+ description: 'Files go back, and the conversation goes on from before this message, which goes back into the prompt',
53
+ scope: { code: true, conversation: true },
54
+ },
55
+ {
56
+ key: 'conversation',
57
+ label: 'Restore conversation',
58
+ description: 'The conversation goes on from before this message; the files stay as they are',
59
+ scope: { code: false, conversation: true },
60
+ },
61
+ {
62
+ key: 'code',
63
+ label: 'Restore code',
64
+ description: 'Files go back; the conversation goes on as it is',
65
+ scope: { code: true, conversation: false },
66
+ },
67
+ ];
68
+ const NEVER_MIND = { key: 'never-mind', label: 'Never mind', description: 'Back to the messages' };
69
+ function ScopeStep({ point, changes, onBack, onPick }) {
70
+ const theme = useTheme();
71
+ const { close } = usePanel();
72
+ const known = useAsync(() => changes, [changes]);
73
+ // Restoring code is offered only where there are file changes to take back.
74
+ const options = known.state === 'pending' ? [] : [...SCOPES.filter((scope) => (known.state === 'done' && known.value) || !scope.scope.code), NEVER_MIND];
75
+ const list = useChoiceList({
76
+ keys: options.map((option) => option.key),
77
+ mode: 'single',
78
+ onCancel: onBack,
79
+ onSubmit: ([key]) => {
80
+ const scope = SCOPES.find((candidate) => candidate.key === key);
81
+ if (!scope)
82
+ return onBack();
83
+ close();
84
+ onPick(scope.scope);
85
+ },
86
+ });
87
+ return (_jsx(Panel, { title: "Rewind to before", subtitle: firstLine(point.text), header: _jsx(Changes, { changes: changes, indent: 0 }), hints: [
88
+ ['Enter', 'rewind'],
89
+ ['Up/Down', 'move'],
90
+ ['Esc', 'back'],
91
+ ], children: _jsx(ChoiceList, { list: list, choices: options.map(({ key, label, description }) => ({ key, label, description: _jsx(Text, { color: theme.muted, children: description }) })) }) }));
92
+ }
93
+ //# sourceMappingURL=rewind-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rewind-panel.js","sourceRoot":"","sources":["../../../src/panels/rewind/rewind-panel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, ChoiceList, Panel, PromptInput, Text, useChoiceList, useInput, useTheme } from '@jinion/tui';
3
+ import { useApi } from '../../app/api.js';
4
+ import { useJinionSignIn } from './use-jinion-sign-in.js';
5
+ const WAYS = ['github', 'email'];
6
+ /** In the prompt's place until someone is signed in to Jinion; it can't be closed, only quit. */
7
+ export function SignInPanel() {
8
+ const api = useApi();
9
+ const theme = useTheme();
10
+ const signIn = useJinionSignIn();
11
+ const { step } = signIn;
12
+ const list = useChoiceList({
13
+ keys: WAYS,
14
+ mode: 'single',
15
+ isActive: step.kind === 'choose',
16
+ onCancel: () => { },
17
+ onSubmit: ([way]) => (way === 'github' ? signIn.withGithub() : signIn.withEmail()),
18
+ });
19
+ useInput((input, key) => {
20
+ if (key.ctrl && input === 'c')
21
+ return api.quit();
22
+ if (key.escape && step.kind !== 'choose')
23
+ signIn.back();
24
+ });
25
+ return (_jsxs(Panel, { title: "Welcome to Jinion", header: _jsx(Text, { color: theme.muted, children: "Sign in to get started." }), hints: hintsOf(step), children: [step.kind === 'choose' && (_jsxs(_Fragment, { children: [step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsx(ChoiceList, { list: list, limit: WAYS.length, choices: [
26
+ { key: 'github', label: 'Continue with GitHub', description: 'Opens your browser' },
27
+ { key: 'email', label: 'Continue with email', description: 'We’ll send you a 6-digit code' },
28
+ ] })] })), step.kind === 'github' && (_jsxs(_Fragment, { children: [_jsx(Text, { children: "Waiting for you to sign in with GitHub in your browser\u2026" }), step.link && (_jsxs(Text, { children: [_jsx(Text, { color: theme.muted, children: "Browser didn\u2019t open? Go to " }), _jsx(Text, { color: theme.code, children: step.link })] }))] })), step.kind === 'email' &&
29
+ (step.sending ? (_jsxs(Text, { color: theme.muted, children: ["Sending your code to ", step.email, "\u2026"] })) : (_jsxs(_Fragment, { children: [step.problem && _jsx(Text, { color: theme.error, children: step.problem }), _jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "email: " }), _jsx(PromptInput, { value: step.email, onChange: signIn.typeEmail, onSubmit: signIn.sendCode, placeholder: "you@example.com", paddingX: 0 })] })] }))), step.kind === 'code' && (_jsxs(_Fragment, { children: [_jsxs(Text, { children: ["We sent a 6-digit code to ", _jsx(Text, { bold: true, children: step.email }), ". It\u2019s valid for 10 minutes."] }), step.problem && _jsx(Text, { color: theme.error, children: step.problem }), step.checking ? (_jsx(Text, { color: theme.muted, children: "Checking your code\u2026" })) : (_jsxs(Box, { children: [_jsx(Text, { color: theme.muted, children: "code: " }), _jsx(PromptInput, { value: step.code, onChange: signIn.typeCode, onSubmit: signIn.signIn, placeholder: "123456", paddingX: 0 })] }))] }))] }));
30
+ }
31
+ function hintsOf(step) {
32
+ switch (step.kind) {
33
+ case 'choose':
34
+ return [
35
+ ['Enter', 'continue'],
36
+ ['Up/Down', 'move'],
37
+ ['Ctrl+C', 'quit'],
38
+ ];
39
+ case 'github':
40
+ return [
41
+ ['Esc', 'back'],
42
+ ['Ctrl+C', 'quit'],
43
+ ];
44
+ case 'email':
45
+ return [
46
+ ['Enter', 'send code'],
47
+ ['Esc', 'back'],
48
+ ];
49
+ case 'code':
50
+ return [
51
+ ['Enter', 'sign in'],
52
+ ['Esc', 'use another email'],
53
+ ];
54
+ }
55
+ }
56
+ //# sourceMappingURL=sign-in-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sign-in-panel.js","sourceRoot":"","sources":["../../../src/panels/sign-in/sign-in-panel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import { errorMessage } from '@jinion/core/lib/errors';
3
+ import { useApi } from '../../app/api.js';
4
+ /**
5
+ * Signing in to Jinion's own account, which runs in the core. Nothing here says it worked: the app's `jinionUser`
6
+ * field changes, and the app draws itself in place of the sign-in.
7
+ */
8
+ export function useJinionSignIn() {
9
+ const api = useApi();
10
+ const [step, setStep] = useState({ kind: 'choose' });
11
+ // Set while the browser has a GitHub sign-in, so leaving cancels it and its refusal isn't shown as a problem.
12
+ const github = useRef(undefined);
13
+ useEffect(() => {
14
+ const stopLink = api.client.on('jinion/sign-in-link', ({ url }) => setStep((now) => (now.kind === 'github' ? { ...now, link: url } : now)));
15
+ return () => {
16
+ stopLink();
17
+ if (github.current === 'waiting')
18
+ api.act(api.request('jinion/sign-in-cancel', {}));
19
+ };
20
+ }, []);
21
+ const withGithub = () => {
22
+ github.current = 'waiting';
23
+ setStep({ kind: 'github' });
24
+ void api.request('jinion/sign-in-github', {}).then(() => {
25
+ github.current = undefined;
26
+ }, (error) => {
27
+ if (github.current !== 'cancelled')
28
+ setStep({ kind: 'choose', problem: errorMessage(error) });
29
+ github.current = undefined;
30
+ });
31
+ };
32
+ const sendCode = (typed) => {
33
+ const email = typed.trim();
34
+ if (!email)
35
+ return;
36
+ setStep({ kind: 'email', email, sending: true });
37
+ void api.request('jinion/send-code', { email }).then(() => setStep({ kind: 'code', email, code: '' }), (error) => setStep({ kind: 'email', email, problem: errorMessage(error) }));
38
+ };
39
+ const signIn = (typed) => {
40
+ if (step.kind !== 'code')
41
+ return;
42
+ const code = typed.trim();
43
+ if (!code)
44
+ return;
45
+ const { email } = step;
46
+ setStep({ kind: 'code', email, code, checking: true });
47
+ void api.request('jinion/sign-in-email', { email, code }).catch((error) => setStep({ kind: 'code', email, code: '', problem: errorMessage(error) }));
48
+ };
49
+ const back = () => {
50
+ if (step.kind === 'code')
51
+ return setStep({ kind: 'email', email: step.email });
52
+ if (step.kind === 'github') {
53
+ github.current = 'cancelled';
54
+ api.act(api.request('jinion/sign-in-cancel', {}));
55
+ }
56
+ setStep({ kind: 'choose' });
57
+ };
58
+ return {
59
+ step,
60
+ withGithub,
61
+ withEmail: () => setStep({ kind: 'email', email: '' }),
62
+ typeEmail: (email) => setStep({ kind: 'email', email }),
63
+ sendCode,
64
+ typeCode: (code) => step.kind === 'code' && setStep({ ...step, code }),
65
+ signIn,
66
+ back,
67
+ };
68
+ }
69
+ //# sourceMappingURL=use-jinion-sign-in.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-jinion-sign-in.js","sourceRoot":"","sources":["../../../src/panels/sign-in/use-jinion-sign-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAQ1C;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IAErB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3D,8GAA8G;IAC9G,MAAM,MAAM,GAAG,MAAM,CAA0B,SAAS,CAAC,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAE5I,OAAO,GAAG,EAAE;YACV,QAAQ,EAAE,CAAC;YACX,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC;QACtF,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;QAC3B,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE5B,KAAK,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,IAAI,CAChD,GAAG,EAAE;YACH,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;QAC7B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;YACjB,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW;gBAAE,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC9F,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;QAC7B,CAAC,CACF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,KAAK,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAClD,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAChD,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CACpF,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO;QAEjC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;QAEvB,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvD,KAAK,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAChK,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAE/E,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3B,MAAM,CAAC,OAAO,GAAG,WAAW,CAAC;YAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,UAAU;QACV,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QACtD,SAAS,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAC/D,QAAQ;QACR,QAAQ,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9E,MAAM;QACN,IAAI;KACL,CAAC;AACJ,CAAC"}
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { ChoiceList, Panel, Text, useChoiceList, useInput, usePanel, useTheme } from '@jinion/tui';
4
+ import { useAtom, useSetAtom } from 'jotai';
5
+ import { statusItemsAtom, statusPreviewAtom } from '../status/items.js';
6
+ import { useStatusData } from '../status/data.js';
7
+ import { DEFAULT_STATUS_LINE, styleOf } from '../status/line.js';
8
+ import { findSegment, SEGMENTS } from '../status/segments/index.js';
9
+ const VISIBLE = 6;
10
+ const NAME_WIDTH = 13;
11
+ export function StatusLinePanel() {
12
+ const theme = useTheme();
13
+ const { close } = usePanel();
14
+ const data = useStatusData();
15
+ const [saved, save] = useAtom(statusItemsAtom);
16
+ const preview = useSetAtom(statusPreviewAtom);
17
+ const [order, setOrder] = useState(() => orderOf(saved));
18
+ const [looks, setLooks] = useState(() => looksOf(saved));
19
+ const itemsOf = (checked) => order.filter((id) => checked.includes(id)).map((id) => ({ id, ...looks[id] }));
20
+ const list = useChoiceList({
21
+ keys: order,
22
+ mode: 'multiple',
23
+ initialChecked: saved.map((item) => item.id),
24
+ onCancel: close,
25
+ onSubmit: (checked) => {
26
+ save(itemsOf(checked));
27
+ close();
28
+ },
29
+ });
30
+ const draft = itemsOf(list.checked);
31
+ const draftKey = JSON.stringify(draft);
32
+ const choices = order.map((id) => {
33
+ const segment = findSegment(id);
34
+ const look = looks[id];
35
+ const shown = list.isChecked(id);
36
+ const style = styleOf({ id, ...look });
37
+ const sample = segment.render(data, style);
38
+ return {
39
+ key: id,
40
+ label: (_jsxs(Text, { children: [segment.name.padEnd(NAME_WIDTH), _jsx(Text, { dimColor: !shown, children: sample ?? _jsx(Text, { color: theme.muted, children: "nothing to show yet" }) })] })),
41
+ description: [segment.description, segment.styles?.find((candidate) => candidate.id === style)?.name].filter(Boolean).join(' · '),
42
+ aside: shown ? look.side : undefined,
43
+ };
44
+ });
45
+ useEffect(() => preview(draft), [draftKey]);
46
+ // However the panel closes, the line goes back to what is saved.
47
+ useEffect(() => () => preview(undefined), []);
48
+ useInput((input, key) => {
49
+ const id = list.focus;
50
+ const look = looks[id];
51
+ const styles = findSegment(id)?.styles ?? [];
52
+ const restyle = (next) => setLooks({ ...looks, [id]: { ...look, ...next } });
53
+ if ((key.upArrow || key.downArrow) && key.shift) {
54
+ const index = order.indexOf(id);
55
+ const target = index + (key.upArrow ? -1 : 1);
56
+ if (target < 0 || target >= order.length)
57
+ return;
58
+ const moved = [...order];
59
+ moved[index] = moved[target];
60
+ moved[target] = id;
61
+ return setOrder(moved);
62
+ }
63
+ if (key.tab)
64
+ return restyle({ side: look.side === 'left' ? 'right' : 'left' });
65
+ if ((key.leftArrow || key.rightArrow) && styles.length > 1) {
66
+ const index = styles.findIndex((style) => style.id === styleOf({ id, ...look }));
67
+ return restyle({ style: styles[(index + (key.rightArrow ? 1 : -1) + styles.length) % styles.length].id });
68
+ }
69
+ if (input === 'r') {
70
+ setOrder(orderOf(DEFAULT_STATUS_LINE));
71
+ setLooks(looksOf(DEFAULT_STATUS_LINE));
72
+ for (const segment of SEGMENTS)
73
+ list.setChecked(segment.id, DEFAULT_STATUS_LINE.some((item) => item.id === segment.id));
74
+ }
75
+ });
76
+ return (_jsx(Panel, { title: "Status line", subtitle: `${list.checked.length} of ${SEGMENTS.length} shown`, header: _jsx(Text, { color: theme.muted, children: "Checked items show in the status line below, in this order. Changes show as you make them." }), hints: [
77
+ ['Space', 'select'],
78
+ ['Shift+Up/Down', 'move'],
79
+ ['Tab', 'side'],
80
+ ['Left/Right', 'style'],
81
+ ['r', 'reset'],
82
+ ['Enter', 'save'],
83
+ ['Esc', 'cancel'],
84
+ ], children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE }) }));
85
+ }
86
+ const orderOf = (items) => [
87
+ ...items.map((item) => item.id),
88
+ ...SEGMENTS.filter((segment) => !items.some((item) => item.id === segment.id)).map((segment) => segment.id),
89
+ ];
90
+ const looksOf = (items) => Object.fromEntries(SEGMENTS.map((segment) => {
91
+ const item = items.find((candidate) => candidate.id === segment.id);
92
+ return [segment.id, item ? { side: item.side, style: item.style } : { side: 'left' }];
93
+ }));
94
+ //# sourceMappingURL=statusline.js.map