@rewrlution/papyrus-cli 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +4 -8
  2. package/dist/cli.js +0 -4
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/auth/logout.js +2 -0
  5. package/dist/commands/auth/logout.js.map +1 -1
  6. package/dist/commands/journal/app.d.ts +1 -0
  7. package/dist/commands/journal/app.js +22 -0
  8. package/dist/commands/journal/app.js.map +1 -0
  9. package/dist/commands/journal/edit.js +8 -10
  10. package/dist/commands/journal/edit.js.map +1 -1
  11. package/dist/commands/journal/index.js +9 -10
  12. package/dist/commands/journal/index.js.map +1 -1
  13. package/dist/commands/journal/show.js +8 -14
  14. package/dist/commands/journal/show.js.map +1 -1
  15. package/dist/components/AppLayout.d.ts +32 -0
  16. package/dist/components/AppLayout.js +34 -0
  17. package/dist/components/AppLayout.js.map +1 -0
  18. package/dist/components/Divider.d.ts +7 -0
  19. package/dist/components/Divider.js +19 -0
  20. package/dist/components/Divider.js.map +1 -0
  21. package/dist/components/JournalBrowser.d.ts +14 -0
  22. package/dist/components/JournalBrowser.js +102 -0
  23. package/dist/components/JournalBrowser.js.map +1 -0
  24. package/dist/components/JournalList.d.ts +16 -0
  25. package/dist/components/JournalList.js +73 -0
  26. package/dist/components/JournalList.js.map +1 -0
  27. package/dist/components/JournalViewer.d.ts +5 -23
  28. package/dist/components/JournalViewer.js +73 -80
  29. package/dist/components/JournalViewer.js.map +1 -1
  30. package/dist/components/LoginForm.js +2 -2
  31. package/dist/components/LoginForm.js.map +1 -1
  32. package/dist/components/LogoCompact.d.ts +5 -0
  33. package/dist/components/LogoCompact.js +11 -0
  34. package/dist/components/LogoCompact.js.map +1 -0
  35. package/dist/components/RegisterForm.js +2 -2
  36. package/dist/components/RegisterForm.js.map +1 -1
  37. package/dist/components/StatusMessage.d.ts +2 -1
  38. package/dist/components/StatusMessage.js +3 -3
  39. package/dist/components/StatusMessage.js.map +1 -1
  40. package/dist/lib/auth/require-auth.js +4 -5
  41. package/dist/lib/auth/require-auth.js.map +1 -1
  42. package/dist/utils/alternate-screen.d.ts +46 -0
  43. package/dist/utils/alternate-screen.js +60 -0
  44. package/dist/utils/alternate-screen.js.map +1 -0
  45. package/dist/utils/date.js +3 -4
  46. package/dist/utils/date.js.map +1 -1
  47. package/dist/utils/editor.js +0 -1
  48. package/dist/utils/editor.js.map +1 -1
  49. package/dist/utils/journal-preview.d.ts +15 -0
  50. package/dist/utils/journal-preview.js +34 -0
  51. package/dist/utils/journal-preview.js.map +1 -0
  52. package/dist/utils/journal-preview.test.d.ts +1 -0
  53. package/dist/utils/journal-preview.test.js +62 -0
  54. package/dist/utils/journal-preview.test.js.map +1 -0
  55. package/dist/utils/messages.d.ts +43 -0
  56. package/dist/utils/messages.js +72 -0
  57. package/dist/utils/messages.js.map +1 -0
  58. package/dist/utils/text.d.ts +25 -0
  59. package/dist/utils/text.js +51 -0
  60. package/dist/utils/text.js.map +1 -0
  61. package/dist/utils/text.test.d.ts +1 -0
  62. package/dist/utils/text.test.js +47 -0
  63. package/dist/utils/text.test.js.map +1 -0
  64. package/package.json +3 -2
  65. package/dist/commands/journal/list.d.ts +0 -1
  66. package/dist/commands/journal/list.js +0 -20
  67. package/dist/commands/journal/list.js.map +0 -1
  68. package/dist/components/Browser.d.ts +0 -29
  69. package/dist/components/Browser.js +0 -124
  70. package/dist/components/Browser.js.map +0 -1
  71. package/dist/components/BrowserFooter.d.ts +0 -6
  72. package/dist/components/BrowserFooter.js +0 -6
  73. package/dist/components/BrowserFooter.js.map +0 -1
  74. package/dist/components/BrowserHeader.d.ts +0 -6
  75. package/dist/components/BrowserHeader.js +0 -6
  76. package/dist/components/BrowserHeader.js.map +0 -1
  77. package/dist/components/JournalListView.d.ts +0 -10
  78. package/dist/components/JournalListView.js +0 -40
  79. package/dist/components/JournalListView.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/utils/editor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/utils/editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAEzD;;;;;GAKG;AACH,SAAS,UAAU,CAAC,MAAc;IAChC,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,SAAS,CAAC;AACnD,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,uEAAuE;IACvE,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oEAAoE;IACpE,yFAAyF;IACzF,4DAA4D;IAC5D,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE;QAC9C,KAAK,EAAE,QAAQ;QACf,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC;QACzB,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CACb,8EAA8E,CAC/E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,eAAuB,YAAY;IAEnC,mBAAmB;IACnB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,cAAc,GAAG,GAAG,IAAI,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;IAExD,wBAAwB;IACxB,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAE9B,iCAAiC;QACjC,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE;YACrC,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,sCAAsC;SAClE,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,aAAa,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEzD,oBAAoB;QACpB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAExB,OAAO,aAAa,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8BAA8B;QAC9B,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Extract first non-empty line from journal content.
3
+ * Skips YAML frontmatter and returns the first line of actual content.
4
+ *
5
+ * @param content - Full journal content (may include frontmatter)
6
+ * @returns First non-empty content line, or "(empty)" if none found
7
+ *
8
+ * @example
9
+ * extractPreview('---\ndate: 2025-01-01\n---\n\nHello World\n')
10
+ * // Returns: "Hello World"
11
+ *
12
+ * extractPreview('---\ndate: 2025-01-01\n---\n\n')
13
+ * // Returns: "(empty)"
14
+ */
15
+ export declare function extractPreview(content: string): string;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Extract first non-empty line from journal content.
3
+ * Skips YAML frontmatter and returns the first line of actual content.
4
+ *
5
+ * @param content - Full journal content (may include frontmatter)
6
+ * @returns First non-empty content line, or "(empty)" if none found
7
+ *
8
+ * @example
9
+ * extractPreview('---\ndate: 2025-01-01\n---\n\nHello World\n')
10
+ * // Returns: "Hello World"
11
+ *
12
+ * extractPreview('---\ndate: 2025-01-01\n---\n\n')
13
+ * // Returns: "(empty)"
14
+ */
15
+ export function extractPreview(content) {
16
+ const lines = content.split('\n');
17
+ // Skip frontmatter (between --- markers)
18
+ let inFrontmatter = false;
19
+ for (const line of lines) {
20
+ if (line.trim() === '---') {
21
+ inFrontmatter = !inFrontmatter;
22
+ continue;
23
+ }
24
+ if (inFrontmatter)
25
+ continue;
26
+ // Return first non-empty line
27
+ const trimmed = line.trim();
28
+ if (trimmed) {
29
+ return trimmed;
30
+ }
31
+ }
32
+ return '(empty)';
33
+ }
34
+ //# sourceMappingURL=journal-preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-preview.js","sourceRoot":"","sources":["../../src/utils/journal-preview.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,yCAAyC;IACzC,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;YAC1B,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,IAAI,aAAa;YAAE,SAAS;QAE5B,8BAA8B;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { extractPreview } from './journal-preview.js';
3
+ describe('extractPreview', () => {
4
+ it('should extract first line after frontmatter', () => {
5
+ const content = `---
6
+ created_at: "2025-01-01T00:00:00Z"
7
+ ---
8
+
9
+ This is the first line
10
+ This is the second line`;
11
+ expect(extractPreview(content)).toBe('This is the first line');
12
+ });
13
+ it('should skip empty lines after frontmatter', () => {
14
+ const content = `---
15
+ created_at: "2025-01-01T00:00:00Z"
16
+ ---
17
+
18
+
19
+
20
+ This is the first line`;
21
+ expect(extractPreview(content)).toBe('This is the first line');
22
+ });
23
+ it('should work with content without frontmatter', () => {
24
+ const content = `This is the first line
25
+ This is the second line`;
26
+ expect(extractPreview(content)).toBe('This is the first line');
27
+ });
28
+ it('should return "(empty)" for empty content', () => {
29
+ expect(extractPreview('')).toBe('(empty)');
30
+ });
31
+ it('should return "(empty)" for content with only frontmatter', () => {
32
+ const content = `---
33
+ created_at: "2025-01-01T00:00:00Z"
34
+ ---
35
+
36
+ `;
37
+ expect(extractPreview(content)).toBe('(empty)');
38
+ });
39
+ it('should return "(empty)" for content with only whitespace', () => {
40
+ const content = `
41
+
42
+ `;
43
+ expect(extractPreview(content)).toBe('(empty)');
44
+ });
45
+ it('should handle CJK characters', () => {
46
+ const content = `---
47
+ created_at: "2025-01-01T00:00:00Z"
48
+ ---
49
+
50
+ 今日はとても良い天気でした`;
51
+ expect(extractPreview(content)).toBe('今日はとても良い天気でした');
52
+ });
53
+ it('should handle emoji', () => {
54
+ const content = `---
55
+ created_at: "2025-01-01T00:00:00Z"
56
+ ---
57
+
58
+ 🎉 Today was a great day!`;
59
+ expect(extractPreview(content)).toBe('🎉 Today was a great day!');
60
+ });
61
+ });
62
+ //# sourceMappingURL=journal-preview.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"journal-preview.test.js","sourceRoot":"","sources":["../../src/utils/journal-preview.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,OAAO,GAAG;;;;;wBAKI,CAAC;QAErB,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,OAAO,GAAG;;;;;;uBAMG,CAAC;QAEpB,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,OAAO,GAAG;wBACI,CAAC;QAErB,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,OAAO,GAAG;;;;CAInB,CAAC;QAEE,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,OAAO,GAAG;;KAEf,CAAC;QAEF,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,OAAO,GAAG;;;;cAIN,CAAC;QAEX,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,OAAO,GAAG;;;;0BAIM,CAAC;QAEvB,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Consistent messaging utilities for non-interactive console output.
3
+ *
4
+ * Use these functions for simple, transactional commands (logout, edit, etc.)
5
+ * For interactive/rich UI, use Ink components (StatusMessage, SyncProgress, etc.)
6
+ */
7
+ /**
8
+ * Display a success message with compact spacing
9
+ * @param message The success message to display
10
+ */
11
+ export declare function success(message: string): void;
12
+ /**
13
+ * Display an error message with optional hint, then exit
14
+ * @param message The error message to display
15
+ * @param hint Optional hint message to help the user
16
+ * @param exitCode Exit code (default: 1)
17
+ */
18
+ export declare function error(message: string, hint?: string, exitCode?: number): never;
19
+ /**
20
+ * Display an informational message with compact spacing
21
+ * @param message The info message to display
22
+ */
23
+ export declare function info(message: string): void;
24
+ /**
25
+ * Display a warning message with compact spacing (non-fatal)
26
+ * @param message The warning message to display
27
+ */
28
+ export declare function warn(message: string): void;
29
+ /**
30
+ * Display a hint/tip message with compact spacing
31
+ * @param message The hint message to display
32
+ */
33
+ export declare function hint(message: string): void;
34
+ /**
35
+ * Display statistics or metrics with compact spacing
36
+ * @param message The stats message to display
37
+ */
38
+ export declare function stats(message: string): void;
39
+ /**
40
+ * Display a special/celebratory message (e.g., first-time creation)
41
+ * @param message The message to display
42
+ */
43
+ export declare function sparkles(message: string): void;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Consistent messaging utilities for non-interactive console output.
3
+ *
4
+ * Use these functions for simple, transactional commands (logout, edit, etc.)
5
+ * For interactive/rich UI, use Ink components (StatusMessage, SyncProgress, etc.)
6
+ */
7
+ const icons = {
8
+ success: '✅',
9
+ error: '❌',
10
+ info: '📖',
11
+ warning: '⚠️',
12
+ hint: '💡',
13
+ stats: '📊',
14
+ sparkles: '✨',
15
+ };
16
+ /**
17
+ * Display a success message with compact spacing
18
+ * @param message The success message to display
19
+ */
20
+ export function success(message) {
21
+ console.log(`${icons.success} ${message}`);
22
+ }
23
+ /**
24
+ * Display an error message with optional hint, then exit
25
+ * @param message The error message to display
26
+ * @param hint Optional hint message to help the user
27
+ * @param exitCode Exit code (default: 1)
28
+ */
29
+ export function error(message, hint, exitCode = 1) {
30
+ console.error(`${icons.error} ${message}`);
31
+ if (hint) {
32
+ console.error(`${icons.hint} ${hint}`);
33
+ }
34
+ console.error('');
35
+ process.exit(exitCode);
36
+ }
37
+ /**
38
+ * Display an informational message with compact spacing
39
+ * @param message The info message to display
40
+ */
41
+ export function info(message) {
42
+ console.log(`${icons.info} ${message}`);
43
+ }
44
+ /**
45
+ * Display a warning message with compact spacing (non-fatal)
46
+ * @param message The warning message to display
47
+ */
48
+ export function warn(message) {
49
+ console.warn(`${icons.warning} ${message}`);
50
+ }
51
+ /**
52
+ * Display a hint/tip message with compact spacing
53
+ * @param message The hint message to display
54
+ */
55
+ export function hint(message) {
56
+ console.log(`${icons.hint} ${message}`);
57
+ }
58
+ /**
59
+ * Display statistics or metrics with compact spacing
60
+ * @param message The stats message to display
61
+ */
62
+ export function stats(message) {
63
+ console.log(`${icons.stats} ${message}`);
64
+ }
65
+ /**
66
+ * Display a special/celebratory message (e.g., first-time creation)
67
+ * @param message The message to display
68
+ */
69
+ export function sparkles(message) {
70
+ console.log(`${icons.sparkles} ${message}`);
71
+ }
72
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/utils/messages.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,KAAK,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,GAAG;CACL,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CACnB,OAAe,EACf,IAAa,EACb,WAAmB,CAAC;IAEpB,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;IAC3C,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe;IAClC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Truncate text to fit within maxWidth, handling wide characters.
3
+ * Uses string-width to properly measure CJK and emoji characters.
4
+ *
5
+ * @param text - The text to truncate
6
+ * @param maxWidth - Maximum width in columns
7
+ * @returns Truncated text with ellipsis if needed
8
+ *
9
+ * @example
10
+ * truncateToWidth('Hello World', 8) // "Hello W…"
11
+ * truncateToWidth('你好世界', 6) // "你好…" (CJK chars are 2 columns each)
12
+ */
13
+ export declare function truncateToWidth(text: string, maxWidth: number): string;
14
+ /**
15
+ * Pad text to exact width, handling wide characters.
16
+ *
17
+ * @param text - The text to pad
18
+ * @param targetWidth - Target width in columns
19
+ * @returns Padded text (or truncated if too long)
20
+ *
21
+ * @example
22
+ * padToWidth('Hello', 10) // "Hello " (5 spaces added)
23
+ * padToWidth('你好', 6) // "你好 " (2 spaces added, CJK chars are 2 columns each)
24
+ */
25
+ export declare function padToWidth(text: string, targetWidth: number): string;
@@ -0,0 +1,51 @@
1
+ import stringWidth from 'string-width';
2
+ /**
3
+ * Truncate text to fit within maxWidth, handling wide characters.
4
+ * Uses string-width to properly measure CJK and emoji characters.
5
+ *
6
+ * @param text - The text to truncate
7
+ * @param maxWidth - Maximum width in columns
8
+ * @returns Truncated text with ellipsis if needed
9
+ *
10
+ * @example
11
+ * truncateToWidth('Hello World', 8) // "Hello W…"
12
+ * truncateToWidth('你好世界', 6) // "你好…" (CJK chars are 2 columns each)
13
+ */
14
+ export function truncateToWidth(text, maxWidth) {
15
+ if (maxWidth <= 0)
16
+ return '';
17
+ const width = stringWidth(text);
18
+ if (width <= maxWidth) {
19
+ return text;
20
+ }
21
+ // Build string char by char, checking width
22
+ let result = '';
23
+ for (const char of text) {
24
+ const testStr = result + char;
25
+ if (stringWidth(testStr) > maxWidth - 1) {
26
+ // -1 for ellipsis
27
+ return result + '…';
28
+ }
29
+ result = testStr;
30
+ }
31
+ return result;
32
+ }
33
+ /**
34
+ * Pad text to exact width, handling wide characters.
35
+ *
36
+ * @param text - The text to pad
37
+ * @param targetWidth - Target width in columns
38
+ * @returns Padded text (or truncated if too long)
39
+ *
40
+ * @example
41
+ * padToWidth('Hello', 10) // "Hello " (5 spaces added)
42
+ * padToWidth('你好', 6) // "你好 " (2 spaces added, CJK chars are 2 columns each)
43
+ */
44
+ export function padToWidth(text, targetWidth) {
45
+ const width = stringWidth(text);
46
+ if (width >= targetWidth) {
47
+ return truncateToWidth(text, targetWidth);
48
+ }
49
+ return text + ' '.repeat(targetWidth - width);
50
+ }
51
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,QAAgB;IAC5D,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAE7B,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IAC5C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;QAC9B,IAAI,WAAW,CAAC,OAAO,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;YACxC,kBAAkB;YAClB,OAAO,MAAM,GAAG,GAAG,CAAC;QACtB,CAAC;QACD,MAAM,GAAG,OAAO,CAAC;IACnB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,WAAmB;IAC1D,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,KAAK,IAAI,WAAW,EAAE,CAAC;QACzB,OAAO,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { truncateToWidth, padToWidth } from './text.js';
3
+ describe('truncateToWidth', () => {
4
+ it('should return text as-is when it fits', () => {
5
+ expect(truncateToWidth('Hello', 10)).toBe('Hello');
6
+ });
7
+ it('should truncate text with ellipsis when too long', () => {
8
+ expect(truncateToWidth('Hello World', 8)).toBe('Hello W…');
9
+ });
10
+ it('should handle empty string', () => {
11
+ expect(truncateToWidth('', 5)).toBe('');
12
+ });
13
+ it('should handle zero maxWidth', () => {
14
+ expect(truncateToWidth('Hello', 0)).toBe('');
15
+ });
16
+ it('should handle CJK characters (wide chars)', () => {
17
+ // 你好 = 2 chars × 2 columns = 4 columns
18
+ expect(truncateToWidth('你好世界', 5)).toBe('你好…');
19
+ });
20
+ it('should handle emoji (wide chars)', () => {
21
+ // 👋 = 2 columns, space = 1, 'He' = 2, ellipsis = 1 → total 6
22
+ expect(truncateToWidth('👋 Hello', 6)).toBe('👋 He…');
23
+ });
24
+ });
25
+ describe('padToWidth', () => {
26
+ it('should pad text with spaces to reach target width', () => {
27
+ expect(padToWidth('Hello', 10)).toBe('Hello ');
28
+ });
29
+ it('should return text as-is when already at target width', () => {
30
+ expect(padToWidth('Hello', 5)).toBe('Hello');
31
+ });
32
+ it('should truncate text when too long', () => {
33
+ expect(padToWidth('Hello World', 8)).toBe('Hello W…');
34
+ });
35
+ it('should handle empty string', () => {
36
+ expect(padToWidth('', 5)).toBe(' ');
37
+ });
38
+ it('should handle CJK characters (wide chars)', () => {
39
+ // 你好 = 2 chars × 2 columns = 4 columns, need 2 more spaces to reach 6
40
+ expect(padToWidth('你好', 6)).toBe('你好 ');
41
+ });
42
+ it('should handle emoji (wide chars)', () => {
43
+ // 👋 = 2 columns, need 3 more spaces to reach 5
44
+ expect(padToWidth('👋', 5)).toBe('👋 ');
45
+ });
46
+ });
47
+ //# sourceMappingURL=text.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.test.js","sourceRoot":"","sources":["../../src/utils/text.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAExD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,uCAAuC;QACvC,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,8DAA8D;QAC9D,MAAM,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,sEAAsE;QACtE,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,gDAAgD;QAChD,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rewrlution/papyrus-cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "AI-powered developer journaling CLI",
5
5
  "keywords": [
6
6
  "journal",
@@ -13,7 +13,6 @@
13
13
  },
14
14
  "type": "module",
15
15
  "bin": {
16
- "pp": "./dist/cli.js",
17
16
  "paper": "./dist/cli.js",
18
17
  "papyrus": "./dist/cli.js"
19
18
  },
@@ -25,6 +24,7 @@
25
24
  "LICENSE"
26
25
  ],
27
26
  "dependencies": {
27
+ "ansi-escapes": "^7.2.0",
28
28
  "axios": "^1.13.2",
29
29
  "chalk": "^5.6.2",
30
30
  "commander": "^14.0.2",
@@ -36,6 +36,7 @@
36
36
  "ink-text-input": "^6.0.0",
37
37
  "jwt-decode": "^4.0.0",
38
38
  "react": "^19.2.3",
39
+ "string-width": "^7.2.0",
39
40
  "@rewrlution/papyrus-shared": "0.0.1"
40
41
  },
41
42
  "devDependencies": {
@@ -1 +0,0 @@
1
- export declare function listEntries(): Promise<void>;
@@ -1,20 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { render } from 'ink';
3
- import React from 'react';
4
- import { Browser } from '../../components/Browser.js';
5
- import { journalStore } from '../../lib/storage/index.js';
6
- export async function listEntries() {
7
- try {
8
- // Load all journal entries
9
- const journals = journalStore.list();
10
- // Render the interactive browser
11
- const { waitUntilExit } = render(React.createElement(Browser, { journals }));
12
- await waitUntilExit();
13
- }
14
- catch (error) {
15
- console.error(`\n❌ Error: Failed to list journal entries`);
16
- console.error(`${error.message}\n`);
17
- process.exit(1);
18
- }
19
- }
20
- //# sourceMappingURL=list.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/commands/journal/list.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,2BAA2B;QAC3B,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;QAErC,iCAAiC;QACjC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAC9B,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAC3C,CAAC;QAEF,MAAM,aAAa,EAAE,CAAC;IACxB,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC3D,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -1,29 +0,0 @@
1
- import React from 'react';
2
- import { type JournalFileInfo } from '../lib/storage/journal-storage.js';
3
- interface BrowserProps {
4
- journals: JournalFileInfo[];
5
- }
6
- /**
7
- * Interactive browser for navigating and reading journal entries.
8
- *
9
- * Features:
10
- * - List view with keyboard navigation (↑/↓ or j/k)
11
- * - Reader view with full journal content
12
- * - Circular navigation (wrap around at top/bottom)
13
- * - Today marker for current date's entry
14
- * - Virtual scrolling for large journal collections
15
- * - Press Enter to read, q to return to list or quit
16
- *
17
- * Architecture:
18
- * 1. BrowserHeader - Shows total journal count
19
- * 2. JournalListView - Virtual scrolling list of journals
20
- * 3. BrowserFooter - Keyboard shortcuts reference
21
- * 4. JournalViewer - Full journal reader (opens when selecting entry)
22
- *
23
- * State Management:
24
- * - viewMode: 'list' | 'reader' - Current view
25
- * - selectedIndex: number - Currently selected journal in list
26
- * - selectedJournal: JournalFileInfo | null - Journal being read
27
- */
28
- export declare const Browser: React.FC<BrowserProps>;
29
- export {};
@@ -1,124 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text, useInput, useApp } from 'ink';
3
- import { useState } from 'react';
4
- import { journalStore } from '../lib/storage/index.js';
5
- import { getTodayDate } from '../utils/date.js';
6
- import { BrowserFooter } from './BrowserFooter.js';
7
- import { BrowserHeader } from './BrowserHeader.js';
8
- import { JournalListView } from './JournalListView.js';
9
- import { JournalViewer } from './JournalViewer.js';
10
- /**
11
- * Interactive browser for navigating and reading journal entries.
12
- *
13
- * Features:
14
- * - List view with keyboard navigation (↑/↓ or j/k)
15
- * - Reader view with full journal content
16
- * - Circular navigation (wrap around at top/bottom)
17
- * - Today marker for current date's entry
18
- * - Virtual scrolling for large journal collections
19
- * - Press Enter to read, q to return to list or quit
20
- *
21
- * Architecture:
22
- * 1. BrowserHeader - Shows total journal count
23
- * 2. JournalListView - Virtual scrolling list of journals
24
- * 3. BrowserFooter - Keyboard shortcuts reference
25
- * 4. JournalViewer - Full journal reader (opens when selecting entry)
26
- *
27
- * State Management:
28
- * - viewMode: 'list' | 'reader' - Current view
29
- * - selectedIndex: number - Currently selected journal in list
30
- * - selectedJournal: JournalFileInfo | null - Journal being read
31
- */
32
- export const Browser = ({ journals }) => {
33
- // State management
34
- const [selectedIndex, setSelectedIndex] = useState(0);
35
- const [viewMode, setViewMode] = useState('list');
36
- const [selectedJournal, setSelectedJournal] = useState(null);
37
- const [journalContent, setJournalContent] = useState('');
38
- const { exit } = useApp();
39
- const today = getTodayDate();
40
- // Keyboard input handlers
41
- useInput((input, key) => {
42
- // Handle list view navigation
43
- if (viewMode === 'list') {
44
- // Navigate up (↑ or k)
45
- if (key.upArrow || input === 'k') {
46
- handleNavigateUp();
47
- return;
48
- }
49
- // Navigate down (↓ or j)
50
- if (key.downArrow || input === 'j') {
51
- handleNavigateDown();
52
- return;
53
- }
54
- // Open journal (Enter or Space)
55
- if (key.return || input === ' ') {
56
- handleOpenJournal();
57
- return;
58
- }
59
- // Quit from list view (q or Escape)
60
- if (input === 'q' || key.escape) {
61
- exit();
62
- return;
63
- }
64
- }
65
- // Note: Reader view keyboard handling is done by JournalViewer component
66
- // It will call handleBackToList() when user presses 'q'
67
- });
68
- // Navigation handlers
69
- const handleNavigateUp = () => {
70
- setSelectedIndex((current) => {
71
- const next = current - 1;
72
- // Circular navigation: if at top, wrap to bottom
73
- if (next < 0) {
74
- return journals.length - 1;
75
- }
76
- return next;
77
- });
78
- };
79
- const handleNavigateDown = () => {
80
- setSelectedIndex((current) => {
81
- const next = current + 1;
82
- // Circular navigation: if at bottom, wrap to top
83
- if (next >= journals.length) {
84
- return 0;
85
- }
86
- return next;
87
- });
88
- };
89
- const handleOpenJournal = () => {
90
- const journal = journals[selectedIndex];
91
- if (journal) {
92
- try {
93
- // Load journal content
94
- const content = journalStore.load(journal.date);
95
- if (content) {
96
- setSelectedJournal(journal);
97
- setJournalContent(content);
98
- setViewMode('reader');
99
- }
100
- }
101
- catch (error) {
102
- // If loading fails, stay in list view
103
- // The error will be visible in the console
104
- console.error(`Failed to load journal: ${error}`);
105
- }
106
- }
107
- };
108
- const handleBackToList = () => {
109
- setViewMode('list');
110
- setSelectedJournal(null);
111
- setJournalContent('');
112
- };
113
- // Empty state
114
- if (journals.length === 0) {
115
- return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", padding: 1, children: [_jsx(Text, { color: "yellow", children: "No journal entries yet." }), _jsx(Text, { dimColor: true, children: " Run 'papyrus add' to create your first entry." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Press 'q' to quit" }) })] }));
116
- }
117
- // Reader view
118
- if (viewMode === 'reader' && selectedJournal) {
119
- return (_jsx(JournalViewer, { date: selectedJournal.date, content: journalContent, onExit: handleBackToList }));
120
- }
121
- // List view (default)
122
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(BrowserHeader, { totalJournals: journals.length }), _jsx(JournalListView, { journals: journals, selectedIndex: selectedIndex, todayDate: today, windowSize: 10 }), _jsx(BrowserFooter, { shortcuts: "\u2191\u2193/jk Navigate \u2022 Enter Read \u2022 q Quit" })] }));
123
- };
124
- //# sourceMappingURL=Browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Browser.js","sourceRoot":"","sources":["../../src/components/Browser.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- interface BrowserFooterProps {
3
- shortcuts: string;
4
- }
5
- export declare const BrowserFooter: React.FC<BrowserFooterProps>;
6
- export {};
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- export const BrowserFooter = ({ shortcuts }) => {
4
- return (_jsx(Box, { marginTop: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: _jsx(Text, { dimColor: true, children: shortcuts }) }));
5
- };
6
- //# sourceMappingURL=BrowserFooter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BrowserFooter.js","sourceRoot":"","sources":["../../src/components/BrowserFooter.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAOhC,MAAM,CAAC,MAAM,aAAa,GAAiC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;IAC3E,OAAO,CACL,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,MAAM,EAAC,QAAQ,EAAE,CAAC,YACnE,KAAC,IAAI,IAAC,QAAQ,kBAAE,SAAS,GAAQ,GAC7B,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -1,6 +0,0 @@
1
- import React from 'react';
2
- interface BrowserHeaderProps {
3
- totalJournals: number;
4
- }
5
- export declare const BrowserHeader: React.FC<BrowserHeaderProps>;
6
- export {};