attio 0.0.1-experimental.20241219 → 0.0.1-experimental.20250101
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/lib/api/create-version.js +2 -2
- package/lib/attio-logo.js +24 -0
- package/lib/attio.js +17 -8
- package/lib/commands/build.js +18 -35
- package/lib/commands/connection/add.js +51 -168
- package/lib/commands/connection/index.js +9 -1
- package/lib/commands/connection/list.js +17 -47
- package/lib/commands/connection/remove.js +17 -65
- package/lib/commands/create.js +27 -126
- package/lib/commands/dev.js +17 -106
- package/lib/commands/version/create.js +17 -68
- package/lib/commands/version/index.js +11 -1
- package/lib/commands/version/invite.js +40 -84
- package/lib/commands/version/list.js +18 -40
- package/lib/commands/version/publish.js +40 -64
- package/lib/machines/actions.js +7 -0
- package/lib/machines/actors.js +7 -1
- package/lib/machines/add-connection-machine.js +169 -201
- package/lib/machines/build-machine.js +35 -4
- package/lib/machines/create-machine.js +95 -70
- package/lib/machines/create-version-machine.js +121 -4
- package/lib/machines/dev-machine.js +173 -53
- package/lib/machines/generate-invite-machine.js +64 -10
- package/lib/machines/list-connections-machine.js +57 -2
- package/lib/machines/list-versions-machine.js +33 -0
- package/lib/machines/publish-version-machine.js +45 -16
- package/lib/machines/remove-connection-machine.js +64 -17
- package/lib/machines/ts-machine.js +4 -1
- package/lib/schema.js +2 -2
- package/lib/util/clear-terminal.js +4 -0
- package/lib/util/load-developer-config.js +2 -2
- package/lib/util/print-install-instructions.js +32 -0
- package/lib/util/print-message.js +9 -0
- package/lib/util/set-terminal-title.js +8 -0
- package/lib/util/text-gradient.js +28 -0
- package/lib/util/typescript.js +25 -0
- package/package.json +13 -12
- package/schema.graphql +8 -1
- package/lib/components/BuildError.js +0 -46
- package/lib/components/BuildLog.js +0 -6
- package/lib/components/CodeGenErrors.js +0 -22
- package/lib/components/Disclaimer.js +0 -9
- package/lib/components/InitialInstructions.js +0 -69
- package/lib/components/Log.js +0 -69
- package/lib/components/Logo.js +0 -10
- package/lib/components/MultiSelect.js +0 -65
- package/lib/components/ScrollBox.js +0 -87
- package/lib/components/ScrollBox.store.js +0 -36
- package/lib/components/ScrollBox.util.js +0 -27
- package/lib/components/Select.js +0 -6
- package/lib/components/Table.js +0 -33
- package/lib/components/TypeScriptErrors.js +0 -38
- package/lib/hooks/useFullScreen.js +0 -22
- package/lib/hooks/useTerminalTitle.js +0 -11
package/schema.graphql
CHANGED
|
@@ -152,10 +152,11 @@ type ActorReferenceValue {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
"""An actor inside Attio."""
|
|
155
|
-
union Actor = User | SystemActor | APITokenActor | Workflow
|
|
155
|
+
union Actor = User | SystemActor | APITokenActor | App | Workflow
|
|
156
156
|
|
|
157
157
|
"""An Attio user."""
|
|
158
158
|
type User {
|
|
159
|
+
id: String!
|
|
159
160
|
email: String!
|
|
160
161
|
name: String!
|
|
161
162
|
}
|
|
@@ -170,6 +171,11 @@ type APITokenActor {
|
|
|
170
171
|
type: String!
|
|
171
172
|
}
|
|
172
173
|
|
|
174
|
+
"""An Attio app."""
|
|
175
|
+
type App {
|
|
176
|
+
type: String!
|
|
177
|
+
}
|
|
178
|
+
|
|
173
179
|
"""An Attio workflow."""
|
|
174
180
|
type Workflow {
|
|
175
181
|
type: String!
|
|
@@ -247,6 +253,7 @@ type Query {
|
|
|
247
253
|
"""Slug of the record's object."""
|
|
248
254
|
object: String!
|
|
249
255
|
): Record
|
|
256
|
+
currentUser: User!
|
|
250
257
|
}
|
|
251
258
|
|
|
252
259
|
"""The person object in the workspace."""
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
const Error = React.forwardRef(({ message, level }, ref) => (React.createElement(Box, { flexDirection: "column", ref: ref },
|
|
4
|
-
React.createElement(Box, null,
|
|
5
|
-
React.createElement(Text, { color: level === "error" ? "red" : "yellow" },
|
|
6
|
-
level === "error" ? "❌" : "⚠️",
|
|
7
|
-
" ",
|
|
8
|
-
React.createElement(Text, { backgroundColor: level === "error" ? "red" : "yellow", color: "white" },
|
|
9
|
-
" ",
|
|
10
|
-
level === "error" ? "ERROR" : "WARNING",
|
|
11
|
-
" ")),
|
|
12
|
-
React.createElement(Text, { bold: true }, message.text)),
|
|
13
|
-
React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
|
|
14
|
-
React.createElement(Box, { marginLeft: 4 },
|
|
15
|
-
React.createElement(Text, null,
|
|
16
|
-
message.location.file,
|
|
17
|
-
":",
|
|
18
|
-
message.location.line,
|
|
19
|
-
":",
|
|
20
|
-
message.location.column)),
|
|
21
|
-
React.createElement(Box, { marginLeft: 4, marginTop: 1 },
|
|
22
|
-
React.createElement(Box, { flexDirection: "column", marginRight: 1 },
|
|
23
|
-
React.createElement(Text, null, message.location.line)),
|
|
24
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
25
|
-
React.createElement(Text, null,
|
|
26
|
-
"| ",
|
|
27
|
-
message.location.lineText.trim()),
|
|
28
|
-
React.createElement(Box, null,
|
|
29
|
-
React.createElement(Text, null, "|"),
|
|
30
|
-
React.createElement(Box, { paddingLeft: message.location.column +
|
|
31
|
-
message.location.lineText.trim().length -
|
|
32
|
-
message.location.lineText.length +
|
|
33
|
-
1 },
|
|
34
|
-
React.createElement(Text, { color: "greenBright" }, "^"))))),
|
|
35
|
-
message.location.additionalLines &&
|
|
36
|
-
message.location.additionalLines.slice(0, 2).map((line, index) => (React.createElement(Box, { key: `additional-line-${index}`, marginLeft: 4 },
|
|
37
|
-
React.createElement(Text, null,
|
|
38
|
-
message.location.line + index + 1,
|
|
39
|
-
" | ",
|
|
40
|
-
line))))))));
|
|
41
|
-
export function renderBuildErrors({ errors, warnings }) {
|
|
42
|
-
return [
|
|
43
|
-
...(errors ?? []).map((error, index) => (React.createElement(Error, { key: `BuildError-${index}`, message: error, level: "error" }))),
|
|
44
|
-
...(warnings ?? []).map((error, index) => (React.createElement(Error, { key: `BuildError-${index}`, message: error, level: "warning" }))),
|
|
45
|
-
];
|
|
46
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
export function BuildLog({ log }) {
|
|
4
|
-
return (React.createElement(Box, { flexDirection: "column" }, log.map((msg, index) => (React.createElement(Box, { key: index },
|
|
5
|
-
React.createElement(Text, null, msg))))));
|
|
6
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { codeFrameColumns } from "@babel/code-frame";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
3
|
-
import React from "react";
|
|
4
|
-
export const CodeGenError = React.forwardRef(({ error }, ref) => {
|
|
5
|
-
return (React.createElement(Box, { flexDirection: "column", ref: ref },
|
|
6
|
-
React.createElement(Box, null,
|
|
7
|
-
React.createElement(Text, { color: "red" },
|
|
8
|
-
React.createElement(Text, { backgroundColor: "red", color: "white" },
|
|
9
|
-
" ",
|
|
10
|
-
"GRAPHQL ERROR",
|
|
11
|
-
" "),
|
|
12
|
-
" ",
|
|
13
|
-
React.createElement(Text, null, error.message))),
|
|
14
|
-
error.locations && (React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
|
|
15
|
-
React.createElement(Box, null,
|
|
16
|
-
React.createElement(Text, null, codeFrameColumns(error.source, {
|
|
17
|
-
start: {
|
|
18
|
-
line: error.locations[0].line,
|
|
19
|
-
column: error.locations[0].column,
|
|
20
|
-
},
|
|
21
|
-
})))))));
|
|
22
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_PROMOTED = "You found something that isn't quite ready yet.";
|
|
4
|
-
export const Disclaimer = () => (React.createElement(Box, { marginBottom: 2, marginX: 1, padding: 1, borderStyle: "bold", width: 61 },
|
|
5
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
6
|
-
React.createElement(Box, null,
|
|
7
|
-
React.createElement(Text, { color: "yellowBright" }, "You are using the Private Alpha version of this CLI tool.")),
|
|
8
|
-
React.createElement(Box, { marginTop: 2, alignSelf: "center" },
|
|
9
|
-
React.createElement(Text, { color: "magentaBright" }, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_PROMOTED)))));
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { stringify } from "ini";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
3
|
-
import Link from "ink-link";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import { APP, APP_NO_PROTOCOL, IS_DEV } from "../env.js";
|
|
6
|
-
import { configFileName } from "../util/load-developer-config.js";
|
|
7
|
-
const exampleConfig = {
|
|
8
|
-
token: "YOUR TOKEN HERE",
|
|
9
|
-
developer_slug: "ANY UNIQUE SLUG YOU WANT",
|
|
10
|
-
target_workspace_id: "YOUR WORKSPACE ID HERE",
|
|
11
|
-
};
|
|
12
|
-
export const InitialInstructions = ({ reason }) => (React.createElement(Box, { flexDirection: "column", gap: 1 },
|
|
13
|
-
reason && (React.createElement(Box, { flexDirection: "column" },
|
|
14
|
-
React.createElement(Box, null,
|
|
15
|
-
React.createElement(Text, null, "Failed to load config file.")),
|
|
16
|
-
React.createElement(Box, null,
|
|
17
|
-
React.createElement(Text, { color: "redBright" }, reason)))),
|
|
18
|
-
React.createElement(Box, null,
|
|
19
|
-
React.createElement(Text, null, "You will need to:")),
|
|
20
|
-
React.createElement(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1 },
|
|
21
|
-
React.createElement(Box, null,
|
|
22
|
-
React.createElement(Text, null,
|
|
23
|
-
"1. Log into",
|
|
24
|
-
IS_DEV && (React.createElement(React.Fragment, null,
|
|
25
|
-
" ",
|
|
26
|
-
React.createElement(Text, { italic: true }, "DEVELOPMENT"))),
|
|
27
|
-
" ",
|
|
28
|
-
"Attio web app:",
|
|
29
|
-
" ",
|
|
30
|
-
React.createElement(Link, { url: APP, fallback: false }, APP),
|
|
31
|
-
".")),
|
|
32
|
-
React.createElement(Box, null,
|
|
33
|
-
React.createElement(Text, null,
|
|
34
|
-
"2. Open ",
|
|
35
|
-
React.createElement(Text, { color: "cyan" }, "Dev Tools"),
|
|
36
|
-
" >",
|
|
37
|
-
" ",
|
|
38
|
-
React.createElement(Text, { color: "cyan" }, "Application"),
|
|
39
|
-
" > ",
|
|
40
|
-
React.createElement(Text, { color: "cyan" }, "Cookies"),
|
|
41
|
-
" ",
|
|
42
|
-
"> ",
|
|
43
|
-
React.createElement(Text, { color: "cyan" }, APP_NO_PROTOCOL))),
|
|
44
|
-
React.createElement(Box, null,
|
|
45
|
-
React.createElement(Text, null,
|
|
46
|
-
"3. Copy the value for ",
|
|
47
|
-
React.createElement(Text, { color: "cyan" }, "attio-session"),
|
|
48
|
-
". That's your \"token\".")),
|
|
49
|
-
React.createElement(Box, null,
|
|
50
|
-
React.createElement(Text, null,
|
|
51
|
-
"4. Create a file in your home directory called",
|
|
52
|
-
" ",
|
|
53
|
-
React.createElement(Text, { color: "cyan" },
|
|
54
|
-
"~/",
|
|
55
|
-
configFileName),
|
|
56
|
-
".")),
|
|
57
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
58
|
-
React.createElement(Text, null,
|
|
59
|
-
"5. It should have the following [",
|
|
60
|
-
React.createElement(Link, { url: "https://en.wikipedia.org/wiki/INI_file" }, "INI"),
|
|
61
|
-
"] format:"),
|
|
62
|
-
React.createElement(Box, { marginLeft: 3, borderStyle: "single", width: 60 },
|
|
63
|
-
React.createElement(Text, null, stringify(exampleConfig).trim()))),
|
|
64
|
-
React.createElement(Box, null,
|
|
65
|
-
React.createElement(Text, null, "6. Run this command again.")),
|
|
66
|
-
React.createElement(Box, { marginY: 1 },
|
|
67
|
-
React.createElement(Text, null, "...")),
|
|
68
|
-
React.createElement(Box, null,
|
|
69
|
-
React.createElement(Text, null, "N. PROFIT!")))));
|
package/lib/components/Log.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
const emojis = {
|
|
4
|
-
log: "📝",
|
|
5
|
-
info: "💬",
|
|
6
|
-
warn: "🔸",
|
|
7
|
-
error: "🚨",
|
|
8
|
-
};
|
|
9
|
-
class GlobalLog {
|
|
10
|
-
constructor() {
|
|
11
|
-
this._messages = [];
|
|
12
|
-
this._listeners = new Map();
|
|
13
|
-
this._nextListenerId = 0;
|
|
14
|
-
}
|
|
15
|
-
notifyListeners() {
|
|
16
|
-
this._listeners.forEach((listener) => listener());
|
|
17
|
-
}
|
|
18
|
-
addMessage(level, messages) {
|
|
19
|
-
this._messages.push({
|
|
20
|
-
level,
|
|
21
|
-
message: messages
|
|
22
|
-
.map((message) => typeof message === "string"
|
|
23
|
-
? message
|
|
24
|
-
: typeof message === "number"
|
|
25
|
-
? message.toString()
|
|
26
|
-
: JSON.stringify(message, null, 2))
|
|
27
|
-
.join(" "),
|
|
28
|
-
});
|
|
29
|
-
this.notifyListeners();
|
|
30
|
-
}
|
|
31
|
-
log(...messages) {
|
|
32
|
-
this.addMessage("log", messages);
|
|
33
|
-
}
|
|
34
|
-
info(...messages) {
|
|
35
|
-
this.addMessage("info", messages);
|
|
36
|
-
}
|
|
37
|
-
warn(...messages) {
|
|
38
|
-
this.addMessage("warn", messages);
|
|
39
|
-
}
|
|
40
|
-
error(...messages) {
|
|
41
|
-
this.addMessage("error", messages);
|
|
42
|
-
}
|
|
43
|
-
clear() {
|
|
44
|
-
this._messages = [];
|
|
45
|
-
this.notifyListeners();
|
|
46
|
-
}
|
|
47
|
-
getMessages() {
|
|
48
|
-
return this._messages;
|
|
49
|
-
}
|
|
50
|
-
listen(listener) {
|
|
51
|
-
const id = this._nextListenerId++;
|
|
52
|
-
this._listeners.set(id, listener);
|
|
53
|
-
return () => this._listeners.delete(id);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const globalLog = new GlobalLog();
|
|
57
|
-
export const log = (...messages) => globalLog.log(...messages);
|
|
58
|
-
export const info = (...messages) => globalLog.info(...messages);
|
|
59
|
-
export const warn = (...messages) => globalLog.warn(...messages);
|
|
60
|
-
export const error = (...messages) => globalLog.error(...messages);
|
|
61
|
-
export const Log = () => {
|
|
62
|
-
const messages = React.useSyncExternalStore(() => globalLog.listen(() => {
|
|
63
|
-
}), () => globalLog.getMessages(), () => []);
|
|
64
|
-
if (messages.length === 0)
|
|
65
|
-
return null;
|
|
66
|
-
return (React.createElement(Box, { flexDirection: "column", paddingY: 1 }, messages.map((message, index) => (React.createElement(Box, { key: index, flexDirection: "row", gap: 1 },
|
|
67
|
-
React.createElement(Text, null, emojis[message.level]),
|
|
68
|
-
React.createElement(Text, null, message.message))))));
|
|
69
|
-
};
|
package/lib/components/Logo.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Box } from "ink";
|
|
2
|
-
import BigText from "ink-big-text";
|
|
3
|
-
import Gradient from "ink-gradient";
|
|
4
|
-
import React from "react";
|
|
5
|
-
import { Disclaimer } from "./Disclaimer.js";
|
|
6
|
-
export const Logo = () => (React.createElement(Box, { flexDirection: "column" },
|
|
7
|
-
React.createElement(Box, null,
|
|
8
|
-
React.createElement(Gradient, { name: "morning" },
|
|
9
|
-
React.createElement(BigText, { text: "/. Attio" }))),
|
|
10
|
-
React.createElement(Disclaimer, null)));
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import figures from "figures";
|
|
2
|
-
import { Box, Text, useStdin } from "ink";
|
|
3
|
-
import React from "react";
|
|
4
|
-
const ARROW_UP = "\u001B[A";
|
|
5
|
-
const ARROW_DOWN = "\u001B[B";
|
|
6
|
-
const ENTER = "\r";
|
|
7
|
-
const SPACE = " ";
|
|
8
|
-
export function MultiSelect({ items, requiredMin = 0, onSubmit, }) {
|
|
9
|
-
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
10
|
-
const [selectedValues, setSelectedValues] = React.useState(new Set());
|
|
11
|
-
const { stdin, setRawMode } = useStdin();
|
|
12
|
-
React.useEffect(() => {
|
|
13
|
-
setRawMode(true);
|
|
14
|
-
return () => setRawMode(false);
|
|
15
|
-
}, [setRawMode]);
|
|
16
|
-
React.useEffect(() => {
|
|
17
|
-
const handleInput = (data) => {
|
|
18
|
-
switch (data) {
|
|
19
|
-
case ARROW_UP:
|
|
20
|
-
case "k":
|
|
21
|
-
setActiveIndex((prev) => (prev - 1 + items.length) % items.length);
|
|
22
|
-
break;
|
|
23
|
-
case ARROW_DOWN:
|
|
24
|
-
case "j":
|
|
25
|
-
setActiveIndex((prev) => (prev + 1) % items.length);
|
|
26
|
-
break;
|
|
27
|
-
case SPACE:
|
|
28
|
-
setSelectedValues((prev) => {
|
|
29
|
-
const newSelectedValues = new Set(prev);
|
|
30
|
-
const item = items[activeIndex];
|
|
31
|
-
if (newSelectedValues.has(item.value)) {
|
|
32
|
-
newSelectedValues.delete(item.value);
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
newSelectedValues.add(item.value);
|
|
36
|
-
}
|
|
37
|
-
return newSelectedValues;
|
|
38
|
-
});
|
|
39
|
-
break;
|
|
40
|
-
case ENTER:
|
|
41
|
-
if (selectedValues.size < requiredMin)
|
|
42
|
-
break;
|
|
43
|
-
onSubmit(Array.from(selectedValues));
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
stdin.on("data", handleInput);
|
|
48
|
-
return () => {
|
|
49
|
-
stdin.removeListener("data", handleInput);
|
|
50
|
-
};
|
|
51
|
-
}, [activeIndex, items, onSubmit, requiredMin, selectedValues, stdin]);
|
|
52
|
-
return (React.createElement(Box, { flexDirection: "column" }, items.map((item, index) => {
|
|
53
|
-
const isHighlighted = index === activeIndex;
|
|
54
|
-
const isSelected = selectedValues.has(item.value);
|
|
55
|
-
return (React.createElement(Box, { key: item.value },
|
|
56
|
-
React.createElement(Text, { color: isSelected ? "yellow" : isHighlighted ? "green" : "white" },
|
|
57
|
-
React.createElement(Text, null,
|
|
58
|
-
isHighlighted ? figures.pointer : " ",
|
|
59
|
-
" "),
|
|
60
|
-
React.createElement(Text, { color: isSelected ? "yellow" : undefined },
|
|
61
|
-
isSelected ? figures.circleFilled : figures.circle,
|
|
62
|
-
" "),
|
|
63
|
-
React.createElement(Text, null, item.label))));
|
|
64
|
-
})));
|
|
65
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { useSelector } from "@xstate/react";
|
|
2
|
-
import { Box, Text, measureElement, useInput } from "ink";
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { useFullScreen } from "../hooks/useFullScreen.js";
|
|
5
|
-
import { useScrollBoxStore } from "./ScrollBox.store.js";
|
|
6
|
-
import { calculateChildRange } from "./ScrollBox.util.js";
|
|
7
|
-
const GAP = 1;
|
|
8
|
-
export const ScrollBox = React.memo(({ padding, ...props }) => {
|
|
9
|
-
const { height: screenHeight, width } = useFullScreen();
|
|
10
|
-
const [top, setTop] = React.useState(0);
|
|
11
|
-
const height = Number(screenHeight) - top;
|
|
12
|
-
const availableHeight = height - (props.borderStyle ? 2 : 0) - (padding ?? 0) * 2;
|
|
13
|
-
const children = React.useMemo(() => React.Children.toArray(props.children).filter((element) => Boolean(element) && React.isValidElement(element)), [props.children]);
|
|
14
|
-
const store = useScrollBoxStore(children.length, availableHeight, Number(width ?? ""));
|
|
15
|
-
const boxRef = React.useCallback((element) => setTop(element?.yogaNode?.getComputedTop() ?? 0), []);
|
|
16
|
-
const heights = useSelector(store, (state) => state.context.heights);
|
|
17
|
-
const offset = useSelector(store, (state) => state.context.offset);
|
|
18
|
-
const allMeasured = heights.length === children.length;
|
|
19
|
-
const haveOverflow = allMeasured && heights.reduce((a, b) => a + b, 0) > availableHeight;
|
|
20
|
-
const childRange = calculateChildRange(heights, offset, availableHeight);
|
|
21
|
-
const itemsShown = childRange[1] - childRange[0];
|
|
22
|
-
const hiddenAbove = offset;
|
|
23
|
-
const hiddenBelow = children.length - (offset + itemsShown);
|
|
24
|
-
useInput((input, key) => {
|
|
25
|
-
if (input === "j" || key.downArrow) {
|
|
26
|
-
if (key.meta) {
|
|
27
|
-
store.send({ type: "Page Down" });
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
store.send({ type: "Down" });
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else if (input === "k" || key.upArrow) {
|
|
34
|
-
if (key.meta) {
|
|
35
|
-
store.send({ type: "Page Up" });
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
store.send({ type: "Up" });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
else if (input === " " || (input === "d" && key.ctrl)) {
|
|
42
|
-
store.send({ type: "Page Down" });
|
|
43
|
-
}
|
|
44
|
-
else if (input === "b" || (input === "u" && key.ctrl)) {
|
|
45
|
-
store.send({ type: "Page Up" });
|
|
46
|
-
}
|
|
47
|
-
else if (input === "G") {
|
|
48
|
-
store.send({ type: "Bottom" });
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
return (React.createElement(Box, { ...props, height: height, ref: boxRef, flexDirection: "column" },
|
|
52
|
-
haveOverflow && (React.createElement(Box, { flexDirection: "column", alignItems: "center", marginBottom: -1 }, hiddenAbove > 0 ? (React.createElement(Text, null,
|
|
53
|
-
"+ ",
|
|
54
|
-
hiddenAbove,
|
|
55
|
-
" item",
|
|
56
|
-
hiddenAbove === 1 ? "" : "s",
|
|
57
|
-
" ... press \u2191 to scroll",
|
|
58
|
-
" ")) : (React.createElement(Text, null, " ")))),
|
|
59
|
-
React.createElement(Box, { flexDirection: "column", gap: GAP, flexGrow: 1, padding: padding }, allMeasured
|
|
60
|
-
? children.map((child, index) => index >= childRange[0] && index < childRange[1]
|
|
61
|
-
? React.cloneElement(child, {
|
|
62
|
-
ref: (element) => {
|
|
63
|
-
const height = element
|
|
64
|
-
? measureElement(element).height + GAP
|
|
65
|
-
: 0;
|
|
66
|
-
if (!height)
|
|
67
|
-
return;
|
|
68
|
-
store.send({ type: "Item Measured", index, height });
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
: null)
|
|
72
|
-
:
|
|
73
|
-
React.cloneElement(children[heights.length], {
|
|
74
|
-
ref: (element) => {
|
|
75
|
-
const height = element ? measureElement(element).height + GAP : 0;
|
|
76
|
-
if (!height)
|
|
77
|
-
return;
|
|
78
|
-
store.send({ type: "Item Measured", index: heights.length, height });
|
|
79
|
-
},
|
|
80
|
-
})),
|
|
81
|
-
haveOverflow && (React.createElement(Box, { flexDirection: "column", alignItems: "center", marginTop: -1 }, hiddenBelow > 0 ? (React.createElement(Text, null,
|
|
82
|
-
"+ ",
|
|
83
|
-
hiddenBelow,
|
|
84
|
-
" item",
|
|
85
|
-
hiddenBelow === 1 ? "" : "s",
|
|
86
|
-
" ... press \u2193 to scroll")) : (React.createElement(Text, null, " "))))));
|
|
87
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createStoreWithProducer } from "@xstate/store";
|
|
2
|
-
import { produce } from "immer";
|
|
3
|
-
import React from "react";
|
|
4
|
-
import { calculateChildRange, calculateLastPageOffset, calculatePreviousPageOffset, } from "./ScrollBox.util.js";
|
|
5
|
-
const initial = {
|
|
6
|
-
offset: 0,
|
|
7
|
-
heights: [],
|
|
8
|
-
};
|
|
9
|
-
export function useScrollBoxStore(numChildren, availableHeight, width) {
|
|
10
|
-
return React.useMemo(() => createStoreWithProducer(produce, initial, {
|
|
11
|
-
"Down": (context) => {
|
|
12
|
-
const [, end] = calculateChildRange(context.heights, context.offset, availableHeight);
|
|
13
|
-
if (end < numChildren) {
|
|
14
|
-
context.offset = Math.min(context.offset + 1, numChildren - 1);
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
"Up": (context) => {
|
|
18
|
-
context.offset = Math.max(context.offset - 1, 0);
|
|
19
|
-
},
|
|
20
|
-
"Page Down": (context) => {
|
|
21
|
-
const [, end] = calculateChildRange(context.heights, context.offset, availableHeight);
|
|
22
|
-
if (end < numChildren - 1) {
|
|
23
|
-
context.offset = end;
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
"Page Up": (context) => {
|
|
27
|
-
context.offset = calculatePreviousPageOffset(context.heights, context.offset, availableHeight);
|
|
28
|
-
},
|
|
29
|
-
"Bottom": (context) => {
|
|
30
|
-
context.offset = calculateLastPageOffset(context.heights, context.offset, availableHeight);
|
|
31
|
-
},
|
|
32
|
-
"Item Measured": (context, { index, height }) => {
|
|
33
|
-
context.heights[index] = height;
|
|
34
|
-
},
|
|
35
|
-
}), [availableHeight, numChildren, width]);
|
|
36
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export function calculateChildRange(heights, offset, availableHeight) {
|
|
2
|
-
let heightUsed = 0;
|
|
3
|
-
for (let index = offset; index < heights.length; index++) {
|
|
4
|
-
heightUsed += heights[index];
|
|
5
|
-
if (heightUsed > availableHeight)
|
|
6
|
-
return [offset, Math.max(index, 1)];
|
|
7
|
-
}
|
|
8
|
-
return [offset, heights.length];
|
|
9
|
-
}
|
|
10
|
-
export function calculatePreviousPageOffset(heights, offset, availableHeight) {
|
|
11
|
-
let heightUsed = 0;
|
|
12
|
-
for (let index = offset - 1; index > 0; index--) {
|
|
13
|
-
heightUsed += heights[index];
|
|
14
|
-
if (heightUsed > availableHeight)
|
|
15
|
-
return index + 1;
|
|
16
|
-
}
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
19
|
-
export function calculateLastPageOffset(heights, offset, availableHeight) {
|
|
20
|
-
let heightUsed = 0;
|
|
21
|
-
for (let index = heights.length - 1; index > 0; index--) {
|
|
22
|
-
heightUsed += heights[index];
|
|
23
|
-
if (heightUsed > availableHeight)
|
|
24
|
-
return index + 1;
|
|
25
|
-
}
|
|
26
|
-
return 0;
|
|
27
|
-
}
|
package/lib/components/Select.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { Text } from "ink";
|
|
2
|
-
import SelectInput from "ink-select-input";
|
|
3
|
-
import React from "react";
|
|
4
|
-
export function Select({ initialValue, items, onSelect }) {
|
|
5
|
-
return (React.createElement(SelectInput, { items: items.map((item) => ({ ...item, key: item.label })), onSelect: ({ value }) => onSelect(value), initialIndex: initialValue ? items.findIndex((item) => item.value === initialValue) : 0, indicatorComponent: ({ isSelected }) => isSelected ? React.createElement(Text, { color: "green" }, "> ") : React.createElement(Text, null, " "), itemComponent: ({ isSelected, label }) => (React.createElement(Text, { color: isSelected ? "green" : "white" }, label)) }));
|
|
6
|
-
}
|
package/lib/components/Table.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
export function Table({ rows, }) {
|
|
4
|
-
const columns = React.useMemo(() => (rows.length > 0 ? Object.keys(rows[0]) : []), [rows]);
|
|
5
|
-
const widths = React.useMemo(() => {
|
|
6
|
-
return rows.reduce((acc, row) => {
|
|
7
|
-
columns.forEach((column) => {
|
|
8
|
-
acc[column] = Math.max(acc[column] ?? 0, row[column].length);
|
|
9
|
-
});
|
|
10
|
-
return acc;
|
|
11
|
-
}, columns.reduce((acc, column) => {
|
|
12
|
-
acc[column] = column.length;
|
|
13
|
-
return acc;
|
|
14
|
-
}, {}));
|
|
15
|
-
}, [rows, columns]);
|
|
16
|
-
const flexWidths = React.useMemo(() => {
|
|
17
|
-
return columns.reduce((acc, column) => {
|
|
18
|
-
acc[column] = {
|
|
19
|
-
flexDirection: "row",
|
|
20
|
-
flexGrow: widths[column],
|
|
21
|
-
flexShrink: widths[column],
|
|
22
|
-
flexBasis: widths[column],
|
|
23
|
-
justifyContent: "center",
|
|
24
|
-
};
|
|
25
|
-
return acc;
|
|
26
|
-
}, {});
|
|
27
|
-
}, [columns, widths]);
|
|
28
|
-
return (React.createElement(Box, { flexDirection: "column", width: "100%" },
|
|
29
|
-
React.createElement(Box, { flexDirection: "row", width: "100%" }, columns.map((column, index) => (React.createElement(Box, { key: index, ...flexWidths[column], borderTop: false, borderLeft: false, borderRight: false, borderStyle: "single" },
|
|
30
|
-
React.createElement(Text, { color: "blue" }, column))))),
|
|
31
|
-
rows.map((row, rowIndex) => (React.createElement(Box, { key: rowIndex, flexDirection: "row", width: "100%", borderStyle: "single", borderTop: rowIndex > 0, borderLeft: false, borderRight: false, borderBottom: rowIndex === rows.length - 1 }, columns.map((column, columnIndex) => (React.createElement(Box, { key: columnIndex, ...flexWidths[column] },
|
|
32
|
-
React.createElement(Text, null, row[column])))))))));
|
|
33
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
const Error = React.forwardRef(({ error }, ref) => {
|
|
4
|
-
return (React.createElement(Box, { flexDirection: "column", ref: ref },
|
|
5
|
-
React.createElement(Box, null,
|
|
6
|
-
React.createElement(Text, { color: "red" },
|
|
7
|
-
React.createElement(Text, { backgroundColor: "red", color: "white" },
|
|
8
|
-
" ",
|
|
9
|
-
"TYPESCRIPT ERROR",
|
|
10
|
-
" "),
|
|
11
|
-
" "),
|
|
12
|
-
React.createElement(Text, { bold: true }, error.text)),
|
|
13
|
-
error.location && (React.createElement(Box, { paddingTop: 1, flexDirection: "column" },
|
|
14
|
-
React.createElement(Box, { marginLeft: 4 },
|
|
15
|
-
React.createElement(Text, null,
|
|
16
|
-
error.location.file,
|
|
17
|
-
":",
|
|
18
|
-
error.location.line,
|
|
19
|
-
":",
|
|
20
|
-
error.location.character)),
|
|
21
|
-
React.createElement(Box, { marginLeft: 4, marginTop: 1 },
|
|
22
|
-
React.createElement(Box, { flexDirection: "column", marginRight: 1 },
|
|
23
|
-
React.createElement(Text, null, error.location.line)),
|
|
24
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
25
|
-
React.createElement(Text, null,
|
|
26
|
-
"| ",
|
|
27
|
-
error.location.lineText.trim()),
|
|
28
|
-
React.createElement(Box, null,
|
|
29
|
-
React.createElement(Text, null, "|"),
|
|
30
|
-
React.createElement(Box, { paddingLeft: error.location.character +
|
|
31
|
-
error.location.lineText.trim().length -
|
|
32
|
-
error.location.lineText.length +
|
|
33
|
-
1 },
|
|
34
|
-
React.createElement(Text, { color: "greenBright" }, "^")))))))));
|
|
35
|
-
});
|
|
36
|
-
export function renderTypeScriptErrors(errors) {
|
|
37
|
-
return errors.map((error, index) => React.createElement(Error, { key: `TypeScriptError-${index}`, error: error }));
|
|
38
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { useStdout } from "ink";
|
|
2
|
-
import React from "react";
|
|
3
|
-
export const useFullScreen = () => {
|
|
4
|
-
const { stdout } = useStdout();
|
|
5
|
-
const [columns, setColumns] = React.useState(stdout.columns);
|
|
6
|
-
const [rows, setRows] = React.useState(stdout.rows);
|
|
7
|
-
React.useEffect(() => {
|
|
8
|
-
const handleResize = () => {
|
|
9
|
-
setColumns(stdout.columns);
|
|
10
|
-
setRows(stdout.rows);
|
|
11
|
-
};
|
|
12
|
-
stdout.addListener("resize", handleResize);
|
|
13
|
-
stdout.write("\x1b[?1049h");
|
|
14
|
-
process.on("beforeExit", () => {
|
|
15
|
-
stdout.write("\x1b[?1049l");
|
|
16
|
-
});
|
|
17
|
-
return () => {
|
|
18
|
-
stdout.removeListener("resize", handleResize);
|
|
19
|
-
};
|
|
20
|
-
}, []);
|
|
21
|
-
return { width: columns, height: rows };
|
|
22
|
-
};
|