@kud/ink-ui 0.6.0 → 0.7.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/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;
@@ -207,4 +247,4 @@ declare const spacing: {
207
247
  };
208
248
  type Spacing = (typeof spacing)[keyof typeof spacing];
209
249
 
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 };
250
+ 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 { jsxs, jsx } from 'react/jsx-runtime';
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';
@@ -223,6 +223,148 @@ var TextInput = ({
223
223
  after
224
224
  ] });
225
225
  };
226
+ var defaultDomains = [
227
+ "gmail.com",
228
+ "outlook.com",
229
+ "hotmail.com",
230
+ "yahoo.com",
231
+ "icloud.com",
232
+ "proton.me"
233
+ ];
234
+ var EmailInput = ({
235
+ placeholder = "",
236
+ defaultValue = "",
237
+ domains = defaultDomains,
238
+ onChange,
239
+ onSubmit,
240
+ isDisabled = false
241
+ }) => {
242
+ const [value, setValue] = useState(defaultValue);
243
+ const [cursor, setCursor] = useState(defaultValue.length);
244
+ const at = value.indexOf("@");
245
+ const domainFragment = at === -1 ? "" : value.slice(at + 1);
246
+ const match = at !== -1 && domainFragment.length > 0 ? domains.find(
247
+ (d) => d.startsWith(domainFragment) && d !== domainFragment
248
+ ) : void 0;
249
+ const suggestion = match ? match.slice(domainFragment.length) : "";
250
+ const showSuggestion = suggestion.length > 0 && cursor === value.length;
251
+ const update = (nextValue, nextCursor) => {
252
+ setValue(nextValue);
253
+ setCursor(nextCursor);
254
+ onChange?.(nextValue);
255
+ };
256
+ useInput(
257
+ (input, key) => {
258
+ if (key.return) {
259
+ onSubmit?.(value);
260
+ return;
261
+ }
262
+ if (key.tab && showSuggestion) {
263
+ update(value + suggestion, value.length + suggestion.length);
264
+ return;
265
+ }
266
+ if (key.leftArrow) {
267
+ setCursor((c) => Math.max(0, c - 1));
268
+ return;
269
+ }
270
+ if (key.rightArrow) {
271
+ setCursor((c) => Math.min(value.length, c + 1));
272
+ return;
273
+ }
274
+ if (key.backspace || key.delete) {
275
+ if (cursor === 0) return;
276
+ update(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
277
+ return;
278
+ }
279
+ if (input && !key.ctrl && !key.meta && !key.tab) {
280
+ update(
281
+ value.slice(0, cursor) + input + value.slice(cursor),
282
+ cursor + input.length
283
+ );
284
+ }
285
+ },
286
+ { isActive: !isDisabled }
287
+ );
288
+ if (value.length === 0) {
289
+ return /* @__PURE__ */ jsxs(Text, { children: [
290
+ /* @__PURE__ */ jsx(Text, { inverse: true, children: " " }),
291
+ placeholder ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : null
292
+ ] });
293
+ }
294
+ if (showSuggestion) {
295
+ return /* @__PURE__ */ jsxs(Text, { children: [
296
+ value,
297
+ /* @__PURE__ */ jsx(Text, { inverse: true, children: suggestion.slice(0, 1) }),
298
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: suggestion.slice(1) })
299
+ ] });
300
+ }
301
+ const before = value.slice(0, cursor);
302
+ const atChar = value.slice(cursor, cursor + 1) || " ";
303
+ const after = value.slice(cursor + 1);
304
+ return /* @__PURE__ */ jsxs(Text, { children: [
305
+ before,
306
+ /* @__PURE__ */ jsx(Text, { inverse: true, children: atChar }),
307
+ after
308
+ ] });
309
+ };
310
+ var PasswordInput = ({
311
+ placeholder = "",
312
+ mask = "*",
313
+ onChange,
314
+ onSubmit,
315
+ isDisabled = false
316
+ }) => {
317
+ const [value, setValue] = useState("");
318
+ const [cursor, setCursor] = useState(0);
319
+ const update = (nextValue, nextCursor) => {
320
+ setValue(nextValue);
321
+ setCursor(nextCursor);
322
+ onChange?.(nextValue);
323
+ };
324
+ useInput(
325
+ (input, key) => {
326
+ if (key.return) {
327
+ onSubmit?.(value);
328
+ return;
329
+ }
330
+ if (key.leftArrow) {
331
+ setCursor((c) => Math.max(0, c - 1));
332
+ return;
333
+ }
334
+ if (key.rightArrow) {
335
+ setCursor((c) => Math.min(value.length, c + 1));
336
+ return;
337
+ }
338
+ if (key.backspace || key.delete) {
339
+ if (cursor === 0) return;
340
+ update(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
341
+ return;
342
+ }
343
+ if (input && !key.ctrl && !key.meta && !key.tab) {
344
+ update(
345
+ value.slice(0, cursor) + input + value.slice(cursor),
346
+ cursor + input.length
347
+ );
348
+ }
349
+ },
350
+ { isActive: !isDisabled }
351
+ );
352
+ if (value.length === 0) {
353
+ return /* @__PURE__ */ jsxs(Text, { children: [
354
+ /* @__PURE__ */ jsx(Text, { inverse: true, children: " " }),
355
+ placeholder ? /* @__PURE__ */ jsx(Text, { dimColor: true, children: placeholder }) : null
356
+ ] });
357
+ }
358
+ const masked = mask.repeat(value.length);
359
+ const before = masked.slice(0, cursor);
360
+ const at = masked.slice(cursor, cursor + 1) || " ";
361
+ const after = masked.slice(cursor + 1);
362
+ return /* @__PURE__ */ jsxs(Text, { children: [
363
+ before,
364
+ /* @__PURE__ */ jsx(Text, { inverse: true, children: at }),
365
+ after
366
+ ] });
367
+ };
226
368
  var ConfirmInput = ({
227
369
  defaultChoice = "confirm",
228
370
  onConfirm,
@@ -249,6 +391,49 @@ var ConfirmInput = ({
249
391
  const hint = defaultChoice === "confirm" ? "(Y/n)" : "(y/N)";
250
392
  return /* @__PURE__ */ jsx(Text, { dimColor: true, children: hint });
251
393
  };
394
+ var markers = ["\u25CF", "\u25CB", "\u25AA", "\u25AB"];
395
+ var DepthContext = createContext(0);
396
+ var UnorderedListItem = ({ children }) => {
397
+ const depth = useContext(DepthContext);
398
+ const marker = markers[Math.max(0, depth - 1) % markers.length];
399
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
400
+ /* @__PURE__ */ jsxs(Text, { children: [
401
+ marker,
402
+ " "
403
+ ] }),
404
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children })
405
+ ] });
406
+ };
407
+ var UnorderedListRoot = ({ children }) => {
408
+ const depth = useContext(DepthContext);
409
+ return /* @__PURE__ */ jsx(DepthContext.Provider, { value: depth + 1, children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children }) });
410
+ };
411
+ var UnorderedList = Object.assign(UnorderedListRoot, {
412
+ Item: UnorderedListItem
413
+ });
414
+ var OrderedListItem = ({ children, _index = 1 }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
415
+ /* @__PURE__ */ jsxs(Text, { children: [
416
+ _index,
417
+ ". "
418
+ ] }),
419
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children })
420
+ ] });
421
+ var OrderedListRoot = ({ children }) => {
422
+ let n = 0;
423
+ const numbered = React8.Children.map(children, (child) => {
424
+ if (React8.isValidElement(child) && child.type === OrderedListItem) {
425
+ n += 1;
426
+ return React8.cloneElement(child, {
427
+ _index: n
428
+ });
429
+ }
430
+ return child;
431
+ });
432
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: numbered });
433
+ };
434
+ var OrderedList = Object.assign(OrderedListRoot, {
435
+ Item: OrderedListItem
436
+ });
252
437
  var ScrollView = ({
253
438
  lines,
254
439
  showIndicator = true,
@@ -475,4 +660,4 @@ var notify = (message, options = {}) => {
475
660
  child.unref();
476
661
  };
477
662
 
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 };
663
+ 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.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "React component library for Ink CLIs",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",