giggles 0.6.1 → 0.6.2
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/README.md +81 -1
- package/dist/{chunk-A7BRQXWE.js → chunk-TWXBZE5C.js} +24 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +4 -4
- package/dist/terminal/index.d.ts +7 -6
- package/dist/ui/index.js +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# giggles
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<img src="https://github.com/user-attachments/assets/c5c7ef05-232f-4180-8b85-0160fb0f083a" width="700" alt="giggles">
|
|
8
8
|
|
|
9
9
|
giggles is a batteries-included react framework for building terminal apps. built on ink, it handles focus, input routing, screen navigation, and theming out of the box so you can skip the plumbing and build.
|
|
10
10
|
|
|
@@ -30,3 +30,83 @@ npx create-giggles-app
|
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
see [giggles.zzzzion.com](https://giggles.zzzzion.com) for API documentation and live demos.
|
|
33
|
+
|
|
34
|
+
## giggles/ui
|
|
35
|
+
|
|
36
|
+
### [select](https://giggles.zzzzion.com/ui/select)
|
|
37
|
+
|
|
38
|
+
<img src="https://github.com/user-attachments/assets/8ce13f75-7a7b-4123-a973-f2992193bf84" width="500" alt="select">
|
|
39
|
+
|
|
40
|
+
### [multi select](https://giggles.zzzzion.com/ui/multi-select)
|
|
41
|
+
|
|
42
|
+
<img src="https://github.com/user-attachments/assets/24f5d625-6e46-4cb1-8d22-42d40eb48f56" width="500" alt="multi-select">
|
|
43
|
+
|
|
44
|
+
### [markdown](https://giggles.zzzzion.com/ui/markdown)
|
|
45
|
+
|
|
46
|
+
<img src="https://github.com/user-attachments/assets/1cdb6e84-c714-470a-8cf0-b6abf68b78a9" width="500" alt="markdown">
|
|
47
|
+
|
|
48
|
+
### [text input](https://giggles.zzzzion.com/ui/text-input)
|
|
49
|
+
|
|
50
|
+
<img src="https://github.com/user-attachments/assets/b56056ca-97e2-4dc2-a1eb-2ee3f4d559e7" width="500" alt="text-input">
|
|
51
|
+
|
|
52
|
+
### [viewport](https://giggles.zzzzion.com/ui/viewport)
|
|
53
|
+
|
|
54
|
+
<img src="https://github.com/user-attachments/assets/56c6cb6b-b2a7-4803-bed4-c6c6c34042c3" width="500" alt="viewport">
|
|
55
|
+
|
|
56
|
+
### [code block](https://giggles.zzzzion.com/ui/codeblock)
|
|
57
|
+
|
|
58
|
+
<img src="https://github.com/user-attachments/assets/283dbd7e-326c-4acb-b8c0-d3608722952b" width="500" alt="codeblock">
|
|
59
|
+
|
|
60
|
+
### [confirm](https://giggles.zzzzion.com/ui/confirm)
|
|
61
|
+
|
|
62
|
+
<img src="https://github.com/user-attachments/assets/b887da72-bf02-4084-b846-8b90cc3c3487" width="500" alt="confirm">
|
|
63
|
+
|
|
64
|
+
### [spinner](https://giggles.zzzzion.com/ui/spinner)
|
|
65
|
+
|
|
66
|
+
<img src="https://github.com/user-attachments/assets/71aef7f8-e53b-4876-864f-b9b1a5100c5d" width="500" alt="spinner">
|
|
67
|
+
|
|
68
|
+
### [modal](https://giggles.zzzzion.com/ui/modal)
|
|
69
|
+
|
|
70
|
+
<img src="https://github.com/user-attachments/assets/7415c554-927e-4b5c-91d7-7e3b1f4ea0ca" width="500" alt="modal">
|
|
71
|
+
|
|
72
|
+
### [paginator](https://giggles.zzzzion.com/ui/paginator)
|
|
73
|
+
|
|
74
|
+
<img src="https://github.com/user-attachments/assets/b0780f46-848e-4881-822a-86d7db02d212" width="500" alt="paginator">
|
|
75
|
+
|
|
76
|
+
### [autocomplete](https://giggles.zzzzion.com/ui/autocomplete)
|
|
77
|
+
|
|
78
|
+
<img src="https://github.com/user-attachments/assets/aa76dd7a-5357-4969-a979-95975b5ec578" width="500" alt="autocomplete">
|
|
79
|
+
|
|
80
|
+
### [command palette](https://giggles.zzzzion.com/ui/command-palette)
|
|
81
|
+
|
|
82
|
+
<img src="https://github.com/user-attachments/assets/30886cb5-986f-4477-85c1-61cba4b499aa" width="500" alt="command-palette">
|
|
83
|
+
|
|
84
|
+
### [virtual list](https://giggles.zzzzion.com/ui/virtual-list)
|
|
85
|
+
|
|
86
|
+
<img src="https://github.com/user-attachments/assets/d3ef1d92-813c-4546-8d60-2c38745ddbbc" width="500" alt="virtual-list">
|
|
87
|
+
|
|
88
|
+
### [badge](https://giggles.zzzzion.com/ui/badge)
|
|
89
|
+
|
|
90
|
+
<img src="https://github.com/user-attachments/assets/b144c3f5-8b3b-4236-abf2-fc239d23f0c6" width="500" alt="badge">
|
|
91
|
+
|
|
92
|
+
### [panel](https://giggles.zzzzion.com/ui/panel)
|
|
93
|
+
|
|
94
|
+
<img src="https://github.com/user-attachments/assets/9831d73a-baa9-410a-b933-e0dfd9433604" width="500" alt="panel">
|
|
95
|
+
|
|
96
|
+
## giggles/terminal
|
|
97
|
+
|
|
98
|
+
### [useShellOut](https://giggles.zzzzion.com/terminal#useshellout)
|
|
99
|
+
|
|
100
|
+
suspend the UI, hand off the terminal to an external program like `vim` or `less`, and resume cleanly when it exits
|
|
101
|
+
|
|
102
|
+
### [useSpawn](https://giggles.zzzzion.com/terminal#usespawn)
|
|
103
|
+
|
|
104
|
+
spawn a child process and stream its stdout/stderr output into your UI — with support for colored output via a pty
|
|
105
|
+
|
|
106
|
+
### [useTerminalSize](https://giggles.zzzzion.com/terminal#useterminalsize)
|
|
107
|
+
|
|
108
|
+
reactively track the terminal's current dimensions (rows and columns), updating on resize
|
|
109
|
+
|
|
110
|
+
### [useTerminalFocus](https://giggles.zzzzion.com/terminal#useterminalfocus)
|
|
111
|
+
|
|
112
|
+
detect when the terminal window gains or loses focus
|
|
@@ -150,12 +150,25 @@ function useFocusScope(options) {
|
|
|
150
150
|
store.unregisterKeybindings(id, keybindingRegistrationId);
|
|
151
151
|
};
|
|
152
152
|
}, [id, keybindingRegistrationId, store]);
|
|
153
|
-
|
|
153
|
+
useEffect4(() => {
|
|
154
|
+
if (!store.hasFocusScopeComponent(id)) {
|
|
155
|
+
throw new GigglesError(
|
|
156
|
+
"useFocusScope() was called but no <FocusScope handle={scope}> was rendered. Every useFocusScope() call requires a corresponding <FocusScope> in the render output \u2014 without it, child components register under the wrong parent scope and keyboard navigation silently breaks."
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}, [id, store]);
|
|
160
|
+
return { id, hasFocus, isPassive, next, prev, nextShallow, prevShallow, escape, drillIn };
|
|
154
161
|
}
|
|
155
162
|
|
|
156
163
|
// src/core/focus/FocusScope.tsx
|
|
164
|
+
import { useEffect as useEffect5 } from "react";
|
|
157
165
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
158
166
|
function FocusScope({ handle, children }) {
|
|
167
|
+
const store = useStore();
|
|
168
|
+
useEffect5(() => {
|
|
169
|
+
store.registerFocusScopeComponent(handle.id);
|
|
170
|
+
return () => store.unregisterFocusScopeComponent(handle.id);
|
|
171
|
+
}, [handle.id, store]);
|
|
159
172
|
return /* @__PURE__ */ jsx3(ScopeIdContext.Provider, { value: handle.id, children });
|
|
160
173
|
}
|
|
161
174
|
|
|
@@ -191,6 +204,7 @@ var FocusStore = class {
|
|
|
191
204
|
passiveSet = /* @__PURE__ */ new Set();
|
|
192
205
|
pendingFocusFirstChild = /* @__PURE__ */ new Set();
|
|
193
206
|
trapNodeId = null;
|
|
207
|
+
renderedScopes = /* @__PURE__ */ new Set();
|
|
194
208
|
listeners = /* @__PURE__ */ new Set();
|
|
195
209
|
version = 0;
|
|
196
210
|
// nodeId → registrationId → BindingRegistration
|
|
@@ -396,6 +410,15 @@ var FocusStore = class {
|
|
|
396
410
|
// ---------------------------------------------------------------------------
|
|
397
411
|
// Trap
|
|
398
412
|
// ---------------------------------------------------------------------------
|
|
413
|
+
registerFocusScopeComponent(id) {
|
|
414
|
+
this.renderedScopes.add(id);
|
|
415
|
+
}
|
|
416
|
+
unregisterFocusScopeComponent(id) {
|
|
417
|
+
this.renderedScopes.delete(id);
|
|
418
|
+
}
|
|
419
|
+
hasFocusScopeComponent(id) {
|
|
420
|
+
return this.renderedScopes.has(id);
|
|
421
|
+
}
|
|
399
422
|
setTrap(nodeId) {
|
|
400
423
|
this.trapNodeId = nodeId;
|
|
401
424
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -41,8 +41,6 @@ type FocusScopeHandle = {
|
|
|
41
41
|
id: string;
|
|
42
42
|
hasFocus: boolean;
|
|
43
43
|
isPassive: boolean;
|
|
44
|
-
};
|
|
45
|
-
type FocusScopeHelpers = {
|
|
46
44
|
next: () => void;
|
|
47
45
|
prev: () => void;
|
|
48
46
|
nextShallow: () => void;
|
|
@@ -50,6 +48,7 @@ type FocusScopeHelpers = {
|
|
|
50
48
|
escape: () => void;
|
|
51
49
|
drillIn: () => void;
|
|
52
50
|
};
|
|
51
|
+
type FocusScopeHelpers = Pick<FocusScopeHandle, 'next' | 'prev' | 'nextShallow' | 'prevShallow' | 'escape' | 'drillIn'>;
|
|
53
52
|
type FocusScopeOptions = {
|
|
54
53
|
parent?: FocusScopeHandle;
|
|
55
54
|
keybindings?: Keybindings | ((helpers: FocusScopeHelpers) => Keybindings);
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useTerminalSize
|
|
3
|
+
} from "./chunk-WNGBTD67.js";
|
|
1
4
|
import {
|
|
2
5
|
FocusScope,
|
|
3
6
|
FocusStore,
|
|
@@ -11,14 +14,11 @@ import {
|
|
|
11
14
|
useKeybindingRegistry,
|
|
12
15
|
useKeybindings,
|
|
13
16
|
useStore
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TWXBZE5C.js";
|
|
15
18
|
import {
|
|
16
19
|
ThemeProvider,
|
|
17
20
|
useTheme
|
|
18
21
|
} from "./chunk-C77VBSPK.js";
|
|
19
|
-
import {
|
|
20
|
-
useTerminalSize
|
|
21
|
-
} from "./chunk-WNGBTD67.js";
|
|
22
22
|
|
|
23
23
|
// src/core/GigglesProvider.tsx
|
|
24
24
|
import { useRef } from "react";
|
package/dist/terminal/index.d.ts
CHANGED
|
@@ -4,6 +4,11 @@ type TerminalSize = {
|
|
|
4
4
|
rows: number;
|
|
5
5
|
columns: number;
|
|
6
6
|
};
|
|
7
|
+
type ShellOutHandle = {
|
|
8
|
+
run: (command: string) => Promise<{
|
|
9
|
+
exitCode: number;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
7
12
|
type SpawnOptions = SpawnOptionsWithoutStdio & {
|
|
8
13
|
/**
|
|
9
14
|
* Inject FORCE_COLOR=1 and TERM=xterm-256color into the child process
|
|
@@ -28,12 +33,8 @@ declare function useTerminalSize(): TerminalSize;
|
|
|
28
33
|
|
|
29
34
|
declare function useTerminalFocus(callback: (focused: boolean) => void): void;
|
|
30
35
|
|
|
31
|
-
declare function useShellOut():
|
|
32
|
-
run: (command: string) => Promise<{
|
|
33
|
-
exitCode: number;
|
|
34
|
-
}>;
|
|
35
|
-
};
|
|
36
|
+
declare function useShellOut(): ShellOutHandle;
|
|
36
37
|
|
|
37
38
|
declare function useSpawn(): SpawnHandle;
|
|
38
39
|
|
|
39
|
-
export { type SpawnHandle, type SpawnOptions, type SpawnOutputLine, type TerminalSize, useShellOut, useSpawn, useTerminalFocus, useTerminalSize };
|
|
40
|
+
export { type ShellOutHandle, type SpawnHandle, type SpawnOptions, type SpawnOutputLine, type TerminalSize, useShellOut, useSpawn, useTerminalFocus, useTerminalSize };
|
package/dist/ui/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "giggles",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "tsup",
|
|
42
42
|
"build:watch": "nodemon --watch src --ext ts,tsx --exec tsup",
|
|
43
|
-
"play": "tsx --watch",
|
|
44
|
-
"record": "vhs",
|
|
43
|
+
"play": "f() { tsx --watch playground/examples/$1.tsx; }; f",
|
|
44
|
+
"record": "f() { vhs playground/tapes/$1.tape; }; f",
|
|
45
45
|
"dev:docs": "pnpm build && concurrently --kill-others \"pnpm build:watch\" \"pnpm --filter documentation dev\"",
|
|
46
46
|
"lint": "prettier --write . && eslint . --fix"
|
|
47
47
|
},
|