@akanjs/devkit 3.0.0-alpha.11 → 3.0.0-alpha.110

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 (187) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/DEV_RUNTIME_KNOBS.md +34 -0
  3. package/README.ko.md +1 -1
  4. package/README.md +1 -1
  5. package/agentsIndex.test.ts +10 -0
  6. package/agentsIndex.ts +21 -1
  7. package/aiEditor.ts +1 -1
  8. package/akanApp/BackendImportGraph.test.ts +120 -0
  9. package/akanApp/BackendImportGraph.ts +167 -0
  10. package/akanApp/akanApp.host.test.ts +16 -678
  11. package/akanApp/akanApp.host.ts +113 -578
  12. package/akanApp/devHostPolicy.test.ts +542 -0
  13. package/akanApp/devHostPolicy.ts +442 -0
  14. package/akanApp/index.ts +2 -0
  15. package/akanConfig/akanConfig.test.ts +182 -14
  16. package/akanConfig/akanConfig.ts +143 -47
  17. package/akanConfig/types.ts +9 -0
  18. package/akanContext.ts +30 -14
  19. package/akanMcpContract.ts +25 -4
  20. package/appSelectionMemory.ts +28 -0
  21. package/applicationBuildRunner.test.ts +37 -2
  22. package/applicationBuildRunner.ts +52 -23
  23. package/artifact/implicitRootLayout.test.ts +70 -1
  24. package/artifact/implicitRootLayout.ts +41 -14
  25. package/artifact/routeSeedIndex.test.ts +1 -0
  26. package/biome.base.json +28 -1
  27. package/biomeBase.ts +1 -1
  28. package/capacitorApp.ts +10 -0
  29. package/cloud/globalConfig.ts +9 -2
  30. package/codegenLock.test.ts +137 -0
  31. package/codegenLock.ts +136 -0
  32. package/commandDecorators/argMeta.ts +9 -1
  33. package/commandDecorators/command.ts +94 -7
  34. package/commandDecorators/commandBuilder.ts +20 -5
  35. package/commandDecorators/commandDecorators.test.ts +115 -3
  36. package/commandDecorators/helpFormatter.ts +4 -0
  37. package/dependencyScanner.test.ts +99 -0
  38. package/dependencyScanner.ts +27 -24
  39. package/devkitUtils.test.ts +0 -104
  40. package/executors.test.ts +135 -7
  41. package/executors.ts +115 -25
  42. package/fileEditor.ts +19 -19
  43. package/fileSys.ts +19 -1
  44. package/formSetterScanner.test.ts +80 -0
  45. package/formSetterScanner.ts +92 -0
  46. package/frontendBuild/autoImportSync.test.ts +58 -0
  47. package/frontendBuild/autoImportSync.ts +7 -2
  48. package/frontendBuild/buildRouteClient.test.ts +47 -24
  49. package/frontendBuild/clientBuildTypes.ts +4 -0
  50. package/frontendBuild/clientEntriesBundler.ts +4 -1
  51. package/frontendBuild/clientEntryDiscovery.ts +2 -2
  52. package/frontendBuild/csrArtifactBuilder.ts +116 -84
  53. package/frontendBuild/cssCompiler.ts +63 -10
  54. package/frontendBuild/devGeneratedIndexSync.ts +3 -2
  55. package/frontendBuild/fontOptimizer.test.ts +75 -2
  56. package/frontendBuild/fontOptimizer.ts +98 -27
  57. package/frontendBuild/fontPruner.test.ts +220 -0
  58. package/frontendBuild/fontPruner.ts +206 -0
  59. package/frontendBuild/frontendBuild.test.ts +124 -10
  60. package/frontendBuild/hmrWatcher.ts +1 -1
  61. package/frontendBuild/index.ts +1 -1
  62. package/frontendBuild/pagesBundleBuilder.ts +3 -3
  63. package/frontendBuild/pagesEntrySourceGenerator.ts +11 -88
  64. package/frontendBuild/routeClientBuilder.ts +12 -5
  65. package/frontendBuild/sourceMtimeIndex.ts +1 -1
  66. package/frontendBuild/ssrBaseArtifactBuilder.ts +21 -4
  67. package/frontendBuild/styleContract.ts +14 -20
  68. package/frontendBuild/themeValidator.ts +22 -17
  69. package/frontendBuild/vendorSpecifiers.ts +1 -0
  70. package/frontendBuild/watchRootResolver.test.ts +129 -0
  71. package/frontendBuild/watchRootResolver.ts +66 -1
  72. package/incrementalBuilder/devWatchBatch.test.ts +18 -20
  73. package/incrementalBuilder/devWatchBatch.ts +6 -2
  74. package/incrementalBuilder/incrementalBuilder.host.ts +51 -7
  75. package/incrementalBuilder/incrementalBuilder.proc.ts +17 -6
  76. package/index.ts +0 -7
  77. package/integration/devStabilityHarness.ts +13 -19
  78. package/libSource.test.ts +112 -0
  79. package/libSource.ts +126 -0
  80. package/lint/__fixtures__/README.md +40 -0
  81. package/lint/__fixtures__/no-arbitrary-color/bad.tsx +3 -0
  82. package/lint/__fixtures__/no-arbitrary-color/good.tsx +4 -0
  83. package/lint/__fixtures__/no-async-component-in-ui/bad.tsx +4 -0
  84. package/lint/__fixtures__/no-async-component-in-ui/good.tsx +4 -0
  85. package/lint/__fixtures__/no-bang-comment-in-client/bad.tsx +4 -0
  86. package/lint/__fixtures__/no-bang-comment-in-client/fixture.json +1 -0
  87. package/lint/__fixtures__/no-bang-comment-in-client/good.tsx +3 -0
  88. package/lint/__fixtures__/no-daisyui-legacy-class/bad.tsx +7 -0
  89. package/lint/__fixtures__/no-daisyui-legacy-class/good.tsx +5 -0
  90. package/lint/__fixtures__/no-deep-internal-import/bad.tsx +3 -0
  91. package/lint/__fixtures__/no-deep-internal-import/fixture.json +1 -0
  92. package/lint/__fixtures__/no-deep-internal-import/good.tsx +3 -0
  93. package/lint/__fixtures__/no-deprecated-log-level/bad.tsx +4 -0
  94. package/lint/__fixtures__/no-deprecated-log-level/good.tsx +4 -0
  95. package/lint/__fixtures__/no-import-client-functions/bad.tsx +2 -0
  96. package/lint/__fixtures__/no-import-client-functions/good.tsx +4 -0
  97. package/lint/__fixtures__/no-import-client-in-server/bad.tsx +6 -0
  98. package/lint/__fixtures__/no-import-client-in-server/good.tsx +5 -0
  99. package/lint/__fixtures__/no-import-external-library/bad.tsx +4 -0
  100. package/lint/__fixtures__/no-import-external-library/good.tsx +5 -0
  101. package/lint/__fixtures__/no-import-server-in-client/bad.tsx +6 -0
  102. package/lint/__fixtures__/no-import-server-in-client/good.tsx +4 -0
  103. package/lint/__fixtures__/no-init-fetch-in-client/store-file/bad.ts +1 -0
  104. package/lint/__fixtures__/no-init-fetch-in-client/store-file/fixture.json +1 -0
  105. package/lint/__fixtures__/no-init-fetch-in-client/store-file/good.ts +1 -0
  106. package/lint/__fixtures__/no-init-fetch-in-client/use-client/bad.tsx +4 -0
  107. package/lint/__fixtures__/no-init-fetch-in-client/use-client/good.tsx +5 -0
  108. package/lint/__fixtures__/no-inline-color/bad.tsx +3 -0
  109. package/lint/__fixtures__/no-inline-color/good.tsx +3 -0
  110. package/lint/__fixtures__/no-interpolated-arbitrary-class/bad.tsx +3 -0
  111. package/lint/__fixtures__/no-interpolated-arbitrary-class/good.tsx +3 -0
  112. package/lint/__fixtures__/no-js-private-class-method/bad.tsx +3 -0
  113. package/lint/__fixtures__/no-js-private-class-method/good.tsx +3 -0
  114. package/lint/__fixtures__/no-model-type-in-util-zone/bad.tsx +3 -0
  115. package/lint/__fixtures__/no-model-type-in-util-zone/good.tsx +6 -0
  116. package/lint/__fixtures__/no-raw-palette-class/bad.tsx +6 -0
  117. package/lint/__fixtures__/no-raw-palette-class/good.tsx +8 -0
  118. package/lint/__fixtures__/no-redeclare-predefined-endpoint/bad.ts +10 -0
  119. package/lint/__fixtures__/no-redeclare-predefined-endpoint/fixture.json +1 -0
  120. package/lint/__fixtures__/no-redeclare-predefined-endpoint/good.ts +6 -0
  121. package/lint/__fixtures__/no-return-in-store-action/bad.tsx +2 -0
  122. package/lint/__fixtures__/no-return-in-store-action/good.tsx +6 -0
  123. package/lint/__fixtures__/no-throw-raw-error/bad.tsx +4 -0
  124. package/lint/__fixtures__/no-throw-raw-error/good.tsx +4 -0
  125. package/lint/__fixtures__/no-unpublished-form-setter/bad.tsx +3 -0
  126. package/lint/__fixtures__/no-unpublished-form-setter/good.tsx +5 -0
  127. package/lint/__fixtures__/no-use-client-in-server/bad.tsx +3 -0
  128. package/lint/__fixtures__/no-use-client-in-server/good.tsx +2 -0
  129. package/lint/__fixtures__/non-scalar-props-restricted/bad.tsx +5 -0
  130. package/lint/__fixtures__/non-scalar-props-restricted/good.tsx +4 -0
  131. package/lint/gritRules.test.ts +178 -0
  132. package/lint/no-arbitrary-color.grit +1 -1
  133. package/lint/no-async-component-in-ui.grit +35 -0
  134. package/lint/no-bang-comment-in-client.grit +23 -10
  135. package/lint/no-daisyui-legacy-class.grit +26 -9
  136. package/lint/no-deprecated-log-level.grit +17 -0
  137. package/lint/no-init-fetch-in-client.grit +47 -0
  138. package/lint/no-inline-color.grit +10 -8
  139. package/lint/no-interpolated-arbitrary-class.grit +3 -3
  140. package/lint/no-model-type-in-util-zone.grit +58 -0
  141. package/lint/no-raw-palette-class.grit +3 -3
  142. package/lint/no-unpublished-form-setter.grit +41 -0
  143. package/lint/non-scalar-props-restricted.grit +16 -7
  144. package/linter.test.ts +80 -0
  145. package/linter.ts +82 -13
  146. package/package.json +5 -8
  147. package/prompter.ts +9 -4
  148. package/qualityScanner.test.ts +80 -142
  149. package/qualityScanner.ts +89 -31
  150. package/recipeScanner.ts +4 -1
  151. package/routeSourceValidator.test.ts +63 -0
  152. package/routeSourceValidator.ts +123 -16
  153. package/scanInfo.ts +32 -26
  154. package/semver.test.ts +26 -0
  155. package/semver.ts +31 -0
  156. package/slicePlanner.test.ts +182 -0
  157. package/slicePlanner.ts +235 -0
  158. package/ssrScanner.test.ts +301 -0
  159. package/subspace.test.ts +418 -0
  160. package/subspace.ts +723 -0
  161. package/subspaceConfig.ts +76 -0
  162. package/transforms/asyncDefaultExportDetector.ts +105 -0
  163. package/transforms/barrelImportsPlugin.ts +1 -1
  164. package/transforms/externalizeFrameworkPlugin.ts +0 -1
  165. package/transforms/transforms.test.ts +5 -5
  166. package/transforms/tsconfigPackageResolver.test.ts +230 -0
  167. package/tsconfig.json +6 -2
  168. package/typeChecker.ts +1 -1
  169. package/types.ts +1 -0
  170. package/uploadRelease.ts +2 -2
  171. package/workflow/executor.test.ts +146 -0
  172. package/workspaceLayout.test.ts +56 -4
  173. package/workspaceLayout.ts +48 -2
  174. package/builder.ts +0 -164
  175. package/extractDeps.ts +0 -86
  176. package/frontendBuild/styleGuard.test.ts +0 -165
  177. package/frontendBuild/styleGuard.ts +0 -322
  178. package/getCredentials.ts +0 -19
  179. package/getModelFileData.ts +0 -62
  180. package/mcpScanner.ts +0 -217
  181. package/src/capacitorApp.ts +0 -282
  182. package/storeScanner.ts +0 -173
  183. package/streamAi.ts +0 -45
  184. package/ui/MultiScrollList.tsx +0 -242
  185. package/ui/ScrollList.tsx +0 -107
  186. package/ui/index.ts +0 -2
  187. package/useStdoutDimensions.ts +0 -20
@@ -1,242 +0,0 @@
1
- "use client";
2
- import { Box, Text, useInput } from "ink";
3
- import { useEffect, useState } from "react";
4
- import { useStdoutDimensions } from "../useStdoutDimensions";
5
-
6
- interface MultiScrollListProps {
7
- logList: {
8
- title: string;
9
- logs: {
10
- type: string;
11
- content: string;
12
- }[];
13
- color: string;
14
- }[];
15
-
16
- maxLength?: number;
17
- }
18
-
19
- /**
20
- * @param logList 로그 목록
21
- * @param maxLength 최대 로그 길이 (기본 100)
22
- */
23
- const HEADER_HEIGHT = 1;
24
- const FOOTER_HEIGHT = 1;
25
- const OUTER_BORDER_HEIGHT = 2;
26
- const BORDER_HEIGHT = 2;
27
- const ANSI_ESCAPE_RE = new RegExp(`${String.fromCharCode(27)}(?:[@-Z\\\\-_]|\\[[\\s\\S]*?[@-~])`, "g");
28
-
29
- export const MultiScrollList = ({ logList, maxLength = 100 }: MultiScrollListProps) => {
30
- // 창 너비, 높이
31
- const [width, height] = useStdoutDimensions();
32
- // 탭별 로그 렌더링
33
-
34
- const [focusLog, setFocusLog] = useState<{ type: string; content: string }[]>([]);
35
- // 탭별 로그 길이 저장 (스크롤시 로그 길이 변화로 위치 조정)
36
- const [lengthMap, setLengthMap] = useState<Map<number, number>>(new Map());
37
- // 스크롤 위치
38
- const [scrollPos, setScrollPos] = useState(0);
39
- // 현재 포커싱탭 인덱스
40
- const [tabIndex, setTabIndex] = useState<number>(0);
41
- // 스크롤 실행 여부
42
- const [isRunning, setIsRunning] = useState(false);
43
- // 박스 높이 (보더 사이즈 2, 헤더 사이즈 1, 푸터 사이즈 5 기본 1)
44
- const [boxHeight, setBoxHeight] = useState(
45
- height - HEADER_HEIGHT - OUTER_BORDER_HEIGHT - FOOTER_HEIGHT - BORDER_HEIGHT,
46
- );
47
- const boxWidth = width - 27;
48
-
49
- // maxLength에 따라 로그 배열을 제한하는 유틸리티 함수
50
- const getLimitedLogs = (logs: { type: string; content: string }[]) => {
51
- const sortedLogs = logs.reduce<{ type: string; content: string }[]>((acc, log) => {
52
- // log.content.length가 boxWidth보다 큰 경우 잘라서 줄 수 만큼 추가
53
- // ANSI 코드 보관
54
-
55
- const content = log.content.replace(ANSI_ESCAPE_RE, "");
56
- if (content.length > boxWidth) {
57
- const lines = Math.ceil(content.length / boxWidth);
58
- for (let i = 0; i < lines; i++) {
59
- acc.push({ type: log.type, content: content.slice(i * boxWidth, (i + 1) * boxWidth) });
60
- }
61
- } else {
62
- acc.push(log);
63
- }
64
- return acc;
65
- }, []);
66
- return sortedLogs.length > maxLength ? sortedLogs.slice(sortedLogs.length - maxLength) : sortedLogs;
67
- };
68
-
69
- // 입력 이벤트 처리
70
- useInput((input, key) => {
71
- // 탭 키 이벤트 처리(포커싱 탭 변경)
72
- if (key.tab) {
73
- setTabIndex((prev: number) => (prev + 1) % logList.length);
74
- setScrollPos(0);
75
- setIsRunning(false);
76
- }
77
- // 스크롤 중지 이벤트 처리 (포커싱까지 완전히 종료)
78
- if (key.escape) {
79
- setScrollPos(0);
80
- setIsRunning(false);
81
- }
82
- // 스크롤 중지 이벤트 처리 (포커싱 유지)
83
- if (input === " ") {
84
- setScrollPos(0);
85
- setIsRunning(false);
86
- }
87
- // 스크롤 다운 이벤트 처리
88
- if (key.downArrow && scrollPos > 0) {
89
- if (key.shift) {
90
- const newScrollPos = scrollPos - 10;
91
- // 스크롤 최소 위치에 도달 경우에 대한 예외 처리
92
- if (newScrollPos < 0) {
93
- setScrollPos(0);
94
- } else {
95
- setScrollPos(newScrollPos);
96
- }
97
- } else {
98
- const newScrollPos = scrollPos - 1;
99
- setScrollPos(newScrollPos);
100
- }
101
- }
102
- // 스크롤 업 이벤트 처리
103
- if (key.upArrow && scrollPos < logList[tabIndex].logs.length - boxHeight) {
104
- const limitedLogs = getLimitedLogs(logList[tabIndex].logs);
105
- if (scrollPos < limitedLogs.length - boxHeight) {
106
- // 스크롤 업 이벤트 처리 (스크롤 속도 증가)
107
- if (key.shift) {
108
- const newScrollPos = scrollPos + 10;
109
- // 스크롤 최대 위치에 도달 경우에 대한 예외 처리
110
- if (newScrollPos > limitedLogs.length - boxHeight) {
111
- setScrollPos(limitedLogs.length - boxHeight);
112
- } else {
113
- setScrollPos(newScrollPos);
114
- }
115
- } else {
116
- setScrollPos(scrollPos + 1);
117
- }
118
- if (!isRunning) setIsRunning(true);
119
- }
120
- }
121
- });
122
-
123
- useEffect(() => {
124
- // 공통 로직을 함수로 추출
125
- const getLogsToRender = (logs: { type: string; content: string }[], index: number) => {
126
- // maxLength에 따라 로그 제한
127
- const limitedLogs = getLimitedLogs(logs);
128
- // 로그 중 boxWidth보다 긴 것이 있는 경우 잘라서 출력
129
-
130
- // 활성 탭이고 스크롤 중인 특별한 경우
131
- if (scrollPos > 0 && tabIndex === index) {
132
- return limitedLogs.slice(limitedLogs.length - boxHeight - scrollPos, limitedLogs.length - scrollPos);
133
- }
134
- // 로그가 표시 영역보다 큰 경우 (공통 로직)
135
- else if (limitedLogs.length > boxHeight) {
136
- return limitedLogs.slice(limitedLogs.length - boxHeight, limitedLogs.length);
137
- }
138
- // 로그가 표시 영역에 모두 들어가는 경우 (공통 로직)
139
- else {
140
- return limitedLogs;
141
- }
142
- };
143
-
144
- // isRunning일 때 로직
145
- if (isRunning) {
146
- // 선택된 탭의 로그 길이 변화 확인 및 스크롤 포지션 업데이트
147
- if (lengthMap.has(tabIndex)) {
148
- const tabLength = lengthMap.get(tabIndex);
149
- const limitedLogsLength = Math.min(logList[tabIndex].logs.length, maxLength);
150
- if (tabLength && tabLength < limitedLogsLength) {
151
- setScrollPos(scrollPos + 1);
152
- lengthMap.set(tabIndex, limitedLogsLength);
153
- }
154
- }
155
-
156
- // 스크롤 위치에 따른 로그 렌더링 업데이트
157
-
158
- setFocusLog(getLogsToRender(logList[tabIndex].logs, tabIndex));
159
- }
160
- // isRunning이 아닐 때 로직
161
- else {
162
- // lengthMap 업데이트 및 초기 렌더링
163
- setFocusLog(getLogsToRender(logList[tabIndex].logs, tabIndex));
164
- }
165
- }, [logList, isRunning, scrollPos, tabIndex, boxHeight, maxLength]);
166
-
167
- useEffect(() => {
168
- setBoxHeight(height - HEADER_HEIGHT - OUTER_BORDER_HEIGHT - FOOTER_HEIGHT - BORDER_HEIGHT);
169
- }, [height]);
170
-
171
- // 초기 로그 사이즈 설정
172
- useEffect(() => {
173
- setLengthMap(new Map(logList.map((log, index) => [index, Math.min(log.logs.length, maxLength)])));
174
- }, [logList, maxLength]);
175
-
176
- return (
177
- <Box width={width} height={height} borderStyle="round" borderColor="blackBright" flexDirection="column">
178
- <Box width={"100%"} height={boxHeight + BORDER_HEIGHT + HEADER_HEIGHT} flexDirection="row">
179
- <Box width={30} height="100%" flexDirection="column">
180
- <Box>
181
- <Text>
182
- List {tabIndex + 1}/{logList.length}
183
- </Text>
184
- </Box>
185
- <Box borderStyle="round" borderColor="blackBright" width={"100%"} height="100%" flexDirection="column">
186
- {logList.map((log, index) => {
187
- return (
188
- <Text key={index} color={index === tabIndex ? "green" : "white"}>
189
- <Text>●</Text>&nbsp;
190
- {log.title.length > 25 ? `${log.title.slice(0, 25)}...` : log.title}
191
- </Text>
192
- );
193
- })}
194
- </Box>
195
- </Box>
196
- <Box width={"100%"} height="100%" flexDirection="column">
197
- <Box height={1}>
198
- <Text color={logList[tabIndex].color}>
199
- {logList[tabIndex].title} {logList[tabIndex].logs.length}
200
- </Text>
201
- </Box>
202
- <Box
203
- borderStyle={isRunning ? "double" : "round"}
204
- flexDirection="column"
205
- borderColor={logList[tabIndex].color}
206
- width="100%"
207
- height="100%"
208
- >
209
- {scrollPos > 0 ? (
210
- <>
211
- {focusLog.slice(0, focusLog.length - 1).map((log, index) => {
212
- return (
213
- <Text underline={false} color={log.type === "error" ? "red" : "white"} key={index}>
214
- {log.content}
215
- </Text>
216
- );
217
- })}
218
- <Text underline={false} backgroundColor="green">
219
- Scrolling... +{scrollPos}
220
- </Text>
221
- </>
222
- ) : (
223
- focusLog.map((log, index) => {
224
- return (
225
- <Text underline={false} color={log.type === "error" ? "red" : "white"} key={index}>
226
- {log.content}
227
- </Text>
228
- );
229
- })
230
- )}
231
- </Box>
232
- </Box>
233
- </Box>
234
- {/* <Text>{renderMultiLogs[tabIndex][0]}</Text> */}
235
- <Box width={"100%"} height={FOOTER_HEIGHT}>
236
- <Text dimColor={true}>
237
- Tab : switch tab | Up / Down(shift : x10) : scroll | Space : back last position | Esc : stop scrolling
238
- </Text>
239
- </Box>
240
- </Box>
241
- );
242
- };
package/ui/ScrollList.tsx DELETED
@@ -1,107 +0,0 @@
1
- "use client";
2
- import { Box, type BoxProps, Newline, Text, useInput } from "ink";
3
- import { type ReactNode, useEffect, useState } from "react";
4
- import { useStdoutDimensions } from "../useStdoutDimensions";
5
-
6
- interface ScrollListProps extends BoxProps {
7
- list: ReactNode[];
8
- }
9
-
10
- export const ScrollList = ({ list, ...props }: ScrollListProps) => {
11
- const [renderLogs, setRenderLogs] = useState<ReactNode[]>(list);
12
- const [width, height] = useStdoutDimensions();
13
- const [scrollPos, setScrollPos] = useState(0);
14
- const [isRunning, setIsRunning] = useState(false);
15
- const [boxHeight, setBoxHeight] = useState(height - 3);
16
-
17
- useInput((input, key) => {
18
- if (key.escape) {
19
- setIsRunning(false);
20
- setScrollPos(0);
21
- }
22
- if (input === " " && isRunning) {
23
- setIsRunning(false);
24
- setScrollPos(0);
25
- }
26
- if (key.downArrow && scrollPos > 0) {
27
- if (key.shift) {
28
- setScrollPos(scrollPos - 10);
29
- } else {
30
- setScrollPos(scrollPos - 1);
31
- }
32
- }
33
- if (key.upArrow && scrollPos < list.length - boxHeight) {
34
- if (key.shift) {
35
- setScrollPos(scrollPos + 10);
36
- } else {
37
- setScrollPos(scrollPos + 1);
38
- }
39
- }
40
- });
41
-
42
- useEffect(() => {
43
- //1 로그가 박스 높이보다 크면 스크롤 위치 조정
44
- //2. scrollPos값에 따라 포커싱 위치 변경하고 pos 활성시 포커싱 위치 고정
45
- if (isRunning) {
46
- setScrollPos(scrollPos + 1);
47
- return;
48
- }
49
- if (list.length > boxHeight) {
50
- setRenderLogs(list.slice(list.length - boxHeight, list.length));
51
- } else {
52
- setRenderLogs(list);
53
- }
54
- }, [list, isRunning]);
55
-
56
- useEffect(() => {
57
- setBoxHeight(Math.floor(height * 0.9));
58
- }, [height]);
59
-
60
- useEffect(() => {
61
- if (scrollPos > 0) {
62
- setRenderLogs(list.slice(list.length - boxHeight - scrollPos, list.length - scrollPos));
63
- setIsRunning(true);
64
- } else {
65
- setRenderLogs(list.slice(list.length - boxHeight, list.length));
66
- setIsRunning(false);
67
- }
68
- }, [scrollPos]);
69
-
70
- return (
71
- <Box {...props} width={width} height={"100%"} flexDirection="column">
72
- <Box borderStyle="round" width={width} height={height - 3}>
73
- <Newline />
74
- <Text>
75
- {isRunning ? (
76
- <>
77
- {renderLogs.slice(0, renderLogs.length - 1).map((log, index) => (
78
- <>
79
- <Text key={index}>{log}</Text>
80
- <Newline />
81
- </>
82
- ))}
83
- <Text backgroundColor="green">scrolling... + {scrollPos}</Text>
84
- </>
85
- ) : (
86
- <>
87
- {renderLogs.map((log, index) => (
88
- <>
89
- <Text key={index}>{log}</Text>
90
- <Newline />
91
- </>
92
- ))}
93
- </>
94
- )}
95
- </Text>
96
- </Box>
97
- <Box>
98
- <Text dimColor={true}>
99
- You can use the following shortcuts:
100
- <Newline />* <Text backgroundColor="green">up</Text> and <Text backgroundColor="green">down</Text> to scroll.{" "}
101
- <Text backgroundColor="green">shift</Text> to scroll faster.
102
- <Newline />* <Text backgroundColor="green">escape</Text> to stop scrolling.
103
- </Text>
104
- </Box>
105
- </Box>
106
- );
107
- };
package/ui/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from "./MultiScrollList";
2
- export * from "./ScrollList";
@@ -1,20 +0,0 @@
1
- "use client";
2
- import { useStdout } from "ink";
3
- import { useEffect, useState } from "react";
4
-
5
- export const useStdoutDimensions = (): [number, number] => {
6
- const { stdout } = useStdout();
7
- const [dimensions, setDimensions] = useState<[number, number]>([stdout.columns, stdout.rows]);
8
-
9
- useEffect(() => {
10
- const handler = () => {
11
- setDimensions([stdout.columns, stdout.rows]);
12
- };
13
- stdout.on("resize", handler);
14
- return () => {
15
- stdout.off("resize", handler);
16
- };
17
- }, [stdout]);
18
-
19
- return dimensions;
20
- };