@danixl30/file-explorer-cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/dist/alerts/AlertContextProvider.js +13 -0
  3. package/dist/alerts/components/AlertDisplay.js +19 -0
  4. package/dist/alerts/logic/alert.logic.js +16 -0
  5. package/dist/app.js +27 -0
  6. package/dist/bookmark/Bookmark.js +123 -0
  7. package/dist/bookmark/components/BookmarkList.js +47 -0
  8. package/dist/bookmark/context/BookmarkPaneContext.js +9 -0
  9. package/dist/bookmark/events/add.item.js +8 -0
  10. package/dist/bookmark/implementations/clean.bookmarks.js +6 -0
  11. package/dist/bookmark/implementations/get.all.bookmarks.js +2 -0
  12. package/dist/bookmark/implementations/save.bookmarks.js +5 -0
  13. package/dist/bookmark/logic/bookmark.manager.js +25 -0
  14. package/dist/bookmark/services/clean.bookmarks.js +1 -0
  15. package/dist/bookmark/services/get.all.bookmarks.js +1 -0
  16. package/dist/bookmark/services/write.bookmarks.js +1 -0
  17. package/dist/bookmark/types/bookmark.js +1 -0
  18. package/dist/cli.js +31 -0
  19. package/dist/clipboard/ClipboardProvider.js +8 -0
  20. package/dist/clipboard/logic/clipboard-logic.js +10 -0
  21. package/dist/core/application/event-handler/event-handler.js +1 -0
  22. package/dist/core/application/event-handler/listener/event-listener.js +1 -0
  23. package/dist/core/application/event-handler/types/event.js +1 -0
  24. package/dist/core/application/event-handler/types/subscription.js +1 -0
  25. package/dist/core/application/id-generator/id.generator.js +1 -0
  26. package/dist/core/application/init-layout/init-layout.js +1 -0
  27. package/dist/core/application/input-manager/input-manager.js +1 -0
  28. package/dist/core/application/input-manager/types/input-manager-result.js +1 -0
  29. package/dist/core/application/on-init/on-init.js +1 -0
  30. package/dist/core/application/on-init-job/lazy/on-init-job-lazy.js +1 -0
  31. package/dist/core/application/on-init-job/on-init-job.js +1 -0
  32. package/dist/core/application/pagination-manager/pagination-manager.js +1 -0
  33. package/dist/core/application/pagination-manager/types/pagination-result.js +1 -0
  34. package/dist/core/application/service/application-service.js +1 -0
  35. package/dist/core/application/state/state-factory.js +1 -0
  36. package/dist/core/application/state/state-provider.js +1 -0
  37. package/dist/core/application/state-observers/state-observer.js +1 -0
  38. package/dist/core/application/timer/sleep/sleep.js +1 -0
  39. package/dist/core/application/timer/timer.js +19 -0
  40. package/dist/core/application/value-provider/value-provider.js +1 -0
  41. package/dist/core/infraestructure/db/bookmark.db.js +4 -0
  42. package/dist/core/infraestructure/event-handler/context/EventProvider.js +9 -0
  43. package/dist/core/infraestructure/event-handler/listener/event-listener-factory.js +8 -0
  44. package/dist/core/infraestructure/event-handler/useEventHadler.js +27 -0
  45. package/dist/core/infraestructure/initLayout/useLayoutEffectOnInit.js +4 -0
  46. package/dist/core/infraestructure/input-manager/useInputManager.js +14 -0
  47. package/dist/core/infraestructure/on-init/useEffectOnInit.js +9 -0
  48. package/dist/core/infraestructure/on-init-job/nativeOnInitJob.js +37 -0
  49. package/dist/core/infraestructure/on-init-job/nativeOnInitJobLazy.js +32 -0
  50. package/dist/core/infraestructure/pagination-manager/data-transforms/infinite.js +1 -0
  51. package/dist/core/infraestructure/pagination-manager/data-transforms/normal.js +1 -0
  52. package/dist/core/infraestructure/pagination-manager/usePaginationManager.js +59 -0
  53. package/dist/core/infraestructure/state/useRefStateProvider.js +39 -0
  54. package/dist/core/infraestructure/state/useStateProvider.js +35 -0
  55. package/dist/core/infraestructure/state-observer/useEffectStateObserver.js +16 -0
  56. package/dist/core/infraestructure/timer/sleep.js +2 -0
  57. package/dist/core/infraestructure/uuid/uuid.generator.js +2 -0
  58. package/dist/core/infraestructure/value-provider/useRefValueProvider.js +12 -0
  59. package/dist/core/utils/argument.type.js +1 -0
  60. package/dist/core/utils/optional.js +1 -0
  61. package/dist/file-display/FileDisplay.js +456 -0
  62. package/dist/file-display/components/Loading.js +4 -0
  63. package/dist/file-display/components/NodeDetails.js +50 -0
  64. package/dist/file-display/components/NodeList.js +61 -0
  65. package/dist/file-display/events/node.written.js +7 -0
  66. package/dist/file-display/hooks/useResize.js +24 -0
  67. package/dist/file-display/implementation/create.dir.js +7 -0
  68. package/dist/file-display/implementation/delete.js +9 -0
  69. package/dist/file-display/implementation/execute.command.async.js +6 -0
  70. package/dist/file-display/implementation/execute.command.sync.js +9 -0
  71. package/dist/file-display/implementation/execute.file.js +4 -0
  72. package/dist/file-display/implementation/filter.glob.js +4 -0
  73. package/dist/file-display/implementation/get.all.files.js +44 -0
  74. package/dist/file-display/implementation/get.directory.js +8 -0
  75. package/dist/file-display/implementation/get.upper.directory.js +17 -0
  76. package/dist/file-display/implementation/move.trash.js +9 -0
  77. package/dist/file-display/implementation/node.details.js +79 -0
  78. package/dist/file-display/implementation/paste.operation.js +40 -0
  79. package/dist/file-display/implementation/rename.js +6 -0
  80. package/dist/file-display/logic/file.manager.js +107 -0
  81. package/dist/file-display/logic/history.manager.js +47 -0
  82. package/dist/file-display/logic/node.detail.js +8 -0
  83. package/dist/file-display/logic/operations.manager.js +103 -0
  84. package/dist/file-display/services/create.dir.js +1 -0
  85. package/dist/file-display/services/delete.js +1 -0
  86. package/dist/file-display/services/execute.command.async.js +1 -0
  87. package/dist/file-display/services/execute.command.sync.js +1 -0
  88. package/dist/file-display/services/execute.file.js +1 -0
  89. package/dist/file-display/services/filter.glob.js +1 -0
  90. package/dist/file-display/services/get.all.files.js +1 -0
  91. package/dist/file-display/services/get.directory.js +1 -0
  92. package/dist/file-display/services/get.upper.directory.js +1 -0
  93. package/dist/file-display/services/move.trash.js +1 -0
  94. package/dist/file-display/services/node.details.js +1 -0
  95. package/dist/file-display/services/paste.operation.js +1 -0
  96. package/dist/file-display/services/remane.js +1 -0
  97. package/dist/file-display/types/node.details.js +1 -0
  98. package/dist/file-display/types/node.js +1 -0
  99. package/dist/file-display/utils/icon.parser.js +144 -0
  100. package/dist/input-capture/InputCapureWrapper.js +10 -0
  101. package/dist/input-capture/InputContextCapture.js +26 -0
  102. package/dist/tabs/TabsContext.js +17 -0
  103. package/dist/tabs/events/update.tab.data.js +8 -0
  104. package/dist/tabs/events/update.tab.selection.js +8 -0
  105. package/dist/tabs/logic/tabsManagerLogic.js +58 -0
  106. package/dist/tabs/wrapper/tabs.wrapper.js +38 -0
  107. package/dist/text-field/TextFieldCaptureContext.js +24 -0
  108. package/dist/text-field/TextFieldWrapper.js +21 -0
  109. package/package.json +62 -0
  110. package/readme.md +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 danixl30
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ import React, { createContext } from 'react';
2
+ import { timerManager } from '../core/application/timer/timer.js';
3
+ import { useEffectStateObserver } from '../core/infraestructure/state-observer/useEffectStateObserver.js';
4
+ import { useRefStateFactory } from '../core/infraestructure/state/useRefStateProvider.js';
5
+ import { setTimeoutSleep } from '../core/infraestructure/timer/sleep.js';
6
+ import { useRefValueProvider } from '../core/infraestructure/value-provider/useRefValueProvider.js';
7
+ import { alertLogic } from './logic/alert.logic.js';
8
+ export const AlertContext = createContext(undefined);
9
+ export const AlertContextProvider = (props) => {
10
+ const stateFactory = useRefStateFactory();
11
+ const data = alertLogic(stateFactory, timerManager(stateFactory, useRefValueProvider(), useEffectStateObserver, props.time || 2000, setTimeoutSleep));
12
+ return (React.createElement(AlertContext.Provider, { value: data }, props.children));
13
+ };
@@ -0,0 +1,19 @@
1
+ import { Alert, Badge } from '@inkjs/ui';
2
+ import { Box } from 'ink';
3
+ import React, { useContext } from 'react';
4
+ import { ClipboardContext } from '../../clipboard/ClipboardProvider.js';
5
+ import { AlertContext } from '../AlertContextProvider.js';
6
+ export const AlertDisplay = () => {
7
+ const alert = useContext(AlertContext);
8
+ const clipboard = useContext(ClipboardContext);
9
+ return (React.createElement(React.Fragment, null,
10
+ React.createElement(Box, { width: "100%", flexDirection: "column" },
11
+ clipboard.item.value && (React.createElement(Box, null,
12
+ React.createElement(Badge, { color: "blue" },
13
+ clipboard.item.value.items.length,
14
+ " items in clipboard"))),
15
+ alert.alert.value?.kind === 'ERR' && (React.createElement(Alert, { variant: "error" }, alert.alert.value.message)),
16
+ alert.alert.value?.kind === 'WARN' && (React.createElement(Alert, { variant: "warning" }, alert.alert.value.message)),
17
+ alert.alert.value?.kind === 'INFO' && (React.createElement(Alert, { variant: "info" }, alert.alert.value.message)),
18
+ alert.alert.value?.kind === 'SUCCESS' && (React.createElement(Alert, { variant: "success" }, alert.alert.value.message)))));
19
+ };
@@ -0,0 +1,16 @@
1
+ export const alertLogic = (stateFactory, timer) => {
2
+ const alertState = stateFactory(undefined);
3
+ const setAlert = (alert) => {
4
+ alertState.setState(alert);
5
+ timer(() => alertState.setState(undefined));
6
+ };
7
+ const alertControlled = (alert) => {
8
+ alertState.setState(alert);
9
+ return () => alertState.setState(undefined);
10
+ };
11
+ return {
12
+ alert: alertState.state,
13
+ alertControlled,
14
+ setAlert,
15
+ };
16
+ };
package/dist/app.js ADDED
@@ -0,0 +1,27 @@
1
+ import { Box } from 'ink';
2
+ import React from 'react';
3
+ import { AlertContextProvider } from './alerts/AlertContextProvider.js';
4
+ import { AlertDisplay } from './alerts/components/AlertDisplay.js';
5
+ import { BookmarkPaneContextProvider } from './bookmark/context/BookmarkPaneContext.js';
6
+ import { ClipboardProvider } from './clipboard/ClipboardProvider.js';
7
+ import { EventProvider } from './core/infraestructure/event-handler/context/EventProvider.js';
8
+ import { InputCaptureWarpper } from './input-capture/InputCapureWrapper.js';
9
+ import { InputContextCaptureProvider } from './input-capture/InputContextCapture.js';
10
+ import { TabsContextProvider } from './tabs/TabsContext.js';
11
+ import TabsWrapper from './tabs/wrapper/tabs.wrapper.js';
12
+ import { TextFieldContextCaptureProvider } from './text-field/TextFieldCaptureContext.js';
13
+ import { TextFieldWrapper } from './text-field/TextFieldWrapper.js';
14
+ export default function App(props) {
15
+ return (React.createElement(Box, { height: "100%", width: "100%", flexDirection: "column" },
16
+ React.createElement(EventProvider, null,
17
+ React.createElement(TextFieldContextCaptureProvider, null,
18
+ React.createElement(InputContextCaptureProvider, null,
19
+ React.createElement(AlertContextProvider, null,
20
+ React.createElement(ClipboardProvider, null,
21
+ React.createElement(BookmarkPaneContextProvider, null,
22
+ React.createElement(TabsContextProvider, { defaultPath: props.defaultPath },
23
+ React.createElement(TabsWrapper, null),
24
+ React.createElement(AlertDisplay, null),
25
+ React.createElement(InputCaptureWarpper, null),
26
+ React.createElement(TextFieldWrapper, null))))))))));
27
+ }
@@ -0,0 +1,123 @@
1
+ import { Box, Text, useInput } from 'ink';
2
+ import React, { useContext, useState } from 'react';
3
+ import { EventContext } from '../core/infraestructure/event-handler/context/EventProvider.js';
4
+ import { nativeOnInitJob } from '../core/infraestructure/on-init-job/nativeOnInitJob.js';
5
+ import { useEffectOnInit } from '../core/infraestructure/on-init/useEffectOnInit.js';
6
+ import { useEffectStateObserver } from '../core/infraestructure/state-observer/useEffectStateObserver.js';
7
+ import { useRefStateFactory } from '../core/infraestructure/state/useRefStateProvider.js';
8
+ import { NODE_WRITTEN } from '../file-display/events/node.written.js';
9
+ import { InputContextCapture } from '../input-capture/InputContextCapture.js';
10
+ import { TabsContext } from '../tabs/TabsContext.js';
11
+ import { TextFieldContextCapture } from '../text-field/TextFieldCaptureContext.js';
12
+ import { BookmarkList } from './components/BookmarkList.js';
13
+ import { BookmarkPaneContext } from './context/BookmarkPaneContext.js';
14
+ import { ADD_BOOKMARK_ITEM } from './events/add.item.js';
15
+ import { cleanBookmarks } from './implementations/clean.bookmarks.js';
16
+ import { getAllBookMarks } from './implementations/get.all.bookmarks.js';
17
+ import { saveBookmarks } from './implementations/save.bookmarks.js';
18
+ import { bookmarkManager } from './logic/bookmark.manager.js';
19
+ export const Bookmark = () => {
20
+ const [index, setIndex] = useState(0);
21
+ const eventHandler = useContext(EventContext);
22
+ const textField = useContext(TextFieldContextCapture);
23
+ const inputController = useContext(InputContextCapture);
24
+ const tabs = useContext(TabsContext);
25
+ const bookmark = bookmarkManager(nativeOnInitJob(useRefStateFactory(), useEffectStateObserver, useEffectOnInit), getAllBookMarks, saveBookmarks, cleanBookmarks);
26
+ const { isBookmarkEnabled, toggleBookmarkPane } = useContext(BookmarkPaneContext);
27
+ const filesList = bookmark.data.value;
28
+ const moveUpArrow = () => {
29
+ setIndex((prev) => {
30
+ if (prev <= 0)
31
+ return prev;
32
+ return prev - 1;
33
+ });
34
+ };
35
+ const moveDownArrow = () => {
36
+ setIndex((prev) => {
37
+ if (!filesList.length)
38
+ return -1;
39
+ if (prev + 1 >= filesList.length)
40
+ return filesList.length - 1;
41
+ return prev + 1;
42
+ });
43
+ };
44
+ const togglePane = () => {
45
+ if (!isBookmarkEnabled)
46
+ return toggleBookmarkPane();
47
+ if (!filesList || !filesList.length)
48
+ return;
49
+ return toggleBookmarkPane();
50
+ };
51
+ const selectOne = () => {
52
+ const item = filesList[index];
53
+ if (!item)
54
+ return;
55
+ toggleBookmarkPane();
56
+ tabs.addTab({
57
+ path: item.path,
58
+ history: {
59
+ forward: [],
60
+ previous: [],
61
+ },
62
+ });
63
+ };
64
+ const remove = () => {
65
+ const item = filesList[index];
66
+ if (!item)
67
+ return;
68
+ bookmark.removeBookmark(item);
69
+ };
70
+ const addItem = (item) => {
71
+ textField.addCallback({
72
+ placeHolder: 'Add alias',
73
+ callback: {
74
+ onChange: (data) => {
75
+ const filesList = bookmark.data.value;
76
+ if (filesList.some((e) => e.alias === data))
77
+ textField.setError('Alias already exist');
78
+ else
79
+ textField.setError('');
80
+ },
81
+ onSuccess: async (data) => {
82
+ if (!data)
83
+ return;
84
+ bookmark.saveBookmark({
85
+ alias: data,
86
+ path: item.path,
87
+ });
88
+ },
89
+ },
90
+ });
91
+ };
92
+ useEffectOnInit(() => {
93
+ eventHandler.subscribe(ADD_BOOKMARK_ITEM, (data) => {
94
+ addItem(data.item);
95
+ });
96
+ eventHandler.subscribe(NODE_WRITTEN, () => {
97
+ bookmark.setCleanBookmarks();
98
+ });
99
+ });
100
+ useInput((input, key) => {
101
+ if (inputController.isInputEnabled || textField.isInputEnabled)
102
+ return;
103
+ if (input === 's')
104
+ togglePane();
105
+ if (!isBookmarkEnabled)
106
+ return;
107
+ if (key.downArrow)
108
+ moveDownArrow();
109
+ else if (key.upArrow)
110
+ moveUpArrow();
111
+ else if (key.return)
112
+ selectOne();
113
+ else if (input === 'd')
114
+ remove();
115
+ });
116
+ if (!bookmark.data.value?.length)
117
+ return React.createElement(React.Fragment, null);
118
+ return (React.createElement(React.Fragment, null,
119
+ React.createElement(Box, { height: "100%", borderStyle: "round", flexDirection: "column", width: "20%" },
120
+ React.createElement(Box, { borderStyle: "double", width: "100%" },
121
+ React.createElement(Text, null, "Bookmarks:")),
122
+ React.createElement(BookmarkList, { index: index, items: filesList, isEnabled: isBookmarkEnabled }))));
123
+ };
@@ -0,0 +1,47 @@
1
+ import { Badge } from '@inkjs/ui';
2
+ import { Box, Text } from 'ink';
3
+ import React, { useEffect, useMemo, useState } from 'react';
4
+ import { useResize } from '../../file-display/hooks/useResize.js';
5
+ const createRange = (start, end) => {
6
+ const arr = [];
7
+ for (let index = start; index <= end; index++)
8
+ arr.push(index);
9
+ return arr;
10
+ };
11
+ const calculatePercent = (nodes, index) => Math.round((index * 100) / nodes.length);
12
+ export const BookmarkList = (props) => {
13
+ const { items, index, isEnabled } = props;
14
+ const [lines, setLines] = useState(0);
15
+ const [[top, down], setSubIndexes] = useState([
16
+ 0,
17
+ lines - 1,
18
+ ]);
19
+ const [_columns, rows] = useResize();
20
+ useEffect(() => {
21
+ if (index < top) {
22
+ setSubIndexes([index, index + lines - 1]);
23
+ return;
24
+ }
25
+ if (index > down) {
26
+ setSubIndexes([index - lines + 1, index]);
27
+ return;
28
+ }
29
+ }, [lines, props.index, items, top, down]);
30
+ useEffect(() => {
31
+ const lines = rows - 6;
32
+ setLines(lines);
33
+ setSubIndexes([0, lines - 1]);
34
+ }, [rows]);
35
+ const range = useMemo(() => createRange(top, down), [top, down]);
36
+ return (React.createElement(React.Fragment, null,
37
+ React.createElement(Box, { height: "100%", flexDirection: "column" }, items.length &&
38
+ range.map((e) => {
39
+ const item = items[e];
40
+ if (!item)
41
+ return React.createElement(React.Fragment, null);
42
+ return (React.createElement(Text, { backgroundColor: index === e && isEnabled
43
+ ? 'blue'
44
+ : undefined }, ' ' + item.alias));
45
+ })),
46
+ React.createElement(Badge, { color: "blueBright" }, calculatePercent(items, index + 1) + '%')));
47
+ };
@@ -0,0 +1,9 @@
1
+ import React, { createContext, useState } from 'react';
2
+ export const BookmarkPaneContext = createContext(undefined);
3
+ export const BookmarkPaneContextProvider = (props) => {
4
+ const [isBookmarkEnabled, setIsBookmarkEnabled] = useState(false);
5
+ const toggleBookmarkPane = () => {
6
+ setIsBookmarkEnabled((prev) => !prev);
7
+ };
8
+ return (React.createElement(BookmarkPaneContext.Provider, { value: { isBookmarkEnabled, toggleBookmarkPane } }, props.children));
9
+ };
@@ -0,0 +1,8 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export const createAddBookmarkItem = (item) => ({
3
+ id: randomUUID(),
4
+ item,
5
+ name: ADD_BOOKMARK_ITEM,
6
+ timestamp: new Date(),
7
+ });
8
+ export const ADD_BOOKMARK_ITEM = 'ADD_BOOKMARK_ITEM';
@@ -0,0 +1,6 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { db } from '../../core/infraestructure/db/bookmark.db.js';
3
+ export const cleanBookmarks = async () => {
4
+ db.data.bookmarks = db.data.bookmarks.filter((e) => existsSync(e.path));
5
+ await db.write();
6
+ };
@@ -0,0 +1,2 @@
1
+ import { db } from '../../core/infraestructure/db/bookmark.db.js';
2
+ export const getAllBookMarks = async () => db.data.bookmarks;
@@ -0,0 +1,5 @@
1
+ import { db } from '../../core/infraestructure/db/bookmark.db.js';
2
+ export const saveBookmarks = async (bookmarks) => {
3
+ db.data.bookmarks = bookmarks;
4
+ await db.write();
5
+ };
@@ -0,0 +1,25 @@
1
+ export const bookmarkManager = (onInitJob, getAllBookmarks, saveBookMarks, cleanBookmarks) => {
2
+ const bookmarksJob = onInitJob(getAllBookmarks);
3
+ const saveBookmark = async (item) => {
4
+ if (bookmarksJob.data.value?.some((e) => e.alias === item.alias))
5
+ throw new Error('Alias already exist');
6
+ await saveBookMarks([...bookmarksJob.data.value, item]);
7
+ bookmarksJob.reload();
8
+ };
9
+ const removeBookmark = async (item) => {
10
+ await saveBookMarks(bookmarksJob.data.value.filter((e) => e.alias !== item.alias));
11
+ bookmarksJob.reload();
12
+ };
13
+ const setCleanBookmarks = async () => {
14
+ await cleanBookmarks();
15
+ bookmarksJob.reload();
16
+ };
17
+ return {
18
+ data: bookmarksJob.data,
19
+ isLoading: bookmarksJob.isLoading,
20
+ error: bookmarksJob.error,
21
+ saveBookmark,
22
+ removeBookmark,
23
+ setCleanBookmarks,
24
+ };
25
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import { withFullScreen } from 'fullscreen-ink';
3
+ import React from 'react';
4
+ import meow from 'meow';
5
+ import App from './app.js';
6
+ import { join } from 'node:path';
7
+ const cli = meow(`
8
+ Usage
9
+ $ files
10
+
11
+ Options
12
+ --path The default path, if not provided uses working directory
13
+ -p Alias for --path
14
+
15
+ Examples
16
+ $ files -p ./dir
17
+ `, {
18
+ importMeta: import.meta,
19
+ flags: {
20
+ path: {
21
+ type: 'string',
22
+ },
23
+ p: {
24
+ type: 'string',
25
+ },
26
+ },
27
+ });
28
+ let defaultPath = process.cwd().replaceAll('\\', '/');
29
+ if (cli.flags.path || cli.flags.p)
30
+ defaultPath = join(process.cwd(), cli.flags.p ?? cli.flags.path ?? '').replaceAll('\\', '/');
31
+ withFullScreen(React.createElement(App, { defaultPath: defaultPath })).start();
@@ -0,0 +1,8 @@
1
+ import React, { createContext } from 'react';
2
+ import { useStateFactory } from '../core/infraestructure/state/useStateProvider.js';
3
+ import { clipboardLogic } from './logic/clipboard-logic.js';
4
+ export const ClipboardContext = createContext(undefined);
5
+ export const ClipboardProvider = (props) => {
6
+ const data = clipboardLogic(useStateFactory);
7
+ return (React.createElement(ClipboardContext.Provider, { value: data }, props.children));
8
+ };
@@ -0,0 +1,10 @@
1
+ export const clipboardLogic = (stateFactory) => {
2
+ const clipboardItemState = stateFactory(undefined);
3
+ const removeItem = () => clipboardItemState.setState(undefined);
4
+ const setItem = (item) => clipboardItemState.setState(item);
5
+ return {
6
+ item: clipboardItemState.state,
7
+ removeItem,
8
+ setItem,
9
+ };
10
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ export const timerManager = (stateFactory, valueProvider, stateObserver, time, sleep) => {
2
+ const callBackState = stateFactory(undefined);
3
+ const currentCallback = valueProvider(undefined);
4
+ const worker = async () => {
5
+ await sleep(time);
6
+ callBackState.state.value?.();
7
+ callBackState.setState(undefined);
8
+ };
9
+ const addCallback = (callback) => {
10
+ currentCallback.value = callBackState.state.value;
11
+ callBackState.setState(callback);
12
+ };
13
+ stateObserver(() => {
14
+ if (callBackState.state.value)
15
+ worker();
16
+ return () => worker();
17
+ }, callBackState.state);
18
+ return addCallback;
19
+ };
@@ -0,0 +1,4 @@
1
+ import { JSONFilePreset } from 'lowdb/node';
2
+ export const db = await JSONFilePreset('db.json', {
3
+ bookmarks: [],
4
+ });
@@ -0,0 +1,9 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import { useRefValueProvider } from '../../value-provider/useRefValueProvider.js';
3
+ import { useEventHadler } from '../useEventHadler.js';
4
+ export const EventContext = createContext(undefined);
5
+ export const getEventContext = () => useContext(EventContext);
6
+ export const EventProvider = (props) => {
7
+ const eventHandler = useEventHadler(useRefValueProvider());
8
+ return (React.createElement(EventContext.Provider, { value: eventHandler }, props.children));
9
+ };
@@ -0,0 +1,8 @@
1
+ export const eventListenerFactory = (onInit, eventHandler) => (event, callback) => {
2
+ onInit(() => {
3
+ const subscription = eventHandler.subscribe(event, callback);
4
+ return () => {
5
+ subscription();
6
+ };
7
+ });
8
+ };
@@ -0,0 +1,27 @@
1
+ export const useEventHadler = (valueFactory) => {
2
+ const callbacksState = valueFactory({});
3
+ const subscribe = (event, callback) => {
4
+ const callbacks = [
5
+ ...(callbacksState.value[event] || []),
6
+ callback,
7
+ ];
8
+ callbacksState.value = {
9
+ ...callbacksState.value,
10
+ [event]: callbacks,
11
+ };
12
+ return () => {
13
+ const callbacks = callbacksState.value[event]?.filter((e) => e !== callback) || [];
14
+ callbacksState.value = {
15
+ ...callbacksState.value,
16
+ [event]: callbacks,
17
+ };
18
+ };
19
+ };
20
+ const publish = (event) => {
21
+ callbacksState.value[event.name]?.forEach((callback) => callback(event));
22
+ };
23
+ return {
24
+ subscribe,
25
+ publish,
26
+ };
27
+ };
@@ -0,0 +1,4 @@
1
+ import { useLayoutEffect } from 'react';
2
+ export const useLayoutEffectInitLayout = (callback) => {
3
+ useLayoutEffect(callback, []);
4
+ };
@@ -0,0 +1,14 @@
1
+ export const useInputManager = (stateFactory) => (initialValue, validator = (_) => '', dataTransform = (d) => d) => {
2
+ const inputState = stateFactory(initialValue);
3
+ const errorState = stateFactory('');
4
+ const onChange = (value) => {
5
+ const transformed = dataTransform(value);
6
+ inputState.setState(transformed);
7
+ errorState.setState(validator(transformed));
8
+ };
9
+ return {
10
+ value: inputState.state,
11
+ error: errorState.state,
12
+ onChange,
13
+ };
14
+ };
@@ -0,0 +1,9 @@
1
+ import { useEffect } from 'react';
2
+ export const useEffectOnInit = (callback) => {
3
+ useEffect(() => {
4
+ const res = callback();
5
+ return () => {
6
+ res?.();
7
+ };
8
+ }, []);
9
+ };
@@ -0,0 +1,37 @@
1
+ export const nativeOnInitJob = (stateFactory, stateObserver, onInit) => (callback, ...args) => {
2
+ const dataState = stateFactory(null);
3
+ const loadingState = stateFactory(false);
4
+ const errorState = stateFactory(null);
5
+ const reloadingState = stateFactory(false);
6
+ const job = async () => {
7
+ dataState.setState(null);
8
+ errorState.setState(null);
9
+ try {
10
+ const res = await callback();
11
+ dataState.setState(res);
12
+ }
13
+ catch (e) {
14
+ errorState.setState(e);
15
+ }
16
+ loadingState.setState(false);
17
+ reloadingState.setState(false);
18
+ };
19
+ onInit(() => {
20
+ loadingState.setState(true);
21
+ job();
22
+ });
23
+ const reload = () => {
24
+ if (reloadingState.state.value || loadingState.state.value)
25
+ throw new Error('Is in job');
26
+ reloadingState.setState(true);
27
+ job();
28
+ };
29
+ stateObserver(reload, ...args);
30
+ return {
31
+ reload,
32
+ data: dataState.state,
33
+ error: errorState.state,
34
+ isLoading: loadingState.state,
35
+ isReloading: reloadingState.state,
36
+ };
37
+ };