floq 0.0.1

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 (59) hide show
  1. package/README.ja.md +133 -0
  2. package/README.md +133 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.js +124 -0
  5. package/dist/commands/add.d.ts +6 -0
  6. package/dist/commands/add.js +36 -0
  7. package/dist/commands/config.d.ts +6 -0
  8. package/dist/commands/config.js +73 -0
  9. package/dist/commands/done.d.ts +1 -0
  10. package/dist/commands/done.js +37 -0
  11. package/dist/commands/list.d.ts +2 -0
  12. package/dist/commands/list.js +96 -0
  13. package/dist/commands/move.d.ts +1 -0
  14. package/dist/commands/move.js +50 -0
  15. package/dist/commands/project.d.ts +8 -0
  16. package/dist/commands/project.js +160 -0
  17. package/dist/config.d.ts +14 -0
  18. package/dist/config.js +64 -0
  19. package/dist/db/index.d.ts +6 -0
  20. package/dist/db/index.js +72 -0
  21. package/dist/db/schema.d.ts +192 -0
  22. package/dist/db/schema.js +13 -0
  23. package/dist/i18n/en.d.ts +160 -0
  24. package/dist/i18n/en.js +108 -0
  25. package/dist/i18n/index.d.ts +7 -0
  26. package/dist/i18n/index.js +15 -0
  27. package/dist/i18n/ja.d.ts +2 -0
  28. package/dist/i18n/ja.js +108 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js +3 -0
  31. package/dist/paths.d.ts +6 -0
  32. package/dist/paths.js +22 -0
  33. package/dist/ui/App.d.ts +2 -0
  34. package/dist/ui/App.js +472 -0
  35. package/dist/ui/SplashScreen.d.ts +7 -0
  36. package/dist/ui/SplashScreen.js +61 -0
  37. package/dist/ui/TaskList.d.ts +10 -0
  38. package/dist/ui/TaskList.js +9 -0
  39. package/dist/ui/ThemeSelector.d.ts +7 -0
  40. package/dist/ui/ThemeSelector.js +17 -0
  41. package/dist/ui/components/FullScreenBox.d.ts +8 -0
  42. package/dist/ui/components/FullScreenBox.js +10 -0
  43. package/dist/ui/components/FunctionKeyBar.d.ts +10 -0
  44. package/dist/ui/components/FunctionKeyBar.js +19 -0
  45. package/dist/ui/components/HelpModal.d.ts +6 -0
  46. package/dist/ui/components/HelpModal.js +11 -0
  47. package/dist/ui/components/StatusBadge.d.ts +7 -0
  48. package/dist/ui/components/StatusBadge.js +16 -0
  49. package/dist/ui/components/TaskItem.d.ts +9 -0
  50. package/dist/ui/components/TaskItem.js +10 -0
  51. package/dist/ui/theme/index.d.ts +10 -0
  52. package/dist/ui/theme/index.js +11 -0
  53. package/dist/ui/theme/themes.d.ts +9 -0
  54. package/dist/ui/theme/themes.js +163 -0
  55. package/dist/ui/theme/types.d.ts +43 -0
  56. package/dist/ui/theme/types.js +1 -0
  57. package/dist/version.d.ts +1 -0
  58. package/dist/version.js +7 -0
  59. package/package.json +57 -0
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { t } from '../../i18n/index.js';
4
+ import { useTheme } from '../theme/index.js';
5
+ export function HelpModal({ onClose }) {
6
+ const i18n = t();
7
+ const help = i18n.tui.help;
8
+ const theme = useTheme();
9
+ const formatTitle = (title) => theme.style.headerUppercase ? title.toUpperCase() : title;
10
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.modal, borderColor: theme.colors.borderActive, paddingX: 2, paddingY: 1, children: [_jsx(Box, { justifyContent: "center", marginBottom: 1, children: _jsx(Text, { bold: true, color: theme.colors.secondary, children: formatTitle(help.title) }) }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(help.navigation) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "1-5" }), " ", help.tabSwitch] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "h/l \u2190/\u2192" }), " ", help.prevNextTab] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "j/k \u2191/\u2193" }), " ", help.taskSelect] })] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(help.actions) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "a" }), " ", help.addTask] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "d" }), " ", help.completeTask] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "n" }), " ", help.moveToNext] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "s" }), " ", help.moveToSomeday] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "i" }), " ", help.moveToInbox] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "r" }), " ", help.refresh] })] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(help.projects) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "p" }), " ", help.makeProject] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "P" }), " ", help.linkToProject] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "Enter" }), " ", help.openProject] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "Esc/b" }), " ", help.backFromProject] })] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(help.other) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "?" }), " ", help.showHelp] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "q" }), " ", help.quit] })] })] }), _jsx(Box, { justifyContent: "center", marginTop: 1, children: _jsx(Text, { color: theme.colors.textMuted, children: help.closeHint }) })] }));
11
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { TaskStatus } from '../../db/schema.js';
3
+ interface StatusBadgeProps {
4
+ status: TaskStatus;
5
+ }
6
+ export declare function StatusBadge({ status }: StatusBadgeProps): React.ReactElement;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { t } from '../../i18n/index.js';
4
+ import { useTheme } from '../theme/index.js';
5
+ export function StatusBadge({ status }) {
6
+ const i18n = t();
7
+ const theme = useTheme();
8
+ const statusColors = {
9
+ inbox: theme.colors.statusInbox,
10
+ next: theme.colors.statusNext,
11
+ waiting: theme.colors.statusWaiting,
12
+ someday: theme.colors.statusSomeday,
13
+ done: theme.colors.statusDone,
14
+ };
15
+ return (_jsx(Text, { color: statusColors[status], bold: true, children: i18n.status[status] }));
16
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { Task } from '../../db/schema.js';
3
+ interface TaskItemProps {
4
+ task: Task;
5
+ isSelected: boolean;
6
+ projectName?: string;
7
+ }
8
+ export declare function TaskItem({ task, isSelected, projectName }: TaskItemProps): React.ReactElement;
9
+ export {};
@@ -0,0 +1,10 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { t } from '../../i18n/index.js';
4
+ import { useTheme } from '../theme/index.js';
5
+ export function TaskItem({ task, isSelected, projectName }) {
6
+ const shortId = task.id.slice(0, 8);
7
+ const i18n = t();
8
+ const theme = useTheme();
9
+ return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: [isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix, "[", shortId, "] ", task.title, projectName && (_jsxs(Text, { color: theme.colors.statusSomeday, children: [" @", projectName] })), task.waitingFor && (_jsxs(Text, { color: theme.colors.statusWaiting, children: [" (", i18n.status.waiting.toLowerCase(), ": ", task.waitingFor, ")"] })), task.dueDate && (_jsxs(Text, { color: theme.colors.accent, children: [" (due: ", task.dueDate.toLocaleDateString(), ")"] }))] }) }));
10
+ }
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import type { Theme, ThemeName } from './types.js';
3
+ export type { Theme, ThemeName, ThemeColors, ThemeBorders, ThemeStyle, BorderStyleType } from './types.js';
4
+ export { themes, VALID_THEMES, getTheme, isValidTheme } from './themes.js';
5
+ export interface ThemeProviderProps {
6
+ themeName: ThemeName;
7
+ children: React.ReactNode;
8
+ }
9
+ export declare function ThemeProvider({ themeName, children }: ThemeProviderProps): React.ReactElement;
10
+ export declare function useTheme(): Theme;
@@ -0,0 +1,11 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import { getTheme, modernTheme } from './themes.js';
3
+ export { themes, VALID_THEMES, getTheme, isValidTheme } from './themes.js';
4
+ const ThemeContext = createContext(modernTheme);
5
+ export function ThemeProvider({ themeName, children }) {
6
+ const theme = getTheme(themeName);
7
+ return React.createElement(ThemeContext.Provider, { value: theme }, children);
8
+ }
9
+ export function useTheme() {
10
+ return useContext(ThemeContext);
11
+ }
@@ -0,0 +1,9 @@
1
+ import type { Theme, ThemeName } from './types.js';
2
+ export declare const modernTheme: Theme;
3
+ export declare const nortonCommanderTheme: Theme;
4
+ export declare const dosPromptTheme: Theme;
5
+ export declare const turboPascalTheme: Theme;
6
+ export declare const themes: Record<ThemeName, Theme>;
7
+ export declare const VALID_THEMES: ThemeName[];
8
+ export declare function getTheme(name: ThemeName): Theme;
9
+ export declare function isValidTheme(name: string): name is ThemeName;
@@ -0,0 +1,163 @@
1
+ export const modernTheme = {
2
+ name: 'modern',
3
+ displayName: 'Modern',
4
+ colors: {
5
+ primary: 'green',
6
+ secondary: 'cyan',
7
+ accent: 'yellow',
8
+ muted: 'gray',
9
+ border: 'gray',
10
+ borderActive: 'cyan',
11
+ statusInbox: 'blue',
12
+ statusNext: 'green',
13
+ statusWaiting: 'yellow',
14
+ statusSomeday: 'magenta',
15
+ statusDone: 'gray',
16
+ text: 'white',
17
+ textMuted: 'gray',
18
+ textSelected: 'cyan',
19
+ textHighlight: 'green',
20
+ fnKeyLabel: 'black',
21
+ fnKeyText: 'cyan',
22
+ },
23
+ borders: {
24
+ main: 'single',
25
+ modal: 'round',
26
+ list: 'single',
27
+ },
28
+ style: {
29
+ selectedPrefix: '› ',
30
+ unselectedPrefix: ' ',
31
+ tabActiveInverse: true,
32
+ tabBrackets: ['', ''],
33
+ headerUppercase: false,
34
+ showFunctionKeys: false,
35
+ loadingChars: ['▪', '▫'],
36
+ },
37
+ };
38
+ export const nortonCommanderTheme = {
39
+ name: 'norton-commander',
40
+ displayName: 'Norton Commander',
41
+ colors: {
42
+ primary: 'cyan',
43
+ secondary: 'yellow',
44
+ accent: 'white',
45
+ muted: 'blue',
46
+ border: 'cyan',
47
+ borderActive: 'yellow',
48
+ background: 'blue',
49
+ statusInbox: 'white',
50
+ statusNext: 'green',
51
+ statusWaiting: 'yellow',
52
+ statusSomeday: 'magenta',
53
+ statusDone: 'gray',
54
+ text: 'cyan',
55
+ textMuted: 'blue',
56
+ textSelected: 'yellow',
57
+ textHighlight: 'white',
58
+ fnKeyLabel: 'black',
59
+ fnKeyText: 'cyan',
60
+ },
61
+ borders: {
62
+ main: 'double',
63
+ modal: 'double',
64
+ list: 'double',
65
+ },
66
+ style: {
67
+ selectedPrefix: '► ',
68
+ unselectedPrefix: ' ',
69
+ tabActiveInverse: true,
70
+ tabBrackets: ['[', ']'],
71
+ headerUppercase: true,
72
+ showFunctionKeys: true,
73
+ loadingChars: ['█', '░'],
74
+ },
75
+ };
76
+ export const dosPromptTheme = {
77
+ name: 'dos-prompt',
78
+ displayName: 'DOS Prompt',
79
+ colors: {
80
+ primary: 'green',
81
+ secondary: 'green',
82
+ accent: 'white',
83
+ muted: 'gray',
84
+ border: 'green',
85
+ borderActive: 'white',
86
+ statusInbox: 'white',
87
+ statusNext: 'green',
88
+ statusWaiting: 'yellow',
89
+ statusSomeday: 'gray',
90
+ statusDone: 'gray',
91
+ text: 'green',
92
+ textMuted: 'gray',
93
+ textSelected: 'white',
94
+ textHighlight: 'green',
95
+ fnKeyLabel: 'green',
96
+ fnKeyText: 'white',
97
+ },
98
+ borders: {
99
+ main: 'single',
100
+ modal: 'single',
101
+ list: 'single',
102
+ },
103
+ style: {
104
+ selectedPrefix: '> ',
105
+ unselectedPrefix: ' ',
106
+ tabActiveInverse: false,
107
+ tabBrackets: ['<', '>'],
108
+ headerUppercase: true,
109
+ showFunctionKeys: true,
110
+ loadingChars: ['#', '-'],
111
+ },
112
+ };
113
+ export const turboPascalTheme = {
114
+ name: 'turbo-pascal',
115
+ displayName: 'Turbo Pascal IDE',
116
+ colors: {
117
+ primary: 'yellow',
118
+ secondary: 'white',
119
+ accent: 'red',
120
+ muted: 'cyan',
121
+ border: 'white',
122
+ borderActive: 'yellow',
123
+ background: 'blue',
124
+ statusInbox: 'white',
125
+ statusNext: 'yellow',
126
+ statusWaiting: 'red',
127
+ statusSomeday: 'cyan',
128
+ statusDone: 'gray',
129
+ text: 'white',
130
+ textMuted: 'cyan',
131
+ textSelected: 'yellow',
132
+ textHighlight: 'white',
133
+ fnKeyLabel: 'red',
134
+ fnKeyText: 'cyan',
135
+ },
136
+ borders: {
137
+ main: 'double',
138
+ modal: 'double',
139
+ list: 'single',
140
+ },
141
+ style: {
142
+ selectedPrefix: '» ',
143
+ unselectedPrefix: ' ',
144
+ tabActiveInverse: true,
145
+ tabBrackets: ['[', ']'],
146
+ headerUppercase: true,
147
+ showFunctionKeys: true,
148
+ loadingChars: ['█', '▒'],
149
+ },
150
+ };
151
+ export const themes = {
152
+ 'modern': modernTheme,
153
+ 'norton-commander': nortonCommanderTheme,
154
+ 'dos-prompt': dosPromptTheme,
155
+ 'turbo-pascal': turboPascalTheme,
156
+ };
157
+ export const VALID_THEMES = ['modern', 'norton-commander', 'dos-prompt', 'turbo-pascal'];
158
+ export function getTheme(name) {
159
+ return themes[name] || modernTheme;
160
+ }
161
+ export function isValidTheme(name) {
162
+ return VALID_THEMES.includes(name);
163
+ }
@@ -0,0 +1,43 @@
1
+ export type ThemeName = 'modern' | 'norton-commander' | 'dos-prompt' | 'turbo-pascal';
2
+ export type BorderStyleType = 'single' | 'double' | 'round' | 'bold' | 'singleDouble' | 'doubleSingle' | 'classic';
3
+ export interface ThemeColors {
4
+ primary: string;
5
+ secondary: string;
6
+ accent: string;
7
+ muted: string;
8
+ border: string;
9
+ borderActive: string;
10
+ background?: string;
11
+ statusInbox: string;
12
+ statusNext: string;
13
+ statusWaiting: string;
14
+ statusSomeday: string;
15
+ statusDone: string;
16
+ text: string;
17
+ textMuted: string;
18
+ textSelected: string;
19
+ textHighlight: string;
20
+ fnKeyLabel: string;
21
+ fnKeyText: string;
22
+ }
23
+ export interface ThemeBorders {
24
+ main: BorderStyleType;
25
+ modal: BorderStyleType;
26
+ list: BorderStyleType;
27
+ }
28
+ export interface ThemeStyle {
29
+ selectedPrefix: string;
30
+ unselectedPrefix: string;
31
+ tabActiveInverse: boolean;
32
+ tabBrackets: [string, string];
33
+ headerUppercase: boolean;
34
+ showFunctionKeys: boolean;
35
+ loadingChars: [string, string];
36
+ }
37
+ export interface Theme {
38
+ name: ThemeName;
39
+ displayName: string;
40
+ colors: ThemeColors;
41
+ borders: ThemeBorders;
42
+ style: ThemeStyle;
43
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare const VERSION: string;
@@ -0,0 +1,7 @@
1
+ import { createRequire } from 'module';
2
+ import { fileURLToPath } from 'url';
3
+ import { dirname, join } from 'path';
4
+ const require = createRequire(import.meta.url);
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const pkg = require(join(__dirname, '..', 'package.json'));
7
+ export const VERSION = pkg.version;
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "floq",
3
+ "version": "0.0.1",
4
+ "description": "Floq - Getting Things Done Task Manager with MS-DOS style themes",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "floq": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "start": "node dist/index.js",
18
+ "prepublishOnly": "npm run build",
19
+ "db:generate": "drizzle-kit generate",
20
+ "db:migrate": "drizzle-kit migrate"
21
+ },
22
+ "keywords": [
23
+ "gtd",
24
+ "task",
25
+ "todo",
26
+ "cli",
27
+ "tui",
28
+ "terminal",
29
+ "dos",
30
+ "retro"
31
+ ],
32
+ "author": "polidog",
33
+ "license": "MIT",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/polidog/gtd-cli.git"
37
+ },
38
+ "homepage": "https://github.com/polidog/gtd-cli#readme",
39
+ "dependencies": {
40
+ "better-sqlite3": "^11.7.0",
41
+ "commander": "^13.1.0",
42
+ "drizzle-orm": "^0.39.1",
43
+ "@inkjs/ui": "^2.0.0",
44
+ "ink": "^5.1.0",
45
+ "ink-text-input": "^6.0.0",
46
+ "react": "^18.3.1",
47
+ "uuid": "^11.0.5"
48
+ },
49
+ "devDependencies": {
50
+ "@types/better-sqlite3": "^7.6.12",
51
+ "@types/node": "^22.10.7",
52
+ "@types/react": "^18.3.18",
53
+ "@types/uuid": "^10.0.0",
54
+ "drizzle-kit": "^0.30.4",
55
+ "typescript": "^5.7.3"
56
+ }
57
+ }