@kud/ink-ui 0.6.0 → 0.8.0
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 +36 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +209 -17
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -13,11 +13,18 @@
|
|
|
13
13
|
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
|
-
- **
|
|
16
|
+
- **25 ready-made components**, pre-styled and ready to drop in:
|
|
17
|
+
- **Inputs** — `TextInput`, `EmailInput` (domain completion), `PasswordInput` (masked), `ConfirmInput`
|
|
18
|
+
- **Lists** — `UnorderedList`, `OrderedList` (both nestable), `Table`
|
|
19
|
+
- **Selection & navigation** — `Select`, `MultiSelect`, `Tabs`, `Switch`, `Toggle`, `SelectableRow`
|
|
20
|
+
- **Status & feedback** — `Spinner`, `ProgressBar`, `StatusMessage`, `Alert`, `Badge`, `Toast`
|
|
21
|
+
- **Layout & chrome** — `Banner`, `Header`, `FooterHints`, `KeyValue`, `LoadingScreen`, `ScrollView`
|
|
22
|
+
- **Full [@inkjs/ui](https://github.com/vadimdemedes/ink-ui) parity** — every upstream component has an equivalent, plus a dozen more the design system adds on top
|
|
23
|
+
- **Colourblind-safe by design** — state is signalled by shape, case, and glyph, never colour alone
|
|
17
24
|
- **Design tokens included** — a shared colour palette (`colors`) and spacing scale (`spacing`) to keep every screen consistent
|
|
18
25
|
- **Full TypeScript support** — ships compiled output with `.d.ts` declarations for every component and token type
|
|
19
26
|
- **ESM only, zero config** — no runtime bundling step; just import and render
|
|
20
|
-
- **Peer-dependency light** — only requires `ink ≥
|
|
27
|
+
- **Peer-dependency light** — only requires `ink ≥ 7` and `react ≥ 19`
|
|
21
28
|
|
|
22
29
|
## Install
|
|
23
30
|
|
|
@@ -50,6 +57,33 @@ const App = () => (
|
|
|
50
57
|
render(<App />)
|
|
51
58
|
```
|
|
52
59
|
|
|
60
|
+
Inputs report their value through `onChange`/`onSubmit`, and lists nest with a shape-distinct marker per level:
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { Text } from "ink"
|
|
64
|
+
import { EmailInput, PasswordInput, UnorderedList } from "@kud/ink-ui"
|
|
65
|
+
|
|
66
|
+
const SignUp = () => (
|
|
67
|
+
<>
|
|
68
|
+
<EmailInput placeholder="you@example.com" onSubmit={setEmail} />
|
|
69
|
+
<PasswordInput placeholder="Password" onSubmit={setPassword} />
|
|
70
|
+
<UnorderedList>
|
|
71
|
+
<UnorderedList.Item>
|
|
72
|
+
<Text>Choose a plan</Text>
|
|
73
|
+
<UnorderedList>
|
|
74
|
+
<UnorderedList.Item>
|
|
75
|
+
<Text>Free</Text>
|
|
76
|
+
</UnorderedList.Item>
|
|
77
|
+
<UnorderedList.Item>
|
|
78
|
+
<Text>Pro</Text>
|
|
79
|
+
</UnorderedList.Item>
|
|
80
|
+
</UnorderedList>
|
|
81
|
+
</UnorderedList.Item>
|
|
82
|
+
</UnorderedList>
|
|
83
|
+
</>
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
53
87
|
All components accept only the props they need — no theme provider or context required. Design tokens are plain objects:
|
|
54
88
|
|
|
55
89
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -94,6 +94,25 @@ type TextInputProps = {
|
|
|
94
94
|
};
|
|
95
95
|
declare const TextInput: ({ placeholder, defaultValue, onChange, onSubmit, isDisabled, }: TextInputProps) => React.JSX.Element;
|
|
96
96
|
|
|
97
|
+
type EmailInputProps = {
|
|
98
|
+
placeholder?: string;
|
|
99
|
+
defaultValue?: string;
|
|
100
|
+
domains?: string[];
|
|
101
|
+
onChange?: (value: string) => void;
|
|
102
|
+
onSubmit?: (value: string) => void;
|
|
103
|
+
isDisabled?: boolean;
|
|
104
|
+
};
|
|
105
|
+
declare const EmailInput: ({ placeholder, defaultValue, domains, onChange, onSubmit, isDisabled, }: EmailInputProps) => React.JSX.Element;
|
|
106
|
+
|
|
107
|
+
type PasswordInputProps = {
|
|
108
|
+
placeholder?: string;
|
|
109
|
+
mask?: string;
|
|
110
|
+
onChange?: (value: string) => void;
|
|
111
|
+
onSubmit?: (value: string) => void;
|
|
112
|
+
isDisabled?: boolean;
|
|
113
|
+
};
|
|
114
|
+
declare const PasswordInput: ({ placeholder, mask, onChange, onSubmit, isDisabled, }: PasswordInputProps) => React.JSX.Element;
|
|
115
|
+
|
|
97
116
|
type ConfirmInputProps = {
|
|
98
117
|
defaultChoice?: "confirm" | "cancel";
|
|
99
118
|
onConfirm?: () => void;
|
|
@@ -102,6 +121,27 @@ type ConfirmInputProps = {
|
|
|
102
121
|
};
|
|
103
122
|
declare const ConfirmInput: ({ defaultChoice, onConfirm, onCancel, isDisabled, }: ConfirmInputProps) => React.JSX.Element;
|
|
104
123
|
|
|
124
|
+
type ItemProps$1 = {
|
|
125
|
+
children: React.ReactNode;
|
|
126
|
+
};
|
|
127
|
+
type UnorderedListProps = {
|
|
128
|
+
children: React.ReactNode;
|
|
129
|
+
};
|
|
130
|
+
declare const UnorderedList: (({ children }: UnorderedListProps) => React.JSX.Element) & {
|
|
131
|
+
Item: ({ children }: ItemProps$1) => React.JSX.Element;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
type ItemProps = {
|
|
135
|
+
children: React.ReactNode;
|
|
136
|
+
_index?: number;
|
|
137
|
+
};
|
|
138
|
+
type OrderedListProps = {
|
|
139
|
+
children: React.ReactNode;
|
|
140
|
+
};
|
|
141
|
+
declare const OrderedList: (({ children }: OrderedListProps) => React.JSX.Element) & {
|
|
142
|
+
Item: ({ children, _index }: ItemProps) => React.JSX.Element;
|
|
143
|
+
};
|
|
144
|
+
|
|
105
145
|
type Span = {
|
|
106
146
|
text: string;
|
|
107
147
|
color?: string;
|
|
@@ -120,8 +160,9 @@ type ScrollViewProps = {
|
|
|
120
160
|
lines: StyledLine[];
|
|
121
161
|
showIndicator?: boolean;
|
|
122
162
|
initialStart?: number;
|
|
163
|
+
isActive?: boolean;
|
|
123
164
|
};
|
|
124
|
-
declare const ScrollView: ({ lines, showIndicator, initialStart, }: ScrollViewProps) => React.JSX.Element;
|
|
165
|
+
declare const ScrollView: ({ lines, showIndicator, initialStart, isActive, }: ScrollViewProps) => React.JSX.Element;
|
|
125
166
|
|
|
126
167
|
type TabItem<T extends string = string> = {
|
|
127
168
|
value: T;
|
|
@@ -207,4 +248,4 @@ declare const spacing: {
|
|
|
207
248
|
};
|
|
208
249
|
type Spacing = (typeof spacing)[keyof typeof spacing];
|
|
209
250
|
|
|
210
|
-
export { Alert, Badge, type BadgeVariant, Banner, type Color, type Column, ConfirmInput, FooterHints, Header, type Hint, type IconMode, KeyValue, LoadingScreen, MultiSelect, type NotifyOptions, ProgressBar, ScrollView, Select, type SelectOption, SelectableRow, type Spacing, type Span, Spinner, StatusMessage, type StatusVariant, type StyledLine, Switch, type SwitchValue, type TabItem, Table, Tabs, TextInput, Toast, Toggle, colors, getIconMode, notify, setIconMode, spacing };
|
|
251
|
+
export { Alert, Badge, type BadgeVariant, Banner, type Color, type Column, ConfirmInput, EmailInput, FooterHints, Header, type Hint, type IconMode, KeyValue, LoadingScreen, MultiSelect, type NotifyOptions, OrderedList, PasswordInput, ProgressBar, ScrollView, Select, type SelectOption, SelectableRow, type Spacing, type Span, Spinner, StatusMessage, type StatusVariant, type StyledLine, Switch, type SwitchValue, type TabItem, Table, Tabs, TextInput, Toast, Toggle, UnorderedList, colors, getIconMode, notify, setIconMode, spacing };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Text, useInput, measureElement } from 'ink';
|
|
2
|
-
import {
|
|
3
|
-
import { useState, useEffect, useRef, useLayoutEffect } from 'react';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import React8, { createContext, useContext, useState, useEffect, useRef, useLayoutEffect } from 'react';
|
|
4
4
|
import cliSpinners from 'cli-spinners';
|
|
5
5
|
import { glyphs } from '@kud/glyphs';
|
|
6
6
|
import { spawn } from 'child_process';
|
|
@@ -115,7 +115,10 @@ var Select = ({
|
|
|
115
115
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
116
116
|
visible.map((option, i) => {
|
|
117
117
|
const active = start + i === cursor;
|
|
118
|
-
return /* @__PURE__ */
|
|
118
|
+
return /* @__PURE__ */ jsxs(SelectableRow, { active, children: [
|
|
119
|
+
/* @__PURE__ */ jsx(Text, { bold: active, color: active ? colors.info : void 0, children: option.label }),
|
|
120
|
+
active ? /* @__PURE__ */ jsx(Text, { color: colors.success, children: " \u2713" }) : null
|
|
121
|
+
] }, option.value);
|
|
119
122
|
}),
|
|
120
123
|
options.length > count && /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2026 ${options.length} total` })
|
|
121
124
|
] });
|
|
@@ -159,8 +162,8 @@ var MultiSelect = ({
|
|
|
159
162
|
const active = start + i === cursor;
|
|
160
163
|
const on = selected.has(option.value);
|
|
161
164
|
return /* @__PURE__ */ jsxs(SelectableRow, { active, children: [
|
|
162
|
-
/* @__PURE__ */ jsx(Text, { color:
|
|
163
|
-
/* @__PURE__ */ jsx(Text, {
|
|
165
|
+
/* @__PURE__ */ jsx(Text, { bold: active, color: active ? colors.info : void 0, children: option.label }),
|
|
166
|
+
on ? /* @__PURE__ */ jsx(Text, { color: colors.success, children: " \u2713" }) : null
|
|
164
167
|
] }, option.value);
|
|
165
168
|
}),
|
|
166
169
|
options.length > count && /* @__PURE__ */ jsx(Text, { dimColor: true, children: ` \u2026 ${options.length} total` })
|
|
@@ -223,6 +226,148 @@ var TextInput = ({
|
|
|
223
226
|
after
|
|
224
227
|
] });
|
|
225
228
|
};
|
|
229
|
+
var defaultDomains = [
|
|
230
|
+
"gmail.com",
|
|
231
|
+
"outlook.com",
|
|
232
|
+
"hotmail.com",
|
|
233
|
+
"yahoo.com",
|
|
234
|
+
"icloud.com",
|
|
235
|
+
"proton.me"
|
|
236
|
+
];
|
|
237
|
+
var EmailInput = ({
|
|
238
|
+
placeholder = "",
|
|
239
|
+
defaultValue = "",
|
|
240
|
+
domains = defaultDomains,
|
|
241
|
+
onChange,
|
|
242
|
+
onSubmit,
|
|
243
|
+
isDisabled = false
|
|
244
|
+
}) => {
|
|
245
|
+
const [value, setValue] = useState(defaultValue);
|
|
246
|
+
const [cursor, setCursor] = useState(defaultValue.length);
|
|
247
|
+
const at = value.indexOf("@");
|
|
248
|
+
const domainFragment = at === -1 ? "" : value.slice(at + 1);
|
|
249
|
+
const match = at !== -1 && domainFragment.length > 0 ? domains.find(
|
|
250
|
+
(d) => d.startsWith(domainFragment) && d !== domainFragment
|
|
251
|
+
) : void 0;
|
|
252
|
+
const suggestion = match ? match.slice(domainFragment.length) : "";
|
|
253
|
+
const showSuggestion = suggestion.length > 0 && cursor === value.length;
|
|
254
|
+
const update = (nextValue, nextCursor) => {
|
|
255
|
+
setValue(nextValue);
|
|
256
|
+
setCursor(nextCursor);
|
|
257
|
+
onChange?.(nextValue);
|
|
258
|
+
};
|
|
259
|
+
useInput(
|
|
260
|
+
(input, key) => {
|
|
261
|
+
if (key.return) {
|
|
262
|
+
onSubmit?.(value);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (key.tab && showSuggestion) {
|
|
266
|
+
update(value + suggestion, value.length + suggestion.length);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (key.leftArrow) {
|
|
270
|
+
setCursor((c) => Math.max(0, c - 1));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (key.rightArrow) {
|
|
274
|
+
setCursor((c) => Math.min(value.length, c + 1));
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (key.backspace || key.delete) {
|
|
278
|
+
if (cursor === 0) return;
|
|
279
|
+
update(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (input && !key.ctrl && !key.meta && !key.tab) {
|
|
283
|
+
update(
|
|
284
|
+
value.slice(0, cursor) + input + value.slice(cursor),
|
|
285
|
+
cursor + input.length
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
{ isActive: !isDisabled }
|
|
290
|
+
);
|
|
291
|
+
if (value.length === 0) {
|
|
292
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
293
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: " " }),
|
|
294
|
+
placeholder ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : null
|
|
295
|
+
] });
|
|
296
|
+
}
|
|
297
|
+
if (showSuggestion) {
|
|
298
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
299
|
+
value,
|
|
300
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: suggestion.slice(0, 1) }),
|
|
301
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: suggestion.slice(1) })
|
|
302
|
+
] });
|
|
303
|
+
}
|
|
304
|
+
const before = value.slice(0, cursor);
|
|
305
|
+
const atChar = value.slice(cursor, cursor + 1) || " ";
|
|
306
|
+
const after = value.slice(cursor + 1);
|
|
307
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
308
|
+
before,
|
|
309
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: atChar }),
|
|
310
|
+
after
|
|
311
|
+
] });
|
|
312
|
+
};
|
|
313
|
+
var PasswordInput = ({
|
|
314
|
+
placeholder = "",
|
|
315
|
+
mask = "*",
|
|
316
|
+
onChange,
|
|
317
|
+
onSubmit,
|
|
318
|
+
isDisabled = false
|
|
319
|
+
}) => {
|
|
320
|
+
const [value, setValue] = useState("");
|
|
321
|
+
const [cursor, setCursor] = useState(0);
|
|
322
|
+
const update = (nextValue, nextCursor) => {
|
|
323
|
+
setValue(nextValue);
|
|
324
|
+
setCursor(nextCursor);
|
|
325
|
+
onChange?.(nextValue);
|
|
326
|
+
};
|
|
327
|
+
useInput(
|
|
328
|
+
(input, key) => {
|
|
329
|
+
if (key.return) {
|
|
330
|
+
onSubmit?.(value);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (key.leftArrow) {
|
|
334
|
+
setCursor((c) => Math.max(0, c - 1));
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
if (key.rightArrow) {
|
|
338
|
+
setCursor((c) => Math.min(value.length, c + 1));
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (key.backspace || key.delete) {
|
|
342
|
+
if (cursor === 0) return;
|
|
343
|
+
update(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (input && !key.ctrl && !key.meta && !key.tab) {
|
|
347
|
+
update(
|
|
348
|
+
value.slice(0, cursor) + input + value.slice(cursor),
|
|
349
|
+
cursor + input.length
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
{ isActive: !isDisabled }
|
|
354
|
+
);
|
|
355
|
+
if (value.length === 0) {
|
|
356
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
357
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: " " }),
|
|
358
|
+
placeholder ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : null
|
|
359
|
+
] });
|
|
360
|
+
}
|
|
361
|
+
const masked = mask.repeat(value.length);
|
|
362
|
+
const before = masked.slice(0, cursor);
|
|
363
|
+
const at = masked.slice(cursor, cursor + 1) || " ";
|
|
364
|
+
const after = masked.slice(cursor + 1);
|
|
365
|
+
return /* @__PURE__ */ jsxs(Text, { children: [
|
|
366
|
+
before,
|
|
367
|
+
/* @__PURE__ */ jsx(Text, { inverse: true, children: at }),
|
|
368
|
+
after
|
|
369
|
+
] });
|
|
370
|
+
};
|
|
226
371
|
var ConfirmInput = ({
|
|
227
372
|
defaultChoice = "confirm",
|
|
228
373
|
onConfirm,
|
|
@@ -249,10 +394,54 @@ var ConfirmInput = ({
|
|
|
249
394
|
const hint = defaultChoice === "confirm" ? "(Y/n)" : "(y/N)";
|
|
250
395
|
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint });
|
|
251
396
|
};
|
|
397
|
+
var markers = ["\u25CF", "\u25CB", "\u25AA", "\u25AB"];
|
|
398
|
+
var DepthContext = createContext(0);
|
|
399
|
+
var UnorderedListItem = ({ children }) => {
|
|
400
|
+
const depth = useContext(DepthContext);
|
|
401
|
+
const marker = markers[Math.max(0, depth - 1) % markers.length];
|
|
402
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
403
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
404
|
+
marker,
|
|
405
|
+
" "
|
|
406
|
+
] }),
|
|
407
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children })
|
|
408
|
+
] });
|
|
409
|
+
};
|
|
410
|
+
var UnorderedListRoot = ({ children }) => {
|
|
411
|
+
const depth = useContext(DepthContext);
|
|
412
|
+
return /* @__PURE__ */ jsx(DepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children }) });
|
|
413
|
+
};
|
|
414
|
+
var UnorderedList = Object.assign(UnorderedListRoot, {
|
|
415
|
+
Item: UnorderedListItem
|
|
416
|
+
});
|
|
417
|
+
var OrderedListItem = ({ children, _index = 1 }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
418
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
419
|
+
_index,
|
|
420
|
+
". "
|
|
421
|
+
] }),
|
|
422
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children })
|
|
423
|
+
] });
|
|
424
|
+
var OrderedListRoot = ({ children }) => {
|
|
425
|
+
let n = 0;
|
|
426
|
+
const numbered = React8.Children.map(children, (child) => {
|
|
427
|
+
if (React8.isValidElement(child) && child.type === OrderedListItem) {
|
|
428
|
+
n += 1;
|
|
429
|
+
return React8.cloneElement(child, {
|
|
430
|
+
_index: n
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
return child;
|
|
434
|
+
});
|
|
435
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: numbered });
|
|
436
|
+
};
|
|
437
|
+
var OrderedList = Object.assign(OrderedListRoot, {
|
|
438
|
+
Item: OrderedListItem
|
|
439
|
+
});
|
|
252
440
|
var ScrollView = ({
|
|
253
441
|
lines,
|
|
254
442
|
showIndicator = true,
|
|
255
|
-
initialStart = 0
|
|
443
|
+
initialStart = 0,
|
|
444
|
+
isActive = true
|
|
256
445
|
}) => {
|
|
257
446
|
const ref = useRef(null);
|
|
258
447
|
const [height, setHeight] = useState(1);
|
|
@@ -265,16 +454,19 @@ var ScrollView = ({
|
|
|
265
454
|
});
|
|
266
455
|
const maxStart = Math.max(0, lines.length - height);
|
|
267
456
|
const clamped = Math.min(start, maxStart);
|
|
268
|
-
useInput(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
457
|
+
useInput(
|
|
458
|
+
(input, key) => {
|
|
459
|
+
if (key.downArrow || input === "j")
|
|
460
|
+
setStart((s) => Math.min(maxStart, s + 1));
|
|
461
|
+
if (key.upArrow || input === "k") setStart((s) => Math.max(0, s - 1));
|
|
462
|
+
if (input === " " || key.pageDown || input === "f")
|
|
463
|
+
setStart((s) => Math.min(maxStart, s + height));
|
|
464
|
+
if (key.pageUp || input === "b") setStart((s) => Math.max(0, s - height));
|
|
465
|
+
if (input === "g") setStart(0);
|
|
466
|
+
if (input === "G") setStart(maxStart);
|
|
467
|
+
},
|
|
468
|
+
{ isActive }
|
|
469
|
+
);
|
|
278
470
|
const visible = lines.slice(clamped, clamped + height);
|
|
279
471
|
const hasMore = lines.length > height;
|
|
280
472
|
const atEnd = clamped >= maxStart;
|
|
@@ -475,4 +667,4 @@ var notify = (message, options = {}) => {
|
|
|
475
667
|
child.unref();
|
|
476
668
|
};
|
|
477
669
|
|
|
478
|
-
export { Alert, Badge, Banner, ConfirmInput, FooterHints, Header, KeyValue, LoadingScreen, MultiSelect, ProgressBar, ScrollView, Select, SelectableRow, Spinner, StatusMessage, Switch, Table, Tabs, TextInput, Toast, Toggle, colors, getIconMode, notify, setIconMode, spacing };
|
|
670
|
+
export { Alert, Badge, Banner, ConfirmInput, EmailInput, FooterHints, Header, KeyValue, LoadingScreen, MultiSelect, OrderedList, PasswordInput, ProgressBar, ScrollView, Select, SelectableRow, Spinner, StatusMessage, Switch, Table, Tabs, TextInput, Toast, Toggle, UnorderedList, colors, getIconMode, notify, setIconMode, spacing };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/ink-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "React component library for Ink CLIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"build": "tsup",
|
|
22
22
|
"dev": "tsup --watch",
|
|
23
|
+
"demo": "tsx src/demo/index.tsx",
|
|
23
24
|
"typecheck": "tsc --noEmit",
|
|
24
25
|
"test": "vitest run",
|
|
25
26
|
"test:watch": "vitest"
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"react": "19.2.7",
|
|
42
43
|
"react-devtools-core": "7.0.1",
|
|
43
44
|
"tsup": "8.5.1",
|
|
45
|
+
"tsx": "4.23.1",
|
|
44
46
|
"typescript": "5.9.3",
|
|
45
47
|
"vitest": "4.1.10"
|
|
46
48
|
},
|