floq 0.2.0 → 0.2.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.
package/dist/i18n/en.d.ts CHANGED
@@ -107,6 +107,7 @@ export declare const en: {
107
107
  title: string;
108
108
  whatsNewTab: string;
109
109
  keybindingsTab: string;
110
+ infoTab: string;
110
111
  tabHint: string;
111
112
  navigation: string;
112
113
  tabSwitch: string;
@@ -168,6 +169,10 @@ export declare const en: {
168
169
  commentDeleted: string;
169
170
  taskDetailTitle: string;
170
171
  taskDetailFooter: string;
172
+ taskDetailStatus: string;
173
+ deleteConfirm: string;
174
+ deleted: string;
175
+ deleteCancelled: string;
171
176
  comments: string;
172
177
  projectTasks: string;
173
178
  search: {
@@ -178,6 +183,21 @@ export declare const en: {
178
183
  resultsTitle: string;
179
184
  searchTasks: string;
180
185
  };
186
+ info: {
187
+ settings: string;
188
+ database: string;
189
+ paths: string;
190
+ theme: string;
191
+ language: string;
192
+ viewMode: string;
193
+ dbType: string;
194
+ dbPath: string;
195
+ tursoUrl: string;
196
+ configFile: string;
197
+ dataDir: string;
198
+ local: string;
199
+ turso: string;
200
+ };
181
201
  };
182
202
  setup: {
183
203
  welcome: {
@@ -232,6 +252,7 @@ export type HelpTranslations = {
232
252
  title: string;
233
253
  whatsNewTab: string;
234
254
  keybindingsTab: string;
255
+ infoTab: string;
235
256
  tabHint: string;
236
257
  navigation: string;
237
258
  tabSwitch: string;
@@ -312,6 +333,21 @@ export type SearchTranslations = {
312
333
  resultsTitle: string;
313
334
  searchTasks: string;
314
335
  };
336
+ export type InfoTranslations = {
337
+ settings: string;
338
+ database: string;
339
+ paths: string;
340
+ theme: string;
341
+ language: string;
342
+ viewMode: string;
343
+ dbType: string;
344
+ dbPath: string;
345
+ tursoUrl: string;
346
+ configFile: string;
347
+ dataDir: string;
348
+ local: string;
349
+ turso: string;
350
+ };
315
351
  export type TuiTranslations = {
316
352
  title: string;
317
353
  helpHint: string;
@@ -342,6 +378,7 @@ export type TuiTranslations = {
342
378
  whatsNew: WhatsNewTranslations;
343
379
  kanbanHelp: KanbanHelpTranslations;
344
380
  search: SearchTranslations;
381
+ info: InfoTranslations;
345
382
  addComment: string;
346
383
  noComments: string;
347
384
  commentHint: string;
@@ -350,6 +387,10 @@ export type TuiTranslations = {
350
387
  commentDeleted: string;
351
388
  taskDetailTitle: string;
352
389
  taskDetailFooter: string;
390
+ taskDetailStatus: string;
391
+ deleteConfirm: string;
392
+ deleted: string;
393
+ deleteCancelled: string;
353
394
  comments: string;
354
395
  projectTasks: string;
355
396
  };
package/dist/i18n/en.js CHANGED
@@ -81,7 +81,7 @@ export const en = {
81
81
  movedToWaiting: 'Moved "{title}" to Waiting (for {person})',
82
82
  waitingFor: 'Waiting for: ',
83
83
  refreshed: 'Refreshed',
84
- footer: 'a=add d=done n=next s=someday w=waiting i=inbox p=project P=link',
84
+ footer: 'a=add d=done D=delete n=next s=someday w=waiting i=inbox p=project P=link',
85
85
  noTasks: 'No tasks',
86
86
  // Tab labels
87
87
  tabInbox: 'Inbox',
@@ -116,6 +116,7 @@ export const en = {
116
116
  title: 'Keyboard Shortcuts',
117
117
  whatsNewTab: "What's New",
118
118
  keybindingsTab: 'Keybindings',
119
+ infoTab: 'Info',
119
120
  tabHint: 'Tab: switch view',
120
121
  navigation: 'Navigation',
121
122
  tabSwitch: 'Switch tab (5=Projects, 6=Done)',
@@ -179,6 +180,10 @@ export const en = {
179
180
  commentDeleted: 'Comment deleted',
180
181
  taskDetailTitle: 'Task Details',
181
182
  taskDetailFooter: 'j/k=select i=comment d=delete P=link b/Esc=back',
183
+ taskDetailStatus: 'Status',
184
+ deleteConfirm: 'Delete "{title}"? (y/n)',
185
+ deleted: 'Deleted: "{title}"',
186
+ deleteCancelled: 'Delete cancelled',
182
187
  comments: 'Comments',
183
188
  projectTasks: 'Tasks',
184
189
  // Search
@@ -190,6 +195,22 @@ export const en = {
190
195
  resultsTitle: 'Search Results',
191
196
  searchTasks: 'Search tasks',
192
197
  },
198
+ // Info tab
199
+ info: {
200
+ settings: 'Settings',
201
+ database: 'Database',
202
+ paths: 'Paths',
203
+ theme: 'Theme',
204
+ language: 'Language',
205
+ viewMode: 'View Mode',
206
+ dbType: 'Type',
207
+ dbPath: 'Path',
208
+ tursoUrl: 'Turso URL',
209
+ configFile: 'Config File',
210
+ dataDir: 'Data Directory',
211
+ local: 'local',
212
+ turso: 'turso',
213
+ },
193
214
  },
194
215
  // Setup wizard
195
216
  setup: {
package/dist/i18n/ja.js CHANGED
@@ -81,7 +81,7 @@ export const ja = {
81
81
  movedToWaiting: '「{title}」を連絡待ち({person})に移動しました',
82
82
  waitingFor: '待機相手: ',
83
83
  refreshed: '更新しました',
84
- footer: 'a=追加 d=完了 n=次 s=いつか w=待ち i=Inbox p=プロジェクト化 P=紐づけ',
84
+ footer: 'a=追加 d=完了 D=削除 n=次 s=いつか w=待ち i=Inbox p=プロジェクト化 P=紐づけ',
85
85
  noTasks: 'タスクなし',
86
86
  // Tab labels
87
87
  tabInbox: 'Inbox',
@@ -116,6 +116,7 @@ export const ja = {
116
116
  title: 'キーボードショートカット',
117
117
  whatsNewTab: '更新履歴',
118
118
  keybindingsTab: 'キー操作',
119
+ infoTab: '情報',
119
120
  tabHint: 'Tab: 表示切替',
120
121
  navigation: 'ナビゲーション',
121
122
  tabSwitch: 'タブ切替 (5=プロジェクト, 6=完了)',
@@ -179,6 +180,10 @@ export const ja = {
179
180
  commentDeleted: 'コメントを削除しました',
180
181
  taskDetailTitle: 'タスク詳細',
181
182
  taskDetailFooter: 'j/k=選択 i=コメント d=削除 P=紐づけ b/Esc=戻る',
183
+ taskDetailStatus: 'ステータス',
184
+ deleteConfirm: '「{title}」を削除しますか? (y/n)',
185
+ deleted: '削除しました: 「{title}」',
186
+ deleteCancelled: '削除をキャンセルしました',
182
187
  comments: 'コメント',
183
188
  projectTasks: 'タスク一覧',
184
189
  // Search
@@ -190,6 +195,22 @@ export const ja = {
190
195
  resultsTitle: '検索結果',
191
196
  searchTasks: 'タスク検索',
192
197
  },
198
+ // Info tab
199
+ info: {
200
+ settings: '設定',
201
+ database: 'データベース',
202
+ paths: 'パス',
203
+ theme: 'テーマ',
204
+ language: '言語',
205
+ viewMode: '表示モード',
206
+ dbType: '種類',
207
+ dbPath: 'パス',
208
+ tursoUrl: 'Turso URL',
209
+ configFile: '設定ファイル',
210
+ dataDir: 'データディレクトリ',
211
+ local: 'ローカル',
212
+ turso: 'turso',
213
+ },
193
214
  },
194
215
  // Setup wizard
195
216
  setup: {
package/dist/ui/App.js CHANGED
@@ -13,7 +13,7 @@ import { SplashScreen } from './SplashScreen.js';
13
13
  import { getDb, schema } from '../db/index.js';
14
14
  import { t, fmt } from '../i18n/index.js';
15
15
  import { ThemeProvider, useTheme } from './theme/index.js';
16
- import { getThemeName, getViewMode, isTursoEnabled, getTursoConfig } from '../config.js';
16
+ import { getThemeName, getViewMode, isTursoEnabled } from '../config.js';
17
17
  import { KanbanBoard } from './components/KanbanBoard.js';
18
18
  import { VERSION } from '../version.js';
19
19
  const TABS = ['inbox', 'next', 'waiting', 'someday', 'projects', 'done'];
@@ -46,6 +46,7 @@ function AppContent() {
46
46
  const [taskComments, setTaskComments] = useState([]);
47
47
  const [selectedCommentIndex, setSelectedCommentIndex] = useState(0);
48
48
  const [taskToWaiting, setTaskToWaiting] = useState(null);
49
+ const [taskToDelete, setTaskToDelete] = useState(null);
49
50
  const [projectProgress, setProjectProgress] = useState({});
50
51
  // Search state
51
52
  const [searchQuery, setSearchQuery] = useState('');
@@ -267,6 +268,15 @@ function AppContent() {
267
268
  setMessage(fmt(i18n.tui.madeProject || 'Made project: {title}', { title: task.title }));
268
269
  await loadTasks();
269
270
  }, [i18n.tui.madeProject, loadTasks]);
271
+ const deleteTask = useCallback(async (task) => {
272
+ const db = getDb();
273
+ // Delete comments first
274
+ await db.delete(schema.comments).where(eq(schema.comments.taskId, task.id));
275
+ // Delete the task
276
+ await db.delete(schema.tasks).where(eq(schema.tasks.id, task.id));
277
+ setMessage(fmt(i18n.tui.deleted || 'Deleted: "{title}"', { title: task.title }));
278
+ await loadTasks();
279
+ }, [i18n.tui.deleted, loadTasks]);
270
280
  const getTabLabel = (tab) => {
271
281
  switch (tab) {
272
282
  case 'inbox':
@@ -314,6 +324,27 @@ function AppContent() {
314
324
  // Let TextInput handle other keys
315
325
  return;
316
326
  }
327
+ // Handle confirm-delete mode
328
+ if (mode === 'confirm-delete' && taskToDelete) {
329
+ if (input === 'y' || input === 'Y') {
330
+ deleteTask(taskToDelete).then(() => {
331
+ if (selectedTaskIndex >= currentTasks.length - 1) {
332
+ setSelectedTaskIndex(Math.max(0, selectedTaskIndex - 1));
333
+ }
334
+ });
335
+ setTaskToDelete(null);
336
+ setMode('normal');
337
+ return;
338
+ }
339
+ if (input === 'n' || input === 'N' || key.escape) {
340
+ setMessage(i18n.tui.deleteCancelled || 'Delete cancelled');
341
+ setTaskToDelete(null);
342
+ setMode('normal');
343
+ return;
344
+ }
345
+ // Ignore other keys in confirm mode
346
+ return;
347
+ }
317
348
  // Handle add mode
318
349
  if (mode === 'add' || mode === 'add-to-project' || mode === 'add-comment' || mode === 'move-to-waiting') {
319
350
  if (key.escape) {
@@ -626,6 +657,13 @@ function AppContent() {
626
657
  });
627
658
  return;
628
659
  }
660
+ // Delete task (D key - with confirmation)
661
+ if (input === 'D' && currentTasks.length > 0 && currentTab !== 'projects') {
662
+ const task = currentTasks[selectedTaskIndex];
663
+ setTaskToDelete(task);
664
+ setMode('confirm-delete');
665
+ return;
666
+ }
629
667
  // Move to next actions
630
668
  if (input === 'n' && currentTasks.length > 0 && currentTab !== 'next' && currentTab !== 'projects' && currentTab !== 'done') {
631
669
  const task = currentTasks[selectedTaskIndex];
@@ -685,24 +723,14 @@ function AppContent() {
685
723
  };
686
724
  // Turso 接続情報を取得
687
725
  const tursoEnabled = isTursoEnabled();
688
- const tursoHost = tursoEnabled ? (() => {
689
- const config = getTursoConfig();
690
- if (config) {
691
- try {
692
- return new URL(config.url).host;
693
- }
694
- catch {
695
- return config.url;
696
- }
697
- }
698
- return '';
699
- })() : '';
700
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: formatTitle(i18n.tui.title) }), _jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ` v${VERSION}` : ` VER ${VERSION}` }), tursoEnabled && (_jsxs(Text, { color: theme.colors.accent, children: [theme.name === 'modern' ? ' ☁️ ' : ' [SYNC] ', tursoHost] })), !tursoEnabled && (_jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ' 💾 local' : ' [LOCAL]' }))] }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.helpHint })] }), _jsx(Box, { marginBottom: 1, children: TABS.map((tab, index) => {
726
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: formatTitle(i18n.tui.title) }), _jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ` v${VERSION}` : ` VER ${VERSION}` }), _jsx(Text, { color: tursoEnabled ? theme.colors.accent : theme.colors.textMuted, children: theme.name === 'modern'
727
+ ? (tursoEnabled ? ' ☁️ turso' : ' 💾 local')
728
+ : (tursoEnabled ? ' [DB]turso' : ' [DB]local') })] }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.helpHint })] }), _jsx(Box, { marginBottom: 1, children: TABS.map((tab, index) => {
701
729
  const isActive = index === currentListIndex && mode !== 'project-detail';
702
730
  const count = tasks[tab].length;
703
731
  const label = `${index + 1}:${getTabLabel(tab)}(${count})`;
704
732
  return (_jsx(Box, { marginRight: 1, children: _jsx(Text, { color: isActive ? theme.colors.textSelected : theme.colors.textMuted, bold: isActive, inverse: isActive && theme.style.tabActiveInverse, children: formatTabLabel(` ${label} `, isActive) }) }, tab));
705
- }) }), mode === 'project-detail' && selectedProject && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📁 ' : '>> ', selectedProject.title] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ")"] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.projectTasks || 'Tasks', " (", projectTasks.length, ")"] }) })] })), (mode === 'task-detail' || mode === 'add-comment') && selectedTask && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Text, { color: theme.colors.textMuted, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` - ${selectedTask.waitingFor}`] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
733
+ }) }), mode === 'project-detail' && selectedProject && (_jsxs(_Fragment, { children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📁 ' : '>> ', selectedProject.title] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ")"] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.projectTasks || 'Tasks', " (", projectTasks.length, ")"] }) })] })), (mode === 'task-detail' || mode === 'add-comment') && selectedTask && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.taskDetailStatus, ": "] }), _jsxs(Text, { color: theme.colors.accent, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` (${selectedTask.waitingFor})`] })] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
706
734
  const isSelected = index === selectedCommentIndex && mode === 'task-detail';
707
735
  return (_jsxs(Box, { flexDirection: "row", marginBottom: 1, children: [_jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.textMuted, children: isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.textMuted, children: ["[", comment.createdAt.toLocaleString(), "]"] }), _jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: comment.content })] })] }, comment.id));
708
736
  })) }), mode === 'add-comment' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.addComment || 'New comment: ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: "" }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] }))] })), mode === 'search' && searchQuery && (_jsx(SearchResults, { results: searchResults, selectedIndex: searchResultIndex, query: searchQuery })), mode !== 'task-detail' && mode !== 'add-comment' && mode !== 'search' && (_jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 10, children: currentTasks.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noTasks })) : (currentTasks.map((task, index) => {
@@ -711,7 +739,7 @@ function AppContent() {
711
739
  return (_jsx(TaskItem, { task: task, isSelected: index === selectedTaskIndex, projectName: parentProject?.title, progress: progress }, task.id));
712
740
  })) })), (mode === 'add' || mode === 'add-to-project') && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: mode === 'add-to-project' && selectedProject
713
741
  ? `${i18n.tui.newTask}[${selectedProject.title}] `
714
- : i18n.tui.newTask }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: i18n.tui.placeholder }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'move-to-waiting' && taskToWaiting && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.waitingFor }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: "" }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'select-project' && taskToLink && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.selectProject || 'Select project for', ": ", taskToLink.title] }), _jsx(Box, { flexDirection: "column", marginTop: 1, borderStyle: theme.borders.list, borderColor: theme.colors.borderActive, paddingX: 1, children: tasks.projects.map((project, index) => (_jsxs(Text, { color: index === projectSelectIndex ? theme.colors.textSelected : theme.colors.text, bold: index === projectSelectIndex, children: [index === projectSelectIndex ? theme.style.selectedPrefix : theme.style.unselectedPrefix, project.title] }, project.id))) }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.selectProjectHelp || 'j/k: select, Enter: confirm, Esc: cancel' })] })), mode === 'search' && (_jsx(SearchBar, { value: searchQuery, onChange: handleSearchChange, onSubmit: handleInputSubmit })), message && mode === 'normal' && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.textHighlight, children: message }) })), _jsx(Box, { marginTop: 1, children: (mode === 'task-detail' || mode === 'add-comment') ? (theme.style.showFunctionKeys ? (_jsx(FunctionKeyBar, { keys: [
742
+ : i18n.tui.newTask }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: i18n.tui.placeholder }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'move-to-waiting' && taskToWaiting && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.waitingFor }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: "" }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'select-project' && taskToLink && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.selectProject || 'Select project for', ": ", taskToLink.title] }), _jsx(Box, { flexDirection: "column", marginTop: 1, borderStyle: theme.borders.list, borderColor: theme.colors.borderActive, paddingX: 1, children: tasks.projects.map((project, index) => (_jsxs(Text, { color: index === projectSelectIndex ? theme.colors.textSelected : theme.colors.text, bold: index === projectSelectIndex, children: [index === projectSelectIndex ? theme.style.selectedPrefix : theme.style.unselectedPrefix, project.title] }, project.id))) }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.selectProjectHelp || 'j/k: select, Enter: confirm, Esc: cancel' })] })), mode === 'search' && (_jsx(SearchBar, { value: searchQuery, onChange: handleSearchChange, onSubmit: handleInputSubmit })), mode === 'confirm-delete' && taskToDelete && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.accent, bold: true, children: fmt(i18n.tui.deleteConfirm || 'Delete "{title}"? (y/n)', { title: taskToDelete.title }) }) })), message && mode === 'normal' && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.textHighlight, children: message }) })), _jsx(Box, { marginTop: 1, children: (mode === 'task-detail' || mode === 'add-comment') ? (theme.style.showFunctionKeys ? (_jsx(FunctionKeyBar, { keys: [
715
743
  { key: 'i', label: i18n.tui.keyBar.comment },
716
744
  { key: 'd', label: i18n.tui.keyBar.delete },
717
745
  { key: 'P', label: i18n.tui.keyBar.project },
@@ -4,6 +4,8 @@ import { Box, Text, useInput } from 'ink';
4
4
  import { t } from '../../i18n/index.js';
5
5
  import { useTheme } from '../theme/index.js';
6
6
  import { parseChangelog } from '../../changelog.js';
7
+ import { loadConfig, isTursoEnabled, getTursoConfig, getDbPath } from '../../config.js';
8
+ import { CONFIG_FILE, DATA_DIR } from '../../paths.js';
7
9
  const VISIBLE_LINES = 12;
8
10
  export function HelpModal({ onClose, isKanban = false }) {
9
11
  const [activeTab, setActiveTab] = useState('keybindings');
@@ -27,10 +29,14 @@ export function HelpModal({ onClose, isKanban = false }) {
27
29
  return items;
28
30
  }, []);
29
31
  const maxScroll = Math.max(0, changelogItems.length - VISIBLE_LINES);
32
+ const tabs = ['keybindings', 'info', 'whatsNew'];
30
33
  useInput((input, key) => {
31
34
  // Tab key detection (key.tab or raw tab character)
32
35
  if (key.tab || input === '\t') {
33
- setActiveTab(prev => prev === 'keybindings' ? 'whatsNew' : 'keybindings');
36
+ setActiveTab(prev => {
37
+ const currentIndex = tabs.indexOf(prev);
38
+ return tabs[(currentIndex + 1) % tabs.length];
39
+ });
34
40
  setScrollOffset(0);
35
41
  return;
36
42
  }
@@ -41,18 +47,29 @@ export function HelpModal({ onClose, isKanban = false }) {
41
47
  return;
42
48
  }
43
49
  if (input === '2') {
50
+ setActiveTab('info');
51
+ setScrollOffset(0);
52
+ return;
53
+ }
54
+ if (input === '3') {
44
55
  setActiveTab('whatsNew');
45
56
  setScrollOffset(0);
46
57
  return;
47
58
  }
48
59
  // Arrow keys and h/l for tab switching
49
60
  if (input === 'h' || key.leftArrow) {
50
- setActiveTab('keybindings');
61
+ setActiveTab(prev => {
62
+ const currentIndex = tabs.indexOf(prev);
63
+ return tabs[(currentIndex - 1 + tabs.length) % tabs.length];
64
+ });
51
65
  setScrollOffset(0);
52
66
  return;
53
67
  }
54
68
  if (input === 'l' || key.rightArrow) {
55
- setActiveTab('whatsNew');
69
+ setActiveTab(prev => {
70
+ const currentIndex = tabs.indexOf(prev);
71
+ return tabs[(currentIndex + 1) % tabs.length];
72
+ });
56
73
  setScrollOffset(0);
57
74
  return;
58
75
  }
@@ -73,7 +90,7 @@ export function HelpModal({ onClose, isKanban = false }) {
73
90
  }
74
91
  });
75
92
  const formatTitle = (title) => theme.style.headerUppercase ? title.toUpperCase() : title;
76
- 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: _jsxs(Box, { children: [_jsxs(Text, { bold: activeTab === 'keybindings', color: activeTab === 'keybindings' ? theme.colors.secondary : theme.colors.textMuted, inverse: activeTab === 'keybindings', children: [' ', formatTitle(help.keybindingsTab), ' '] }), _jsx(Text, { color: theme.colors.textMuted, children: " \u2502 " }), _jsxs(Text, { bold: activeTab === 'whatsNew', color: activeTab === 'whatsNew' ? theme.colors.secondary : theme.colors.textMuted, inverse: activeTab === 'whatsNew', children: [' ', formatTitle(help.whatsNewTab), ' '] })] }) }), activeTab === 'keybindings' ? (isKanban ? (_jsx(KanbanKeybindingsContent, {})) : (_jsx(GTDKeybindingsContent, {}))) : (_jsx(WhatsNewContent, { items: changelogItems, scrollOffset: scrollOffset, visibleLines: VISIBLE_LINES, maxScroll: maxScroll })), _jsx(Box, { justifyContent: "center", marginTop: 1, children: _jsx(Text, { color: theme.colors.textMuted, children: activeTab === 'whatsNew' && maxScroll > 0
93
+ 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: _jsxs(Box, { children: [_jsxs(Text, { bold: activeTab === 'keybindings', color: activeTab === 'keybindings' ? theme.colors.secondary : theme.colors.textMuted, inverse: activeTab === 'keybindings', children: [' ', formatTitle(help.keybindingsTab), ' '] }), _jsx(Text, { color: theme.colors.textMuted, children: " \u2502 " }), _jsxs(Text, { bold: activeTab === 'info', color: activeTab === 'info' ? theme.colors.secondary : theme.colors.textMuted, inverse: activeTab === 'info', children: [' ', formatTitle(help.infoTab), ' '] }), _jsx(Text, { color: theme.colors.textMuted, children: " \u2502 " }), _jsxs(Text, { bold: activeTab === 'whatsNew', color: activeTab === 'whatsNew' ? theme.colors.secondary : theme.colors.textMuted, inverse: activeTab === 'whatsNew', children: [' ', formatTitle(help.whatsNewTab), ' '] })] }) }), activeTab === 'keybindings' ? (isKanban ? (_jsx(KanbanKeybindingsContent, {})) : (_jsx(GTDKeybindingsContent, {}))) : activeTab === 'info' ? (_jsx(InfoContent, {})) : (_jsx(WhatsNewContent, { items: changelogItems, scrollOffset: scrollOffset, visibleLines: VISIBLE_LINES, maxScroll: maxScroll })), _jsx(Box, { justifyContent: "center", marginTop: 1, children: _jsx(Text, { color: theme.colors.textMuted, children: activeTab === 'whatsNew' && maxScroll > 0
77
94
  ? `j/k: scroll | ${help.tabHint} | ${help.closeHint}`
78
95
  : `${help.tabHint} | ${help.closeHint}` }) })] }));
79
96
  }
@@ -91,6 +108,26 @@ function KanbanKeybindingsContent() {
91
108
  const formatTitle = (title) => theme.style.headerUppercase ? title.toUpperCase() : title;
92
109
  return (_jsxs(_Fragment, { children: [_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: "h/l \u2190/\u2192" }), " ", help.columnSwitch] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "1-3" }), " ", help.columnDirect] }), _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: "Enter" }), " ", help.moveRight] }), _jsxs(Text, { color: theme.colors.text, children: [_jsx(Text, { color: theme.colors.textHighlight, children: "BS" }), " ", help.moveLeft] })] })] }), _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.searchTasks] }), _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] })] })] })] }));
93
110
  }
111
+ function InfoContent() {
112
+ const i18n = t();
113
+ const info = i18n.tui.info;
114
+ const theme = useTheme();
115
+ const formatTitle = (title) => theme.style.headerUppercase ? title.toUpperCase() : title;
116
+ const config = loadConfig();
117
+ const tursoEnabled = isTursoEnabled();
118
+ const tursoConfig = tursoEnabled ? getTursoConfig() : undefined;
119
+ const dbPath = getDbPath();
120
+ // Get Turso host for display
121
+ const tursoUrl = tursoConfig ? (() => {
122
+ try {
123
+ return new URL(tursoConfig.url).host;
124
+ }
125
+ catch {
126
+ return tursoConfig.url;
127
+ }
128
+ })() : '';
129
+ return (_jsxs(_Fragment, { children: [_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(info.settings) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.theme, ":"] }), " ", config.theme] }), _jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.language, ":"] }), " ", config.locale] }), _jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.viewMode, ":"] }), " ", config.viewMode] })] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(info.database) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.dbType, ":"] }), " ", tursoEnabled ? info.turso : info.local] }), _jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.dbPath, ":"] }), " ", dbPath] }), tursoEnabled && tursoUrl && (_jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.tursoUrl, ":"] }), " ", tursoUrl] }))] })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.accent, children: formatTitle(info.paths) }), _jsxs(Box, { paddingLeft: 2, flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.configFile, ":"] }), " ", CONFIG_FILE] }), _jsxs(Text, { color: theme.colors.text, children: [_jsxs(Text, { color: theme.colors.textHighlight, children: [info.dataDir, ":"] }), " ", DATA_DIR] })] })] })] }));
130
+ }
94
131
  function WhatsNewContent({ items, scrollOffset, visibleLines, maxScroll }) {
95
132
  const i18n = t();
96
133
  const whatsNew = i18n.tui.whatsNew;
@@ -12,7 +12,7 @@ import { SearchResults } from './SearchResults.js';
12
12
  import { getDb, schema } from '../../db/index.js';
13
13
  import { t, fmt } from '../../i18n/index.js';
14
14
  import { useTheme } from '../theme/index.js';
15
- import { isTursoEnabled, getTursoConfig } from '../../config.js';
15
+ import { isTursoEnabled } from '../../config.js';
16
16
  import { VERSION } from '../../version.js';
17
17
  const COLUMNS = ['todo', 'doing', 'done'];
18
18
  export function KanbanBoard({ onSwitchToGtd }) {
@@ -476,19 +476,9 @@ export function KanbanBoard({ onSwitchToGtd }) {
476
476
  const formatTitle = (title) => theme.style.headerUppercase ? title.toUpperCase() : title;
477
477
  // Turso connection info
478
478
  const tursoEnabled = isTursoEnabled();
479
- const tursoHost = tursoEnabled ? (() => {
480
- const config = getTursoConfig();
481
- if (config) {
482
- try {
483
- return new URL(config.url).host;
484
- }
485
- catch {
486
- return config.url;
487
- }
488
- }
489
- return '';
490
- })() : '';
491
- return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: formatTitle(i18n.tui.title) }), _jsx(Text, { color: theme.colors.accent, children: " [KANBAN]" }), _jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ` v${VERSION}` : ` VER ${VERSION}` }), tursoEnabled && (_jsxs(Text, { color: theme.colors.accent, children: [theme.name === 'modern' ? ' ☁️ ' : ' [SYNC] ', tursoHost] })), !tursoEnabled && (_jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ' 💾 local' : ' [LOCAL]' }))] }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.helpHint })] }), (mode === 'task-detail' || mode === 'add-comment' || mode === 'select-project') && selectedTask ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Text, { color: theme.colors.textMuted, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` - ${selectedTask.waitingFor}`, selectedTask.dueDate && ` (${selectedTask.dueDate.toLocaleDateString()})`] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
479
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsxs(Box, { marginBottom: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [_jsx(Text, { bold: true, color: theme.colors.primary, children: formatTitle(i18n.tui.title) }), _jsx(Text, { color: theme.colors.accent, children: " [KANBAN]" }), _jsx(Text, { color: theme.colors.textMuted, children: theme.name === 'modern' ? ` v${VERSION}` : ` VER ${VERSION}` }), _jsx(Text, { color: tursoEnabled ? theme.colors.accent : theme.colors.textMuted, children: theme.name === 'modern'
480
+ ? (tursoEnabled ? ' ☁️ turso' : ' 💾 local')
481
+ : (tursoEnabled ? ' [DB]turso' : ' [DB]local') })] }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.helpHint })] }), (mode === 'task-detail' || mode === 'add-comment' || mode === 'select-project') && selectedTask ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: theme.colors.accent, bold: true, children: [theme.name === 'modern' ? '📋 ' : '>> ', i18n.tui.taskDetailTitle || 'Task Details'] }), _jsxs(Text, { color: theme.colors.textMuted, children: [" (Esc/b: ", i18n.tui.back || 'back', ", ", i18n.tui.commentHint || 'i: add comment', ")"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, marginBottom: 1, children: [_jsx(Text, { color: theme.colors.text, bold: true, children: selectedTask.title }), selectedTask.description && (_jsx(Text, { color: theme.colors.textMuted, children: selectedTask.description })), _jsxs(Text, { color: theme.colors.textMuted, children: [i18n.status[selectedTask.status], selectedTask.waitingFor && ` - ${selectedTask.waitingFor}`, selectedTask.dueDate && ` (${selectedTask.dueDate.toLocaleDateString()})`] })] }), _jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.comments || 'Comments', " (", taskComments.length, ")"] }) }), _jsx(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.border, paddingX: 1, paddingY: 1, minHeight: 5, children: taskComments.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: i18n.tui.noComments || 'No comments yet' })) : (taskComments.map((comment, index) => {
492
482
  const isSelected = index === selectedCommentIndex && mode === 'task-detail';
493
483
  return (_jsxs(Box, { flexDirection: "row", marginBottom: 1, children: [_jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.textMuted, children: isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix }), _jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: theme.colors.textMuted, children: ["[", comment.createdAt.toLocaleString(), "]"] }), _jsx(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: comment.content })] })] }, comment.id));
494
484
  })) }), mode === 'add-comment' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.addComment || 'New comment: ' }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: "" }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'select-project' && (_jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsxs(Text, { color: theme.colors.secondary, bold: true, children: [i18n.tui.selectProject || 'Select project for', ": ", selectedTask.title] }), _jsx(Box, { flexDirection: "column", marginTop: 1, borderStyle: theme.borders.list, borderColor: theme.colors.borderActive, paddingX: 1, children: projects.map((project, index) => (_jsxs(Text, { color: index === projectSelectIndex ? theme.colors.textSelected : theme.colors.text, bold: index === projectSelectIndex, children: [index === projectSelectIndex ? theme.style.selectedPrefix : theme.style.unselectedPrefix, project.title] }, project.id))) }), _jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.selectProjectHelp || 'j/k: select, Enter: confirm, Esc: cancel' })] }))] })) : mode === 'search' ? (_jsx(_Fragment, { children: searchQuery && (_jsx(SearchResults, { results: searchResults, selectedIndex: searchResultIndex, query: searchQuery })) })) : (_jsxs(_Fragment, { children: [_jsx(Box, { marginBottom: 1, children: COLUMNS.map((column, index) => (_jsx(Box, { flexGrow: 1, flexBasis: 0, marginRight: index < 2 ? 1 : 0, children: _jsxs(Text, { color: currentColumnIndex === index ? theme.colors.textHighlight : theme.colors.textMuted, children: [index + 1, ":"] }) }, column))) }), _jsx(Box, { flexDirection: "row", children: COLUMNS.map((column, index) => (_jsx(KanbanColumn, { title: getColumnLabel(column), tasks: tasks[column], isActive: index === currentColumnIndex, selectedTaskIndex: selectedTaskIndices[column], columnIndex: index }, column))) })] })), mode === 'add' && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.colors.secondary, bold: true, children: i18n.tui.newTask }), _jsx(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleInputSubmit, placeholder: i18n.tui.placeholder }), _jsxs(Text, { color: theme.colors.textMuted, children: [" ", i18n.tui.inputHelp] })] })), mode === 'search' && (_jsx(SearchBar, { value: searchQuery, onChange: handleSearchChange, onSubmit: handleInputSubmit })), message && mode === 'normal' && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.textHighlight, children: message }) })), _jsx(Box, { marginTop: 1, children: mode === 'select-project' ? (_jsx(Text, { color: theme.colors.textMuted, children: i18n.tui.selectProjectHelp || 'j/k: select, Enter: confirm, Esc: cancel' })) : (mode === 'task-detail' || mode === 'add-comment') ? (theme.style.showFunctionKeys ? (_jsx(FunctionKeyBar, { keys: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floq",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Floq - Getting Things Done Task Manager with MS-DOS style themes",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",