@shopify/cli-kit 3.46.2 → 3.47.0-pre.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.
Files changed (79) hide show
  1. package/assets/cli-ruby/lib/graphql/extension_create.graphql +1 -0
  2. package/assets/cli-ruby/lib/graphql/extension_update_draft.graphql +1 -0
  3. package/assets/cli-ruby/lib/graphql/get_extension_registrations.graphql +1 -0
  4. package/assets/cli-ruby/lib/shopify_cli/theme/dev_server/cdn_fonts.rb +8 -3
  5. package/assets/cli-ruby/lib/shopify_cli/theme/dev_server/local_assets.rb +13 -4
  6. package/assets/cli-ruby/lib/shopify_cli/theme/dev_server.rb +1 -1
  7. package/assets/cli-ruby/lib/shopify_cli/theme/extension/dev_server/local_assets.rb +2 -1
  8. package/assets/cli-ruby/lib/shopify_cli/theme/extension/dev_server.rb +1 -1
  9. package/assets/cli-ruby/lib/shopify_cli/theme/repl/auth_dev_server.rb +1 -1
  10. package/dist/private/node/api.d.ts +1 -1
  11. package/dist/private/node/api.js +1 -1
  12. package/dist/private/node/api.js.map +1 -1
  13. package/dist/private/node/session/exchange.d.ts +1 -0
  14. package/dist/private/node/session/exchange.js +3 -1
  15. package/dist/private/node/session/exchange.js.map +1 -1
  16. package/dist/private/node/session/identity.js +12 -0
  17. package/dist/private/node/session/identity.js.map +1 -1
  18. package/dist/private/node/session/scopes.js +5 -1
  19. package/dist/private/node/session/scopes.js.map +1 -1
  20. package/dist/private/node/session.d.ts +7 -0
  21. package/dist/private/node/session.js +8 -1
  22. package/dist/private/node/session.js.map +1 -1
  23. package/dist/private/node/ui/components/Alert.js +7 -12
  24. package/dist/private/node/ui/components/Alert.js.map +1 -1
  25. package/dist/private/node/ui/components/AutocompletePrompt.js +7 -10
  26. package/dist/private/node/ui/components/AutocompletePrompt.js.map +1 -1
  27. package/dist/private/node/ui/components/Banner.js +9 -11
  28. package/dist/private/node/ui/components/Banner.js.map +1 -1
  29. package/dist/private/node/ui/components/Banner.test.js +63 -29
  30. package/dist/private/node/ui/components/Banner.test.js.map +1 -1
  31. package/dist/private/node/ui/components/ConcurrentOutput.js +5 -6
  32. package/dist/private/node/ui/components/ConcurrentOutput.js.map +1 -1
  33. package/dist/private/node/ui/components/FatalError.js +8 -11
  34. package/dist/private/node/ui/components/FatalError.js.map +1 -1
  35. package/dist/private/node/ui/components/List.js +2 -4
  36. package/dist/private/node/ui/components/List.js.map +1 -1
  37. package/dist/private/node/ui/components/List.test.js +32 -0
  38. package/dist/private/node/ui/components/List.test.js.map +1 -1
  39. package/dist/private/node/ui/components/Prompts/InfoTable.js +2 -3
  40. package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
  41. package/dist/private/node/ui/components/SelectInput.d.ts +9 -7
  42. package/dist/private/node/ui/components/SelectInput.js +41 -61
  43. package/dist/private/node/ui/components/SelectInput.js.map +1 -1
  44. package/dist/private/node/ui/components/SelectInput.test.js +205 -62
  45. package/dist/private/node/ui/components/SelectInput.test.js.map +1 -1
  46. package/dist/private/node/ui/components/SelectPrompt.js +4 -16
  47. package/dist/private/node/ui/components/SelectPrompt.js.map +1 -1
  48. package/dist/private/node/ui/components/SelectPrompt.test.js +29 -0
  49. package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
  50. package/dist/private/node/ui/components/TextAnimation.d.ts +2 -2
  51. package/dist/private/node/ui/components/TextAnimation.js +4 -3
  52. package/dist/private/node/ui/components/TextAnimation.js.map +1 -1
  53. package/dist/private/node/ui/hooks/use-select-state.d.ts +85 -0
  54. package/dist/private/node/ui/hooks/use-select-state.js +180 -0
  55. package/dist/private/node/ui/hooks/use-select-state.js.map +1 -0
  56. package/dist/private/node/ui.js +2 -1
  57. package/dist/private/node/ui.js.map +1 -1
  58. package/dist/public/common/version.d.ts +1 -1
  59. package/dist/public/common/version.js +1 -1
  60. package/dist/public/common/version.js.map +1 -1
  61. package/dist/public/node/api/business-platform.d.ts +10 -0
  62. package/dist/public/node/api/business-platform.js +25 -0
  63. package/dist/public/node/api/business-platform.js.map +1 -0
  64. package/dist/public/node/context/fqdn.d.ts +6 -0
  65. package/dist/public/node/context/fqdn.js +17 -0
  66. package/dist/public/node/context/fqdn.js.map +1 -1
  67. package/dist/public/node/metadata.d.ts +1 -1
  68. package/dist/public/node/metadata.js.map +1 -1
  69. package/dist/public/node/monorail.d.ts +2 -1
  70. package/dist/public/node/monorail.js +1 -1
  71. package/dist/public/node/monorail.js.map +1 -1
  72. package/dist/public/node/session.d.ts +7 -0
  73. package/dist/public/node/session.js +16 -0
  74. package/dist/public/node/session.js.map +1 -1
  75. package/dist/public/node/ui.d.ts +2 -2
  76. package/dist/public/node/ui.js +2 -2
  77. package/dist/public/node/ui.js.map +1 -1
  78. package/dist/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +2 -2
@@ -2,12 +2,11 @@ import { SelectInput } from './SelectInput.js';
2
2
  import { InfoTable } from './Prompts/InfoTable.js';
3
3
  import { TextInput } from './TextInput.js';
4
4
  import { TokenizedText } from './TokenizedText.js';
5
- import { handleCtrlC } from '../../ui.js';
6
5
  import { messageWithPunctuation } from '../utilities.js';
7
6
  import { debounce } from '../../../../public/common/function.js';
8
7
  import useAbortSignal from '../hooks/use-abort-signal.js';
9
8
  import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
10
- import { Box, measureElement, Text, useApp, useInput, useStdout } from 'ink';
9
+ import { Box, measureElement, Text, useApp, useStdout } from 'ink';
11
10
  import figures from 'figures';
12
11
  import ansiEscapes from 'ansi-escapes';
13
12
  import { uniqBy } from '@shopify/cli-kit/common/array';
@@ -68,19 +67,19 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
68
67
  };
69
68
  }, [wrapperHeight, selectInputHeight, searchResults.length, stdout, limit, numberOfGroups]);
70
69
  const { isAborted } = useAbortSignal(abortSignal);
71
- useInput((input, key) => {
72
- handleCtrlC(input, key);
73
- if (key.return && promptState === PromptState.Idle && answer) {
70
+ const submitAnswer = useCallback((answer) => {
71
+ if (promptState === PromptState.Idle) {
74
72
  // -1 is for the last row with the terminal cursor
75
73
  if (stdout && wrapperHeight >= stdout.rows - 1) {
76
74
  stdout.write(ansiEscapes.clearTerminal);
77
75
  }
76
+ setAnswer(answer);
78
77
  setPromptState(PromptState.Submitted);
79
78
  setSearchTerm('');
80
79
  unmountInk();
81
80
  onSubmit(answer.value);
82
81
  }
83
- });
82
+ }, [promptState, stdout, wrapperHeight, onSubmit, unmountInk]);
84
83
  const setLoadingWhenSlow = useRef();
85
84
  // we want to set it each time so that searchTermRef always tracks searchTerm,
86
85
  // this is NOT the same as writing useRef(searchTerm)
@@ -137,11 +136,9 @@ function AutocompletePrompt({ message, choices: initialChoices, infoTable, onSub
137
136
  React.createElement(Box, { marginRight: 2 },
138
137
  React.createElement(Text, { color: "cyan" }, figures.tick)),
139
138
  React.createElement(Text, { color: "cyan" }, answer.label))) : (React.createElement(Box, { marginTop: 1 },
140
- React.createElement(SelectInput, { items: searchResults, onChange: ({ item }) => {
141
- setAnswer(item);
142
- }, enableShortcuts: false, emptyMessage: "No results found.", highlightedTerm: searchTerm, loading: promptState === PromptState.Loading, errorMessage: promptState === PromptState.Error
139
+ React.createElement(SelectInput, { items: searchResults, enableShortcuts: false, emptyMessage: "No results found.", highlightedTerm: searchTerm, loading: promptState === PromptState.Loading, errorMessage: promptState === PromptState.Error
143
140
  ? 'There has been an error while searching. Please try again later.'
144
- : undefined, hasMorePages: hasMorePages, morePagesMessage: "Find what you're looking for by typing its name.", ref: inputRef, limit: limit })))));
141
+ : undefined, hasMorePages: hasMorePages, morePagesMessage: "Find what you're looking for by typing its name.", ref: inputRef, limit: limit, onSubmit: submitAnswer })))));
145
142
  }
146
143
  export { AutocompletePrompt };
147
144
  //# sourceMappingURL=AutocompletePrompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTable, InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport {debounce} from '../../../../public/common/function.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {ReactElement, useCallback, useLayoutEffect, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useInput, useStdout} from 'ink'\nimport figures from 'figures'\nimport ansiEscapes from 'ansi-escapes'\nimport {uniqBy} from '@shopify/cli-kit/common/array'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: string\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n abortSignal?: AbortSignal\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n abortSignal,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const canSearch = initialChoices.length >= PAGE_SIZE\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n const [wrapperHeight, setWrapperHeight] = useState(0)\n const [selectInputHeight, setSelectInputHeight] = useState(0)\n const [limit, setLimit] = useState(searchResults.length)\n const numberOfGroups = uniqBy(\n searchResults.filter((choice) => choice.group),\n 'group',\n ).length\n\n const paginatedSearch = useCallback(\n async (term: string) => {\n const results = await search(term)\n results.data = results.data.slice(0, PAGE_SIZE)\n return results\n },\n [search],\n )\n\n const wrapperRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setWrapperHeight(height)\n }\n }, [])\n\n const inputRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setSelectInputHeight(height)\n }\n }, [])\n\n useLayoutEffect(() => {\n function onResize() {\n const availableSpace = stdout.rows - (wrapperHeight - selectInputHeight)\n // rough estimate of the limit needed based on the space available\n const newLimit = Math.max(2, availableSpace - numberOfGroups * 2 - 4)\n\n if (newLimit < limit) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n\n setLimit(Math.min(newLimit, searchResults.length))\n }\n\n onResize()\n\n stdout.on('resize', onResize)\n return () => {\n stdout.off('resize', onResize)\n }\n }, [wrapperHeight, selectInputHeight, searchResults.length, stdout, limit, numberOfGroups])\n\n const {isAborted} = useAbortSignal(abortSignal)\n\n useInput((input, key) => {\n handleCtrlC(input, key)\n\n if (key.return && promptState === PromptState.Idle && answer) {\n // -1 is for the last row with the terminal cursor\n if (stdout && wrapperHeight >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n })\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n // disable exhaustive-deps because we want to memoize the debounce function itself\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const debounceSearch = useCallback(\n debounce((term: string) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n setHasMorePages(initialHasMorePages)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n }, 300),\n [initialHasMorePages, paginatedInitialChoices, paginatedSearch],\n )\n\n return isAborted ? null : (\n <Box flexDirection=\"column\" marginBottom={1} ref={wrapperRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <TokenizedText item={messageWithPunctuation(message)} />\n {promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted ? (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n ) : null}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n onChange={({item}) => {\n setAnswer(item)\n }}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n ref={inputRef}\n limit={limit}\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
1
+ {"version":3,"file":"AutocompletePrompt.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/AutocompletePrompt.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SelectInput, SelectInputProps, Item as SelectItem} from './SelectInput.js'\nimport {InfoTable, InfoTableProps} from './Prompts/InfoTable.js'\nimport {TextInput} from './TextInput.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {messageWithPunctuation} from '../utilities.js'\nimport {debounce} from '../../../../public/common/function.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {ReactElement, useCallback, useLayoutEffect, useRef, useState} from 'react'\nimport {Box, measureElement, Text, useApp, useStdout} from 'ink'\nimport figures from 'figures'\nimport ansiEscapes from 'ansi-escapes'\nimport {uniqBy} from '@shopify/cli-kit/common/array'\n\nexport interface SearchResults<T> {\n data: SelectItem<T>[]\n meta?: {\n hasNextPage: boolean\n }\n}\n\nexport interface AutocompletePromptProps<T> {\n message: string\n choices: SelectInputProps<T>['items']\n onSubmit: (value: T) => void\n infoTable?: InfoTableProps['table']\n hasMorePages?: boolean\n search: (term: string) => Promise<SearchResults<T>>\n abortSignal?: AbortSignal\n}\n\nenum PromptState {\n Idle = 'idle',\n Loading = 'loading',\n Submitted = 'submitted',\n Error = 'error',\n}\n\nconst PAGE_SIZE = 25\n\n// eslint-disable-next-line react/function-component-definition\nfunction AutocompletePrompt<T>({\n message,\n choices: initialChoices,\n infoTable,\n onSubmit,\n search,\n hasMorePages: initialHasMorePages = false,\n abortSignal,\n}: React.PropsWithChildren<AutocompletePromptProps<T>>): ReactElement | null {\n const paginatedInitialChoices = initialChoices.slice(0, PAGE_SIZE)\n const [answer, setAnswer] = useState<SelectItem<T> | undefined>(paginatedInitialChoices[0])\n const {exit: unmountInk} = useApp()\n const [promptState, setPromptState] = useState<PromptState>(PromptState.Idle)\n const [searchTerm, setSearchTerm] = useState('')\n const [searchResults, setSearchResults] = useState<SelectItem<T>[]>(paginatedInitialChoices.slice(0, PAGE_SIZE))\n const {stdout} = useStdout()\n const canSearch = initialChoices.length >= PAGE_SIZE\n const [hasMorePages, setHasMorePages] = useState(initialHasMorePages)\n const [wrapperHeight, setWrapperHeight] = useState(0)\n const [selectInputHeight, setSelectInputHeight] = useState(0)\n const [limit, setLimit] = useState(searchResults.length)\n const numberOfGroups = uniqBy(\n searchResults.filter((choice) => choice.group),\n 'group',\n ).length\n\n const paginatedSearch = useCallback(\n async (term: string) => {\n const results = await search(term)\n results.data = results.data.slice(0, PAGE_SIZE)\n return results\n },\n [search],\n )\n\n const wrapperRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setWrapperHeight(height)\n }\n }, [])\n\n const inputRef = useCallback((node) => {\n if (node !== null) {\n const {height} = measureElement(node)\n setSelectInputHeight(height)\n }\n }, [])\n\n useLayoutEffect(() => {\n function onResize() {\n const availableSpace = stdout.rows - (wrapperHeight - selectInputHeight)\n // rough estimate of the limit needed based on the space available\n const newLimit = Math.max(2, availableSpace - numberOfGroups * 2 - 4)\n\n if (newLimit < limit) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n\n setLimit(Math.min(newLimit, searchResults.length))\n }\n\n onResize()\n\n stdout.on('resize', onResize)\n return () => {\n stdout.off('resize', onResize)\n }\n }, [wrapperHeight, selectInputHeight, searchResults.length, stdout, limit, numberOfGroups])\n\n const {isAborted} = useAbortSignal(abortSignal)\n\n const submitAnswer = useCallback(\n (answer: SelectItem<T>) => {\n if (promptState === PromptState.Idle) {\n // -1 is for the last row with the terminal cursor\n if (stdout && wrapperHeight >= stdout.rows - 1) {\n stdout.write(ansiEscapes.clearTerminal)\n }\n setAnswer(answer)\n setPromptState(PromptState.Submitted)\n setSearchTerm('')\n unmountInk()\n onSubmit(answer.value)\n }\n },\n [promptState, stdout, wrapperHeight, onSubmit, unmountInk],\n )\n\n const setLoadingWhenSlow = useRef<NodeJS.Timeout>()\n\n // we want to set it each time so that searchTermRef always tracks searchTerm,\n // this is NOT the same as writing useRef(searchTerm)\n const searchTermRef = useRef('')\n searchTermRef.current = searchTerm\n\n // disable exhaustive-deps because we want to memoize the debounce function itself\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const debounceSearch = useCallback(\n debounce((term: string) => {\n setLoadingWhenSlow.current = setTimeout(() => {\n setPromptState(PromptState.Loading)\n }, 100)\n paginatedSearch(term)\n .then((result) => {\n // while we were waiting for the promise to resolve, the user\n // has emptied the search term, so we want to show the default\n // choices instead\n if (searchTermRef.current.length === 0) {\n setSearchResults(paginatedInitialChoices)\n setHasMorePages(initialHasMorePages)\n } else {\n setSearchResults(result.data)\n setHasMorePages(result.meta?.hasNextPage ?? false)\n }\n\n setPromptState(PromptState.Idle)\n })\n .catch(() => {\n setPromptState(PromptState.Error)\n })\n .finally(() => {\n clearTimeout(setLoadingWhenSlow.current)\n })\n }, 300),\n [initialHasMorePages, paginatedInitialChoices, paginatedSearch],\n )\n\n return isAborted ? null : (\n <Box flexDirection=\"column\" marginBottom={1} ref={wrapperRef}>\n <Box>\n <Box marginRight={2}>\n <Text>?</Text>\n </Box>\n <TokenizedText item={messageWithPunctuation(message)} />\n {promptState !== PromptState.Submitted && canSearch ? (\n <Box marginLeft={3}>\n <TextInput\n value={searchTerm}\n onChange={(term) => {\n setSearchTerm(term)\n\n if (term.length > 0) {\n debounceSearch(term)\n } else {\n debounceSearch.cancel()\n setPromptState(PromptState.Idle)\n setSearchResults(paginatedInitialChoices)\n }\n }}\n placeholder=\"Type to search...\"\n />\n </Box>\n ) : null}\n </Box>\n\n {infoTable && promptState !== PromptState.Submitted ? (\n <Box marginLeft={7} marginTop={1}>\n <InfoTable table={infoTable} />\n </Box>\n ) : null}\n\n {promptState === PromptState.Submitted ? (\n <Box>\n <Box marginRight={2}>\n <Text color=\"cyan\">{figures.tick}</Text>\n </Box>\n\n <Text color=\"cyan\">{answer!.label}</Text>\n </Box>\n ) : (\n <Box marginTop={1}>\n <SelectInput\n items={searchResults}\n enableShortcuts={false}\n emptyMessage=\"No results found.\"\n highlightedTerm={searchTerm}\n loading={promptState === PromptState.Loading}\n errorMessage={\n promptState === PromptState.Error\n ? 'There has been an error while searching. Please try again later.'\n : undefined\n }\n hasMorePages={hasMorePages}\n morePagesMessage=\"Find what you're looking for by typing its name.\"\n ref={inputRef}\n limit={limit}\n onSubmit={submitAnswer}\n />\n </Box>\n )}\n </Box>\n )\n}\n\nexport {AutocompletePrompt}\n"]}
@@ -38,10 +38,10 @@ const BoxWithBorder = ({ type, children }) => {
38
38
  return newId;
39
39
  },
40
40
  } },
41
- React.createElement(Box, { width: twoThirds, paddingY: 1, paddingX: 2, marginBottom: 1, borderStyle: "round", flexDirection: "column", borderColor: typeToColor(type) },
42
- React.createElement(Box, { marginTop: -2, marginBottom: 1, marginLeft: -1 },
41
+ React.createElement(Box, { width: twoThirds, marginBottom: 1, borderStyle: "round", flexDirection: "column", borderColor: typeToColor(type) },
42
+ React.createElement(Box, { marginTop: -1, marginLeft: 1 },
43
43
  React.createElement(Text, null, ` ${type.replace(/_/g, ' ')} `)),
44
- children),
44
+ React.createElement(Box, { flexDirection: "column", paddingY: 1, paddingX: 2, gap: 1 }, children)),
45
45
  React.createElement(Footnotes, null)));
46
46
  };
47
47
  const BoxWithTopBottomLines = ({ type, children }) => {
@@ -50,15 +50,13 @@ const BoxWithTopBottomLines = ({ type, children }) => {
50
50
  let topLineAfterTypeLength = twoThirds - 2 - type.length - 2;
51
51
  if (topLineAfterTypeLength < 0)
52
52
  topLineAfterTypeLength = 0;
53
- return (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
54
- React.createElement(Box, { marginBottom: 1 },
55
- React.createElement(Text, null,
56
- React.createElement(Text, { color: typeToColor(type) }, ''.repeat(2)),
57
- React.createElement(Text, null, ` ${type.replace(/_/g, ' ')} `),
58
- React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(topLineAfterTypeLength)))),
53
+ return (React.createElement(Box, { flexDirection: "column", marginBottom: 1, gap: 1 },
54
+ React.createElement(Text, null,
55
+ React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(2)),
56
+ React.createElement(Text, null, ` ${type.replace(/_/g, ' ')} `),
57
+ React.createElement(Text, { color: typeToColor(type) }, ''.repeat(topLineAfterTypeLength))),
59
58
  children,
60
- React.createElement(Box, { marginTop: 1 },
61
- React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(twoThirds)))));
59
+ React.createElement(Text, { color: typeToColor(type) }, '─'.repeat(twoThirds))));
62
60
  };
63
61
  const Banner = ({ children, ...props }) => {
64
62
  if (props.type === 'external_error') {
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"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","sourcesContent":["import useLayout from '../hooks/use-layout.js'\nimport {Link, LinksContext} from '../contexts/LinksContext.js'\nimport {Box, Text} from 'ink'\nimport React, {FunctionComponent, useContext, useRef} from 'react'\n\nexport type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error'\n\ninterface BannerProps {\n type: BannerType\n}\n\nfunction typeToColor(type: BannerProps['type']) {\n return {\n success: 'green',\n error: 'red',\n warning: 'yellow',\n info: 'dim',\n external_error: 'red',\n }[type]\n}\n\nconst Footnotes = () => {\n const linksContext = useContext(LinksContext)\n\n if (linksContext === null || linksContext.links.current === null) {\n return null\n }\n\n const links = linksContext.links.current\n const linkIds = Object.keys(links)\n\n return linkIds.length > 0 ? (\n <Box marginBottom={1} marginTop={-1} flexDirection=\"column\">\n {linkIds.map((id) => (\n <Text key={id}>{`[${id}] ${links[id]?.url}`}</Text>\n ))}\n </Box>\n ) : null\n}\n\nconst BoxWithBorder: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n const links = useRef<{[key: string]: Link}>({})\n\n return (\n <LinksContext.Provider\n value={{\n links,\n addLink: (label, url) => {\n const id: string | undefined = Object.keys(links.current).find((id) => links.current[id]!.url === url)\n if (id) {\n return id\n }\n const newId = (Object.keys(links.current).length + 1).toString()\n links.current = {\n ...links.current,\n [newId]: {label, url},\n }\n return newId\n },\n }}\n >\n <Box\n width={twoThirds}\n paddingY={1}\n paddingX={2}\n marginBottom={1}\n borderStyle=\"round\"\n flexDirection=\"column\"\n borderColor={typeToColor(type)}\n >\n <Box marginTop={-2} marginBottom={1} marginLeft={-1}>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n </Box>\n {children}\n </Box>\n <Footnotes />\n </LinksContext.Provider>\n )\n}\n\nconst BoxWithTopBottomLines: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n // 2 initial dashes + 2 spaces surrounding the type\n let topLineAfterTypeLength = twoThirds - 2 - type.length - 2\n if (topLineAfterTypeLength < 0) topLineAfterTypeLength = 0\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box marginBottom={1}>\n <Text>\n <Text color={typeToColor(type)}>{'─'.repeat(2)}</Text>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n <Text color={typeToColor(type)}>{'─'.repeat(topLineAfterTypeLength)}</Text>\n </Text>\n </Box>\n\n {children}\n\n <Box marginTop={1}>\n <Text color={typeToColor(type)}>{'─'.repeat(twoThirds)}</Text>\n </Box>\n </Box>\n )\n}\n\nconst Banner: FunctionComponent<BannerProps> = ({children, ...props}) => {\n if (props.type === 'external_error') {\n return React.createElement(BoxWithTopBottomLines, props, children)\n } else {\n return React.createElement(BoxWithBorder, props, children)\n }\n}\n\nexport {Banner}\n"]}
1
+ {"version":3,"file":"Banner.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.tsx"],"names":[],"mappings":"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","sourcesContent":["import useLayout from '../hooks/use-layout.js'\nimport {Link, LinksContext} from '../contexts/LinksContext.js'\nimport {Box, Text} from 'ink'\nimport React, {FunctionComponent, useContext, useRef} from 'react'\n\nexport type BannerType = 'success' | 'error' | 'warning' | 'info' | 'external_error'\n\ninterface BannerProps {\n type: BannerType\n}\n\nfunction typeToColor(type: BannerProps['type']) {\n return {\n success: 'green',\n error: 'red',\n warning: 'yellow',\n info: 'dim',\n external_error: 'red',\n }[type]\n}\n\nconst Footnotes = () => {\n const linksContext = useContext(LinksContext)\n\n if (linksContext === null || linksContext.links.current === null) {\n return null\n }\n\n const links = linksContext.links.current\n const linkIds = Object.keys(links)\n\n return linkIds.length > 0 ? (\n <Box marginBottom={1} marginTop={-1} flexDirection=\"column\">\n {linkIds.map((id) => (\n <Text key={id}>{`[${id}] ${links[id]?.url}`}</Text>\n ))}\n </Box>\n ) : null\n}\n\nconst BoxWithBorder: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n const links = useRef<{[key: string]: Link}>({})\n\n return (\n <LinksContext.Provider\n value={{\n links,\n addLink: (label, url) => {\n const id: string | undefined = Object.keys(links.current).find((id) => links.current[id]!.url === url)\n if (id) {\n return id\n }\n const newId = (Object.keys(links.current).length + 1).toString()\n links.current = {\n ...links.current,\n [newId]: {label, url},\n }\n return newId\n },\n }}\n >\n <Box\n width={twoThirds}\n marginBottom={1}\n borderStyle=\"round\"\n flexDirection=\"column\"\n borderColor={typeToColor(type)}\n >\n <Box marginTop={-1} marginLeft={1}>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n </Box>\n <Box flexDirection=\"column\" paddingY={1} paddingX={2} gap={1}>\n {children}\n </Box>\n </Box>\n <Footnotes />\n </LinksContext.Provider>\n )\n}\n\nconst BoxWithTopBottomLines: FunctionComponent<BannerProps> = ({type, children}) => {\n const {twoThirds} = useLayout()\n // 2 initial dashes + 2 spaces surrounding the type\n let topLineAfterTypeLength = twoThirds - 2 - type.length - 2\n if (topLineAfterTypeLength < 0) topLineAfterTypeLength = 0\n\n return (\n <Box flexDirection=\"column\" marginBottom={1} gap={1}>\n <Text>\n <Text color={typeToColor(type)}>{'─'.repeat(2)}</Text>\n <Text>{` ${type.replace(/_/g, ' ')} `}</Text>\n <Text color={typeToColor(type)}>{'─'.repeat(topLineAfterTypeLength)}</Text>\n </Text>\n\n {children}\n\n <Text color={typeToColor(type)}>{'─'.repeat(twoThirds)}</Text>\n </Box>\n )\n}\n\nconst Banner: FunctionComponent<BannerProps> = ({children, ...props}) => {\n if (props.type === 'external_error') {\n return React.createElement(BoxWithTopBottomLines, props, children)\n } else {\n return React.createElement(BoxWithBorder, props, children)\n }\n}\n\nexport {Banner}\n"]}
@@ -1,55 +1,89 @@
1
1
  import { Banner } from './Banner.js';
2
+ import { List } from './List.js';
2
3
  import { render } from '../../testing/ui.js';
3
4
  import { describe, expect, test } from 'vitest';
4
5
  import React from 'react';
6
+ import { Text } from 'ink';
7
+ import { unstyled } from '@shopify/cli-kit/node/output';
5
8
  describe('Banner', async () => {
6
- test('renders with a border for success', async () => {
7
- const { lastFrame } = render(React.createElement(Banner, { type: "success" }));
8
- expect(lastFrame()).toMatchInlineSnapshot(`
9
- "╭─ success ────────────────────────────────────────────────────────────────────╮
10
- │ │
11
- │ │
12
- ╰──────────────────────────────────────────────────────────────────────────────╯
9
+ test('renders with a border for success with proper wrapping', async () => {
10
+ const { lastFrame } = render(React.createElement(Banner, { type: "success" },
11
+ React.createElement(List, { items: [
12
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
13
+ 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
14
+ ] })));
15
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
16
+ "╭─ success ────────────────────────────────────────────────────────────────────╮
17
+ │ │
18
+ │ • Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │
19
+ │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │
20
+ │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │
21
+ │ commodo consequat. │
22
+ │ • Duis aute irure dolor in reprehenderit in voluptate velit esse cillum │
23
+ │ dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non │
24
+ │ proident, sunt in culpa qui officia deserunt mollit anim id est │
25
+ │ laborum. │
26
+ │ │
27
+ ╰──────────────────────────────────────────────────────────────────────────────╯
13
28
  "
14
29
  `);
15
30
  });
16
31
  test('renders with a border for info', async () => {
17
- const { lastFrame } = render(React.createElement(Banner, { type: "info" }));
18
- expect(lastFrame()).toMatchInlineSnapshot(`
19
- "╭─ info ───────────────────────────────────────────────────────────────────────╮
20
- │ │
21
- │ │
22
- ╰──────────────────────────────────────────────────────────────────────────────╯
32
+ const { lastFrame } = render(React.createElement(Banner, { type: "info" },
33
+ React.createElement(Text, null, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")));
34
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
35
+ "╭─ info ───────────────────────────────────────────────────────────────────────╮
36
+
37
+ │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │
38
+ │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │
39
+ │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │
40
+ │ commodo consequat. │
41
+ │ │
42
+ ╰──────────────────────────────────────────────────────────────────────────────╯
23
43
  "
24
44
  `);
25
45
  });
26
46
  test('renders with a border for warning', async () => {
27
- const { lastFrame } = render(React.createElement(Banner, { type: "warning" }));
28
- expect(lastFrame()).toMatchInlineSnapshot(`
29
- "╭─ warning ────────────────────────────────────────────────────────────────────╮
30
- │ │
31
- │ │
32
- ╰──────────────────────────────────────────────────────────────────────────────╯
47
+ const { lastFrame } = render(React.createElement(Banner, { type: "warning" },
48
+ React.createElement(Text, null, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")));
49
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
50
+ "╭─ warning ────────────────────────────────────────────────────────────────────╮
51
+
52
+ │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │
53
+ │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │
54
+ │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │
55
+ │ commodo consequat. │
56
+ │ │
57
+ ╰──────────────────────────────────────────────────────────────────────────────╯
33
58
  "
34
59
  `);
35
60
  });
36
61
  test('renders with a border for error', async () => {
37
- const { lastFrame } = render(React.createElement(Banner, { type: "error" }));
38
- expect(lastFrame()).toMatchInlineSnapshot(`
39
- "╭─ error ──────────────────────────────────────────────────────────────────────╮
40
- │ │
41
- │ │
42
- ╰──────────────────────────────────────────────────────────────────────────────╯
62
+ const { lastFrame } = render(React.createElement(Banner, { type: "error" },
63
+ React.createElement(Text, null, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")));
64
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
65
+ "╭─ error ──────────────────────────────────────────────────────────────────────╮
66
+
67
+ │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │
68
+ │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │
69
+ │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │
70
+ │ commodo consequat. │
71
+ │ │
72
+ ╰──────────────────────────────────────────────────────────────────────────────╯
43
73
  "
44
74
  `);
45
75
  });
46
76
  test('renders with a top and bottom lines only for external errors', async () => {
47
- const { lastFrame } = render(React.createElement(Banner, { type: "external_error" }));
48
- expect(lastFrame()).toMatchInlineSnapshot(`
49
- "── external error ──────────────────────────────────────────────────────────────
77
+ const { lastFrame } = render(React.createElement(Banner, { type: "external_error" },
78
+ React.createElement(Text, null, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.")));
79
+ expect(unstyled(lastFrame())).toMatchInlineSnapshot(`
80
+ "── external error ──────────────────────────────────────────────────────────────
50
81
 
82
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore
83
+ et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
84
+ aliquip ex ea commodo consequat.
51
85
 
52
- ────────────────────────────────────────────────────────────────────────────────
86
+ ────────────────────────────────────────────────────────────────────────────────
53
87
  "
54
88
  `);
55
89
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,QAAQ,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC5B,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS,GAAG,CAAC,CAAA;QAErD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAMzC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,MAAM,GAAG,CAAC,CAAA;QAClD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAMzC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS,GAAG,CAAC,CAAA;QACrD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAMzC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,OAAO,GAAG,CAAC,CAAA;QACnD,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAMzC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CAAC,oBAAC,MAAM,IAAC,IAAI,EAAC,gBAAgB,GAAG,CAAC,CAAA;QAE5D,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,qBAAqB,CAAC;;;;;;KAMzC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Banner} from './Banner.js'\nimport {render} from '../../testing/ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\n\ndescribe('Banner', async () => {\n test('renders with a border for success', async () => {\n const {lastFrame} = render(<Banner type=\"success\" />)\n\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[32m╭─\u001b[39m success \u001b[32m────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[32m│\u001b[39m \u001b[32m│\u001b[39m\n \u001b[32m│\u001b[39m \u001b[32m│\u001b[39m\n \u001b[32m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\n \"\n `)\n })\n\n test('renders with a border for info', async () => {\n const {lastFrame} = render(<Banner type=\"info\" />)\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[2m╭─\u001b[22m info \u001b[2m───────────────────────────────────────────────────────────────────────╮\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m│\u001b[22m \u001b[2m│\u001b[22m\n \u001b[2m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[22m\n \"\n `)\n })\n\n test('renders with a border for warning', async () => {\n const {lastFrame} = render(<Banner type=\"warning\" />)\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[33m╭─\u001b[39m warning \u001b[33m────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[33m│\u001b[39m \u001b[33m│\u001b[39m\n \u001b[33m│\u001b[39m \u001b[33m│\u001b[39m\n \u001b[33m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\n \"\n `)\n })\n\n test('renders with a border for error', async () => {\n const {lastFrame} = render(<Banner type=\"error\" />)\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[31m╭─\u001b[39m error \u001b[31m──────────────────────────────────────────────────────────────────────╮\u001b[39m\n \u001b[31m│\u001b[39m \u001b[31m│\u001b[39m\n \u001b[31m│\u001b[39m \u001b[31m│\u001b[39m\n \u001b[31m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[39m\n \"\n `)\n })\n\n test('renders with a top and bottom lines only for external errors', async () => {\n const {lastFrame} = render(<Banner type=\"external_error\" />)\n\n expect(lastFrame()).toMatchInlineSnapshot(`\n \"\u001b[31m──\u001b[39m external error \u001b[31m──────────────────────────────────────────────────────────────\u001b[39m\n\n\n \u001b[31m────────────────────────────────────────────────────────────────────────────────\u001b[39m\n \"\n `)\n })\n})\n"]}
1
+ {"version":3,"file":"Banner.test.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/Banner.test.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,MAAM,EAAC,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAC,MAAM,QAAQ,CAAA;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,KAAK,CAAA;AACxB,OAAO,EAAC,QAAQ,EAAC,MAAM,8BAA8B,CAAA;AAErD,QAAQ,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC5B,IAAI,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CACxB,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS;YACpB,oBAAC,IAAI,IACH,KAAK,EAAE;oBACL,yOAAyO;oBACzO,uNAAuN;iBACxN,GACD,CACK,CACV,CAAA;QAED,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;KAcpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CACxB,oBAAC,MAAM,IAAC,IAAI,EAAC,MAAM;YACjB,oBAAC,IAAI,kPAIE,CACA,CACV,CAAA;QACD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;KAUpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CACxB,oBAAC,MAAM,IAAC,IAAI,EAAC,SAAS;YACpB,oBAAC,IAAI,kPAIE,CACA,CACV,CAAA;QACD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;KAUpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CACxB,oBAAC,MAAM,IAAC,IAAI,EAAC,OAAO;YAClB,oBAAC,IAAI,kPAIE,CACA,CACV,CAAA;QACD,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;;KAUpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,CACxB,oBAAC,MAAM,IAAC,IAAI,EAAC,gBAAgB;YAC3B,oBAAC,IAAI,kPAIE,CACA,CACV,CAAA;QAED,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC;;;;;;;;;KASpD,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import {Banner} from './Banner.js'\nimport {List} from './List.js'\nimport {render} from '../../testing/ui.js'\nimport {describe, expect, test} from 'vitest'\nimport React from 'react'\nimport {Text} from 'ink'\nimport {unstyled} from '@shopify/cli-kit/node/output'\n\ndescribe('Banner', async () => {\n test('renders with a border for success with proper wrapping', async () => {\n const {lastFrame} = render(\n <Banner type=\"success\">\n <List\n items={[\n 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',\n 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',\n ]}\n />\n </Banner>,\n )\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ success ────────────────────────────────────────────────────────────────────╮\n │\n │ • Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │\n │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │\n │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │\n │ commodo consequat. │\n │ • Duis aute irure dolor in reprehenderit in voluptate velit esse cillum │\n │ dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non │\n │ proident, sunt in culpa qui officia deserunt mollit anim id est │\n │ laborum. │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders with a border for info', async () => {\n const {lastFrame} = render(\n <Banner type=\"info\">\n <Text>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n consequat.\n </Text>\n </Banner>,\n )\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ info ───────────────────────────────────────────────────────────────────────╮\n │\n │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │\n │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │\n │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │\n │ commodo consequat. │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders with a border for warning', async () => {\n const {lastFrame} = render(\n <Banner type=\"warning\">\n <Text>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n consequat.\n </Text>\n </Banner>,\n )\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ warning ────────────────────────────────────────────────────────────────────╮\n │\n │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │\n │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │\n │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │\n │ commodo consequat. │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders with a border for error', async () => {\n const {lastFrame} = render(\n <Banner type=\"error\">\n <Text>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n consequat.\n </Text>\n </Banner>,\n )\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"╭─ error ──────────────────────────────────────────────────────────────────────╮\n │\n │ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod │\n │ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim │\n │ veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea │\n │ commodo consequat. │\n │ │\n ╰──────────────────────────────────────────────────────────────────────────────╯\n \"\n `)\n })\n\n test('renders with a top and bottom lines only for external errors', async () => {\n const {lastFrame} = render(\n <Banner type=\"external_error\">\n <Text>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore\n magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n consequat.\n </Text>\n </Banner>,\n )\n\n expect(unstyled(lastFrame()!)).toMatchInlineSnapshot(`\n \"── external error ──────────────────────────────────────────────────────────────\n\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore\n et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut\n aliquip ex ea commodo consequat.\n\n ────────────────────────────────────────────────────────────────────────────────\n \"\n `)\n })\n})\n"]}
@@ -96,15 +96,14 @@ const ConcurrentOutput = ({ processes, abortSignal, showTimestamps = true, onInp
96
96
  });
97
97
  return (React.createElement(React.Fragment, null,
98
98
  React.createElement(Static, { items: processOutput }, (chunk, index) => {
99
- return (React.createElement(Box, { flexDirection: "column", key: index }, chunk.lines.map((line, index) => (React.createElement(Box, { key: index, flexDirection: "row" },
100
- showTimestamps ? (React.createElement(Box, null,
101
- React.createElement(Box, { marginRight: 1 },
102
- React.createElement(Text, { color: chunk.color }, new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''))),
99
+ return (React.createElement(Box, { flexDirection: "column", key: index }, chunk.lines.map((line, index) => (React.createElement(Box, { key: index, flexDirection: "row", gap: 1 },
100
+ showTimestamps ? (React.createElement(Box, { gap: 1 },
101
+ React.createElement(Text, { color: chunk.color }, new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')),
103
102
  React.createElement(Text, { bold: true, color: chunk.color }, figures.lineVertical))) : null,
104
- React.createElement(Box, { width: prefixColumnSize, marginX: 1 },
103
+ React.createElement(Box, { width: prefixColumnSize },
105
104
  React.createElement(Text, { color: chunk.color }, chunk.prefix)),
106
105
  React.createElement(Text, { bold: true, color: chunk.color }, figures.lineVertical),
107
- React.createElement(Box, { flexGrow: 1, paddingLeft: 1 },
106
+ React.createElement(Box, { flexGrow: 1 },
108
107
  React.createElement(Text, { color: chunk.color }, line)))))));
109
108
  }),
110
109
  footer ? (React.createElement(Box, { marginY: 1, flexDirection: "column", flexGrow: 1 },
@@ -1 +1 @@
1
- {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../public/node/output.js'\nimport useAsyncAndUnmount from '../hooks/use-async-and-unmount.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {addOrUpdateConcurrentUIEventOutput} from '../../demo-recorder.js'\nimport {treeKill} from '../../tree-kill.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {FunctionComponent, useState} from 'react'\nimport {Box, Key, Static, Text, useInput, TextProps, useStdin} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport figures from 'figures'\nimport {Writable} from 'stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\n\ninterface Shortcut {\n key: string\n action: string\n}\nexport interface ConcurrentOutputProps {\n processes: OutputProcess[]\n abortSignal: AbortSignal\n showTimestamps?: boolean\n onInput?: (input: string, key: Key, exit: () => void) => void\n footer?: {\n shortcuts: Shortcut[]\n subTitle?: string\n }\n}\ninterface Chunk {\n color: TextProps['color']\n prefix: string\n lines: string[]\n}\n\nenum ConcurrentOutputState {\n Running = 'running',\n Stopped = 'stopped',\n}\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<ConcurrentOutputProps> = ({\n processes,\n abortSignal,\n showTimestamps = true,\n onInput,\n footer,\n}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const concurrentColors: TextProps['color'][] = ['yellow', 'cyan', 'magenta', 'green', 'blue']\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {isRawModeSupported} = useStdin()\n const [state, setState] = useState<ConcurrentOutputState>(ConcurrentOutputState.Running)\n\n function lineColor(index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n }\n\n const writableStream = (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('utf8').replace(/(\\n)$/, '')).split(/\\n/)\n addOrUpdateConcurrentUIEventOutput({prefix: process.prefix, index, output: lines.join('\\n')}, {footer})\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n }\n\n const runProcesses = () => {\n return Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortSignal)\n }),\n )\n }\n\n const {isAborted} = useAbortSignal(abortSignal)\n\n const useShortcuts = isRawModeSupported && state === ConcurrentOutputState.Running && !isAborted\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n onInput!(input, key, () => treeKill('SIGINT'))\n },\n {isActive: typeof onInput !== 'undefined' && useShortcuts},\n )\n\n useAsyncAndUnmount(runProcesses, {\n onFulfilled: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n onRejected: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n })\n\n return (\n <>\n <Static items={processOutput}>\n {(chunk, index) => {\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\">\n {showTimestamps ? (\n <Box>\n <Box marginRight={1}>\n <Text color={chunk.color}>\n {new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '')}\n </Text>\n </Box>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n </Box>\n ) : null}\n\n <Box width={prefixColumnSize} marginX={1}>\n <Text color={chunk.color}>{chunk.prefix}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n\n <Box flexGrow={1} paddingLeft={1}>\n <Text color={chunk.color}>{line}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n {footer ? (\n <Box marginY={1} flexDirection=\"column\" flexGrow={1}>\n {useShortcuts ? (\n <Box flexDirection=\"column\">\n {footer.shortcuts.map((shortcut, index) => (\n <Text key={index}>\n {figures.pointerSmall} Press <Text bold>{shortcut.key}</Text> {figures.lineVertical} {shortcut.action}\n </Text>\n ))}\n </Box>\n ) : null}\n {footer.subTitle ? (\n <Box marginTop={useShortcuts ? 1 : 0}>\n <Text>{footer.subTitle}</Text>\n </Box>\n ) : null}\n </Box>\n ) : null}\n </>\n )\n}\n\nexport {ConcurrentOutput}\n"]}
1
+ {"version":3,"file":"ConcurrentOutput.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/ConcurrentOutput.tsx"],"names":[],"mappings":"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","sourcesContent":["import {OutputProcess} from '../../../../public/node/output.js'\nimport useAsyncAndUnmount from '../hooks/use-async-and-unmount.js'\nimport {AbortSignal} from '../../../../public/node/abort.js'\nimport {handleCtrlC} from '../../ui.js'\nimport {addOrUpdateConcurrentUIEventOutput} from '../../demo-recorder.js'\nimport {treeKill} from '../../tree-kill.js'\nimport useAbortSignal from '../hooks/use-abort-signal.js'\nimport React, {FunctionComponent, useState} from 'react'\nimport {Box, Key, Static, Text, useInput, TextProps, useStdin} from 'ink'\nimport stripAnsi from 'strip-ansi'\nimport figures from 'figures'\nimport {Writable} from 'stream'\n\nexport type WritableStream = (process: OutputProcess, index: number) => Writable\n\ninterface Shortcut {\n key: string\n action: string\n}\nexport interface ConcurrentOutputProps {\n processes: OutputProcess[]\n abortSignal: AbortSignal\n showTimestamps?: boolean\n onInput?: (input: string, key: Key, exit: () => void) => void\n footer?: {\n shortcuts: Shortcut[]\n subTitle?: string\n }\n}\ninterface Chunk {\n color: TextProps['color']\n prefix: string\n lines: string[]\n}\n\nenum ConcurrentOutputState {\n Running = 'running',\n Stopped = 'stopped',\n}\n\n/**\n * Renders output from concurrent processes to the terminal.\n * Output will be divided in a three column layout\n * with the left column containing the timestamp,\n * the right column containing the output,\n * and the middle column containing the process prefix.\n * Every process will be rendered with a different color, up to 4 colors.\n *\n * For example running `shopify app dev`:\n *\n * ```shell\n * 2022-10-10 13:11:03 | backend | npm\n * 2022-10-10 13:11:03 | backend | WARN ignoring workspace config at ...\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | > shopify-app-template-node@0.1.0 dev\n * 2022-10-10 13:11:03 | backend | > cross-env NODE_ENV=development nodemon backend/index.js --watch ./backend\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend | > starter-react-frontend-app@0.1.0 dev\n * 2022-10-10 13:11:03 | frontend | > cross-env NODE_ENV=development node vite-server.js\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | frontend |\n * 2022-10-10 13:11:03 | backend |\n * 2022-10-10 13:11:03 | backend | [nodemon] to restart at any time, enter `rs`\n * 2022-10-10 13:11:03 | backend | [nodemon] watching path(s): backend/\n * 2022-10-10 13:11:03 | backend | [nodemon] watching extensions: js,mjs,json\n * 2022-10-10 13:11:03 | backend | [nodemon] starting `node backend/index.js`\n * 2022-10-10 13:11:03 | backend |\n *\n * ```\n */\nconst ConcurrentOutput: FunctionComponent<ConcurrentOutputProps> = ({\n processes,\n abortSignal,\n showTimestamps = true,\n onInput,\n footer,\n}) => {\n const [processOutput, setProcessOutput] = useState<Chunk[]>([])\n const concurrentColors: TextProps['color'][] = ['yellow', 'cyan', 'magenta', 'green', 'blue']\n const prefixColumnSize = Math.max(...processes.map((process) => process.prefix.length))\n const {isRawModeSupported} = useStdin()\n const [state, setState] = useState<ConcurrentOutputState>(ConcurrentOutputState.Running)\n\n function lineColor(index: number) {\n const colorIndex = index < concurrentColors.length ? index : index % concurrentColors.length\n return concurrentColors[colorIndex]!\n }\n\n const writableStream = (process: OutputProcess, index: number) => {\n return new Writable({\n write(chunk, _encoding, next) {\n const lines = stripAnsi(chunk.toString('utf8').replace(/(\\n)$/, '')).split(/\\n/)\n addOrUpdateConcurrentUIEventOutput({prefix: process.prefix, index, output: lines.join('\\n')}, {footer})\n\n setProcessOutput((previousProcessOutput) => [\n ...previousProcessOutput,\n {\n color: lineColor(index),\n prefix: process.prefix,\n lines,\n },\n ])\n\n next()\n },\n })\n }\n\n const runProcesses = () => {\n return Promise.all(\n processes.map(async (process, index) => {\n const stdout = writableStream(process, index)\n const stderr = writableStream(process, index)\n\n await process.action(stdout, stderr, abortSignal)\n }),\n )\n }\n\n const {isAborted} = useAbortSignal(abortSignal)\n\n const useShortcuts = isRawModeSupported && state === ConcurrentOutputState.Running && !isAborted\n\n useInput(\n (input, key) => {\n handleCtrlC(input, key)\n\n onInput!(input, key, () => treeKill('SIGINT'))\n },\n {isActive: typeof onInput !== 'undefined' && useShortcuts},\n )\n\n useAsyncAndUnmount(runProcesses, {\n onFulfilled: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n onRejected: () => {\n setState(ConcurrentOutputState.Stopped)\n },\n })\n\n return (\n <>\n <Static items={processOutput}>\n {(chunk, index) => {\n return (\n <Box flexDirection=\"column\" key={index}>\n {chunk.lines.map((line, index) => (\n <Box key={index} flexDirection=\"row\" gap={1}>\n {showTimestamps ? (\n <Box gap={1}>\n <Text color={chunk.color}>{new Date().toISOString().replace(/T/, ' ').replace(/\\..+/, '')}</Text>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n </Box>\n ) : null}\n\n <Box width={prefixColumnSize}>\n <Text color={chunk.color}>{chunk.prefix}</Text>\n </Box>\n\n <Text bold color={chunk.color}>\n {figures.lineVertical}\n </Text>\n\n <Box flexGrow={1}>\n <Text color={chunk.color}>{line}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n }}\n </Static>\n {footer ? (\n <Box marginY={1} flexDirection=\"column\" flexGrow={1}>\n {useShortcuts ? (\n <Box flexDirection=\"column\">\n {footer.shortcuts.map((shortcut, index) => (\n <Text key={index}>\n {figures.pointerSmall} Press <Text bold>{shortcut.key}</Text> {figures.lineVertical} {shortcut.action}\n </Text>\n ))}\n </Box>\n ) : null}\n {footer.subTitle ? (\n <Box marginTop={useShortcuts ? 1 : 0}>\n <Text>{footer.subTitle}</Text>\n </Box>\n ) : null}\n </Box>\n ) : null}\n </>\n )\n}\n\nexport {ConcurrentOutput}\n"]}
@@ -30,19 +30,16 @@ const FatalError = ({ error }) => {
30
30
  tool = `${error.command} ${error.args.join(' ')}`;
31
31
  }
32
32
  return (React.createElement(Banner, { type: tool ? 'external_error' : 'error' },
33
- tool ? (React.createElement(Box, { marginBottom: 1 },
34
- React.createElement(Text, null,
35
- "Error coming from ",
36
- React.createElement(Command, { command: tool })))) : null,
37
- React.createElement(Box, null, error.formattedMessage ? React.createElement(TokenizedText, { item: error.formattedMessage }) : React.createElement(Text, null, error.message)),
38
- error.tryMessage ? (React.createElement(Box, { marginTop: 1 },
39
- React.createElement(TokenizedText, { item: error.tryMessage }))) : null,
40
- error.nextSteps && error.nextSteps.length > 0 ? (React.createElement(Box, { marginTop: 1 },
41
- React.createElement(List, { title: "Next steps", items: error.nextSteps }))) : null,
42
- error.customSections && error.customSections.length > 0 ? (React.createElement(Box, { flexDirection: "column" }, error.customSections.map((section, index) => (React.createElement(Box, { key: index, flexDirection: "column", marginTop: 1 },
33
+ tool ? (React.createElement(Text, null,
34
+ "Error coming from ",
35
+ React.createElement(Command, { command: tool }))) : null,
36
+ error.formattedMessage ? React.createElement(TokenizedText, { item: error.formattedMessage }) : React.createElement(Text, null, error.message),
37
+ error.tryMessage ? React.createElement(TokenizedText, { item: error.tryMessage }) : null,
38
+ error.nextSteps && error.nextSteps.length > 0 ? React.createElement(List, { title: "Next steps", items: error.nextSteps }) : null,
39
+ error.customSections && error.customSections.length > 0 ? (React.createElement(Box, { flexDirection: "column", gap: 1 }, error.customSections.map((section, index) => (React.createElement(Box, { key: index, flexDirection: "column" },
43
40
  section.title ? React.createElement(Text, { bold: true }, section.title) : null,
44
41
  React.createElement(TokenizedText, { item: section.body })))))) : null,
45
- stack && stack.items.length !== 0 ? (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
42
+ stack && stack.items.length !== 0 ? (React.createElement(Box, { flexDirection: "column" },
46
43
  React.createElement(Text, null, "To investigate the issue, examine this stack trace:"),
47
44
  stack.items.map((item, index) => (React.createElement(Box, { flexDirection: "column", key: index, paddingLeft: 2 },
48
45
  React.createElement(Text, null,
@@ -1 +1 @@
1
- {"version":3,"file":"FatalError.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FatalError.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Banner} from './Banner.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {Command} from './Command.js'\nimport {List} from './List.js'\nimport {BugError, cleanSingleStackTracePath, ExternalError, FatalError as Fatal} from '../../../../public/node/error.js'\nimport {Box, Text} from 'ink'\nimport React, {FunctionComponent} from 'react'\nimport StackTracey from 'stacktracey'\n\nexport interface FatalErrorProps {\n error: Fatal\n}\n\nconst FatalError: FunctionComponent<FatalErrorProps> = ({error}) => {\n let stack\n let tool\n\n if (error instanceof BugError) {\n stack = new StackTracey(error)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = stack.withSources()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1]! : fileShortComponents[0]!\n return item\n })\n }\n\n if (error instanceof ExternalError) {\n tool = `${error.command} ${error.args.join(' ')}`\n }\n\n return (\n <Banner type={tool ? 'external_error' : 'error'}>\n {tool ? (\n <Box marginBottom={1}>\n <Text>\n Error coming from <Command command={tool} />\n </Text>\n </Box>\n ) : null}\n\n <Box>\n {error.formattedMessage ? <TokenizedText item={error.formattedMessage} /> : <Text>{error.message}</Text>}\n </Box>\n\n {error.tryMessage ? (\n <Box marginTop={1}>\n <TokenizedText item={error.tryMessage} />\n </Box>\n ) : null}\n\n {error.nextSteps && error.nextSteps.length > 0 ? (\n <Box marginTop={1}>\n <List title=\"Next steps\" items={error.nextSteps} />\n </Box>\n ) : null}\n\n {error.customSections && error.customSections.length > 0 ? (\n <Box flexDirection=\"column\">\n {error.customSections.map((section, index) => (\n <Box key={index} flexDirection=\"column\" marginTop={1}>\n {section.title ? <Text bold>{section.title}</Text> : null}\n <TokenizedText item={section.body} />\n </Box>\n ))}\n </Box>\n ) : null}\n\n {stack && stack.items.length !== 0 ? (\n <Box marginTop={1} flexDirection=\"column\">\n <Text>To investigate the issue, examine this stack trace:</Text>\n {stack.items.map((item, index) => (\n <Box flexDirection=\"column\" key={index} paddingLeft={2}>\n <Text>\n at{item.calleeShort ? <Text color=\"yellow\">{` ${item.calleeShort}`}</Text> : null}\n {item.fileShort ? ` (${item.fileShort}:${item.line})` : null}\n </Text>\n <Box paddingLeft={2}>\n <Text dimColor>{item.sourceLine?.trim()}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n ) : null}\n </Banner>\n )\n}\n\nexport {FatalError}\n"]}
1
+ {"version":3,"file":"FatalError.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/FatalError.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,QAAQ,EAAE,yBAAyB,EAAE,aAAa,EAAsB,MAAM,kCAAkC,CAAA;AACxH,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAA;AAC7B,OAAO,KAA0B,MAAM,OAAO,CAAA;AAC9C,OAAO,WAAW,MAAM,aAAa,CAAA;AAMrC,MAAM,UAAU,GAAuC,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE;IACjE,IAAI,KAAK,CAAA;IACT,IAAI,IAAI,CAAA;IAER,IAAI,KAAK,YAAY,QAAQ,EAAE;QAC7B,KAAK,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,CAAA;QAC9B,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAC3B,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;QAEF,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;QAC3B,KAAK,GAAG,KAAK;aACV,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAChB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;QAC5C,CAAC,CAAC;aACD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACZ,4DAA4D;YAC5D,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;YAC7D,IAAI,CAAC,SAAS,GAAG,mBAAmB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAE,CAAA;YACrG,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CAAA;KACL;IAED,IAAI,KAAK,YAAY,aAAa,EAAE;QAClC,IAAI,GAAG,GAAG,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;KAClD;IAED,OAAO,CACL,oBAAC,MAAM,IAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO;QAC5C,IAAI,CAAC,CAAC,CAAC,CACN,oBAAC,IAAI;;YACe,oBAAC,OAAO,IAAC,OAAO,EAAE,IAAI,GAAI,CACvC,CACR,CAAC,CAAC,CAAC,IAAI;QAEP,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,oBAAC,aAAa,IAAC,IAAI,EAAE,KAAK,CAAC,gBAAgB,GAAI,CAAC,CAAC,CAAC,oBAAC,IAAI,QAAE,KAAK,CAAC,OAAO,CAAQ;QAEvG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAC,aAAa,IAAC,IAAI,EAAE,KAAK,CAAC,UAAU,GAAI,CAAC,CAAC,CAAC,IAAI;QAEnE,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,oBAAC,IAAI,IAAC,KAAK,EAAC,YAAY,EAAC,KAAK,EAAE,KAAK,CAAC,SAAS,GAAI,CAAC,CAAC,CAAC,IAAI;QAE1G,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACzD,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,GAAG,EAAE,CAAC,IAC/B,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5C,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK,EAAE,aAAa,EAAC,QAAQ;YACpC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,oBAAC,IAAI,IAAC,IAAI,UAAE,OAAO,CAAC,KAAK,CAAQ,CAAC,CAAC,CAAC,IAAI;YACzD,oBAAC,aAAa,IAAC,IAAI,EAAE,OAAO,CAAC,IAAI,GAAI,CACjC,CACP,CAAC,CACE,CACP,CAAC,CAAC,CAAC,IAAI;QAEP,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACnC,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;YACzB,oBAAC,IAAI,8DAA2D;YAC/D,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAChC,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;gBACpD,oBAAC,IAAI;;oBACA,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,IAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAQ,CAAC,CAAC,CAAC,IAAI;oBAChF,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CACvD;gBACP,oBAAC,GAAG,IAAC,WAAW,EAAE,CAAC;oBACjB,oBAAC,IAAI,IAAC,QAAQ,UAAE,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAQ,CAC3C,CACF,CACP,CAAC,CACE,CACP,CAAC,CAAC,CAAC,IAAI,CACD,CACV,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,UAAU,EAAC,CAAA","sourcesContent":["import {Banner} from './Banner.js'\nimport {TokenizedText} from './TokenizedText.js'\nimport {Command} from './Command.js'\nimport {List} from './List.js'\nimport {BugError, cleanSingleStackTracePath, ExternalError, FatalError as Fatal} from '../../../../public/node/error.js'\nimport {Box, Text} from 'ink'\nimport React, {FunctionComponent} from 'react'\nimport StackTracey from 'stacktracey'\n\nexport interface FatalErrorProps {\n error: Fatal\n}\n\nconst FatalError: FunctionComponent<FatalErrorProps> = ({error}) => {\n let stack\n let tool\n\n if (error instanceof BugError) {\n stack = new StackTracey(error)\n stack.items.forEach((item) => {\n item.file = cleanSingleStackTracePath(item.file)\n })\n\n stack = stack.withSources()\n stack = stack\n .filter((entry) => {\n return !entry.file.includes('@oclif/core')\n })\n .map((item) => {\n /** We make the paths relative to the packages/ directory */\n const fileShortComponents = item.fileShort.split('packages/')\n item.fileShort = fileShortComponents.length === 2 ? fileShortComponents[1]! : fileShortComponents[0]!\n return item\n })\n }\n\n if (error instanceof ExternalError) {\n tool = `${error.command} ${error.args.join(' ')}`\n }\n\n return (\n <Banner type={tool ? 'external_error' : 'error'}>\n {tool ? (\n <Text>\n Error coming from <Command command={tool} />\n </Text>\n ) : null}\n\n {error.formattedMessage ? <TokenizedText item={error.formattedMessage} /> : <Text>{error.message}</Text>}\n\n {error.tryMessage ? <TokenizedText item={error.tryMessage} /> : null}\n\n {error.nextSteps && error.nextSteps.length > 0 ? <List title=\"Next steps\" items={error.nextSteps} /> : null}\n\n {error.customSections && error.customSections.length > 0 ? (\n <Box flexDirection=\"column\" gap={1}>\n {error.customSections.map((section, index) => (\n <Box key={index} flexDirection=\"column\">\n {section.title ? <Text bold>{section.title}</Text> : null}\n <TokenizedText item={section.body} />\n </Box>\n ))}\n </Box>\n ) : null}\n\n {stack && stack.items.length !== 0 ? (\n <Box flexDirection=\"column\">\n <Text>To investigate the issue, examine this stack trace:</Text>\n {stack.items.map((item, index) => (\n <Box flexDirection=\"column\" key={index} paddingLeft={2}>\n <Text>\n at{item.calleeShort ? <Text color=\"yellow\">{` ${item.calleeShort}`}</Text> : null}\n {item.fileShort ? ` (${item.fileShort}:${item.line})` : null}\n </Text>\n <Box paddingLeft={2}>\n <Text dimColor>{item.sourceLine?.trim()}</Text>\n </Box>\n </Box>\n ))}\n </Box>\n ) : null}\n </Banner>\n )\n}\n\nexport {FatalError}\n"]}
@@ -10,10 +10,8 @@ const List = ({ title, items, margin = true, ordered = false, color }) => {
10
10
  return (React.createElement(Box, { flexDirection: "column" },
11
11
  title ? (React.createElement(Text, { color: color },
12
12
  React.createElement(TokenizedText, { item: title }))) : null,
13
- items.map((item, index) => (React.createElement(Box, { key: index },
14
- React.createElement(Box, null,
15
- margin ? React.createElement(Text, null, ' ') : null,
16
- React.createElement(Text, { color: color }, `${ordered ? `${index + 1}.` : DOT}`)),
13
+ items.map((item, index) => (React.createElement(Box, { key: index, marginLeft: margin ? 2 : 0 },
14
+ React.createElement(Text, { color: color }, `${ordered ? `${index + 1}.` : DOT}`),
17
15
  React.createElement(Box, { flexGrow: 1, marginLeft: 1 },
18
16
  React.createElement(Text, { color: color },
19
17
  React.createElement(TokenizedText, { item: item }))))))));
@@ -1 +1 @@
1
- {"version":3,"file":"List.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAC,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAC,GAAG,EAAE,IAAI,EAAY,MAAM,KAAK,CAAA;AACxC,OAAO,KAA0B,MAAM,OAAO,CAAA;AAU9C,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;GAGG;AACH,MAAM,IAAI,GAAiC,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,KAAK,EAAC,EAAe,EAAE;IAChH,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACxB,KAAK,CAAC,CAAC,CAAC,CACP,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK;YAChB,oBAAC,aAAa,IAAC,IAAI,EAAE,KAAK,GAAI,CACzB,CACR,CAAC,CAAC,CAAC,IAAI;QACP,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK;YACb,oBAAC,GAAG;gBACD,MAAM,CAAC,CAAC,CAAC,oBAAC,IAAI,QAAE,IAAI,CAAQ,CAAC,CAAC,CAAC,IAAI;gBACpC,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK,IAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAQ,CAC7D;YAEN,oBAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;gBAC7B,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK;oBAChB,oBAAC,aAAa,IAAC,IAAI,EAAE,IAAI,GAAI,CACxB,CACH,CACF,CACP,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {InlineToken, TokenItem, TokenizedText} from './TokenizedText.js'\nimport {Box, Text, TextProps} from 'ink'\nimport React, {FunctionComponent} from 'react'\n\ninterface ListProps {\n title?: TokenItem<InlineToken>\n items: TokenItem<InlineToken>[]\n ordered?: boolean\n margin?: boolean\n color?: TextProps['color']\n}\n\nconst DOT = '•'\n\n/**\n * `List` displays an unordered or ordered list with text aligned with the bullet point\n * and wrapped to the container width.\n */\nconst List: FunctionComponent<ListProps> = ({title, items, margin = true, ordered = false, color}): JSX.Element => {\n return (\n <Box flexDirection=\"column\">\n {title ? (\n <Text color={color}>\n <TokenizedText item={title} />\n </Text>\n ) : null}\n {items.map((item, index) => (\n <Box key={index}>\n <Box>\n {margin ? <Text>{' '}</Text> : null}\n <Text color={color}>{`${ordered ? `${index + 1}.` : DOT}`}</Text>\n </Box>\n\n <Box flexGrow={1} marginLeft={1}>\n <Text color={color}>\n <TokenizedText item={item} />\n </Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n}\n\nexport {List}\n"]}
1
+ {"version":3,"file":"List.js","sourceRoot":"","sources":["../../../../../src/private/node/ui/components/List.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAC,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAC,GAAG,EAAE,IAAI,EAAY,MAAM,KAAK,CAAA;AACxC,OAAO,KAA0B,MAAM,OAAO,CAAA;AAU9C,MAAM,GAAG,GAAG,GAAG,CAAA;AAEf;;;GAGG;AACH,MAAM,IAAI,GAAiC,CAAC,EAAC,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAG,KAAK,EAAE,KAAK,EAAC,EAAe,EAAE;IAChH,OAAO,CACL,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;QACxB,KAAK,CAAC,CAAC,CAAC,CACP,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK;YAChB,oBAAC,aAAa,IAAC,IAAI,EAAE,KAAK,GAAI,CACzB,CACR,CAAC,CAAC,CAAC,IAAI;QACP,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,oBAAC,GAAG,IAAC,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK,IAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAQ;YAEjE,oBAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;gBAC7B,oBAAC,IAAI,IAAC,KAAK,EAAE,KAAK;oBAChB,oBAAC,aAAa,IAAC,IAAI,EAAE,IAAI,GAAI,CACxB,CACH,CACF,CACP,CAAC,CACE,CACP,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAC,IAAI,EAAC,CAAA","sourcesContent":["import {InlineToken, TokenItem, TokenizedText} from './TokenizedText.js'\nimport {Box, Text, TextProps} from 'ink'\nimport React, {FunctionComponent} from 'react'\n\ninterface ListProps {\n title?: TokenItem<InlineToken>\n items: TokenItem<InlineToken>[]\n ordered?: boolean\n margin?: boolean\n color?: TextProps['color']\n}\n\nconst DOT = '•'\n\n/**\n * `List` displays an unordered or ordered list with text aligned with the bullet point\n * and wrapped to the container width.\n */\nconst List: FunctionComponent<ListProps> = ({title, items, margin = true, ordered = false, color}): JSX.Element => {\n return (\n <Box flexDirection=\"column\">\n {title ? (\n <Text color={color}>\n <TokenizedText item={title} />\n </Text>\n ) : null}\n {items.map((item, index) => (\n <Box key={index} marginLeft={margin ? 2 : 0}>\n <Text color={color}>{`${ordered ? `${index + 1}.` : DOT}`}</Text>\n\n <Box flexGrow={1} marginLeft={1}>\n <Text color={color}>\n <TokenizedText item={item} />\n </Text>\n </Box>\n </Box>\n ))}\n </Box>\n )\n}\n\nexport {List}\n"]}