diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 02a80f8..c84258b 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -40,8 +40,6 @@ jobs: run: | npm pack - - - name: List files in typescript dir working-directory: ./typescript run: | diff --git a/typescript/examples/vite_basic/public/spacing_test.json b/typescript/examples/vite_basic/public/spacing_test.json new file mode 100644 index 0000000..9f3247c --- /dev/null +++ b/typescript/examples/vite_basic/public/spacing_test.json @@ -0,0 +1,1056 @@ +{ + "object": "page", + "id": "pg_spacing_test_document", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "properties": { + "title": { + "type": "title", + "title": [ + { + "type": "text", + "text": { + "content": "JSON-DOC Block Spacing Test" + }, + "annotations": {}, + "plain_text": "JSON-DOC Block Spacing Test" + } + ] + } + }, + "children": [ + { + "object": "block", + "id": "blk_heading1_top", + "type": "heading_1", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_1": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 1" + }, + "annotations": {}, + "plain_text": "Heading 1" + } + ] + } + }, + { + "object": "block", + "id": "blk_heading2_top", + "type": "heading_2", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_2": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 2" + }, + "annotations": {}, + "plain_text": "Heading 2" + } + ] + } + }, + { + "object": "block", + "id": "blk_heading3_top", + "type": "heading_3", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_3": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 3" + }, + "annotations": {}, + "plain_text": "Heading 3" + } + ] + } + }, + { + "object": "block", + "id": "blk_heading1_1", + "type": "heading_1", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_1": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 1 - Main Title" + }, + "annotations": {}, + "plain_text": "Heading 1 - Main Title" + } + ] + } + }, + { + "object": "block", + "id": "blk_paragraph_1", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is a paragraph that comes after Heading 1. It should have proper spacing above and below. The text can be " + }, + "annotations": {}, + "plain_text": "This is a paragraph that comes after Heading 1. It should have proper spacing above and below. The text can be " + }, + { + "type": "text", + "text": { + "content": "bold" + }, + "annotations": { + "bold": true + }, + "plain_text": "bold" + }, + { + "type": "text", + "text": { + "content": ", " + }, + "annotations": {}, + "plain_text": ", " + }, + { + "type": "text", + "text": { + "content": "italic" + }, + "annotations": { + "italic": true + }, + "plain_text": "italic" + }, + { + "type": "text", + "text": { + "content": ", or " + }, + "annotations": {}, + "plain_text": ", or " + }, + { + "type": "text", + "text": { + "content": "both bold and italic" + }, + "annotations": { + "bold": true, + "italic": true + }, + "plain_text": "both bold and italic" + }, + { + "type": "text", + "text": { + "content": "." + }, + "annotations": {}, + "plain_text": "." + } + ] + } + }, + { + "object": "block", + "id": "blk_heading2_1", + "type": "heading_2", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_2": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 2 - Secondary Title" + }, + "annotations": {}, + "plain_text": "Heading 2 - Secondary Title" + } + ] + } + }, + { + "object": "block", + "id": "blk_paragraph_2", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Another paragraph after Heading 2. Notice the spacing relationship between headings and paragraphs." + }, + "annotations": {}, + "plain_text": "Another paragraph after Heading 2. Notice the spacing relationship between headings and paragraphs." + } + ] + } + }, + { + "object": "block", + "id": "blk_heading3_1", + "type": "heading_3", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "heading_3": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Heading 3 - Tertiary Title" + }, + "annotations": {}, + "plain_text": "Heading 3 - Tertiary Title" + } + ] + } + }, + { + "object": "block", + "id": "blk_bulleted_list_1", + "type": "bulleted_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "bulleted_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "First bulleted list item" + }, + "annotations": {}, + "plain_text": "First bulleted list item" + } + ] + } + }, + { + "object": "block", + "id": "blk_bulleted_list_2", + "type": "bulleted_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "bulleted_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Second bulleted list item with " + }, + "annotations": {}, + "plain_text": "Second bulleted list item with " + }, + { + "type": "text", + "text": { + "content": "bold text" + }, + "annotations": { + "bold": true + }, + "plain_text": "bold text" + } + ] + } + }, + { + "object": "block", + "id": "blk_bulleted_list_3", + "type": "bulleted_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "bulleted_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Third bulleted list item" + }, + "annotations": {}, + "plain_text": "Third bulleted list item" + } + ] + } + }, + { + "object": "block", + "id": "blk_numbered_list_1", + "type": "numbered_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "numbered_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "First numbered list item" + }, + "annotations": {}, + "plain_text": "First numbered list item" + } + ] + } + }, + { + "object": "block", + "id": "blk_numbered_list_2", + "type": "numbered_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "numbered_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Second numbered list item" + }, + "annotations": {}, + "plain_text": "Second numbered list item" + } + ] + } + }, + { + "object": "block", + "id": "blk_numbered_list_3", + "type": "numbered_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "numbered_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Third numbered list item" + }, + "annotations": {}, + "plain_text": "Third numbered list item" + } + ] + } + }, + { + "object": "block", + "id": "blk_quote_1", + "type": "quote", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "quote": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is a quote block. It should be visually distinct from paragraphs with proper indentation and styling. Quote blocks are often used for citations or emphasized text." + }, + "annotations": {}, + "plain_text": "This is a quote block. It should be visually distinct from paragraphs with proper indentation and styling. Quote blocks are often used for citations or emphasized text." + } + ] + } + }, + { + "object": "block", + "id": "blk_code_1", + "type": "code", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "code": { + "language": "javascript", + "rich_text": [ + { + "type": "text", + "text": { + "content": "// This is a code block\nfunction helloWorld() {\n console.log('Hello, World!');\n return 'Perfect spacing test';\n}\n\n// Multiple lines to test spacing\nconst result = helloWorld();" + }, + "annotations": {}, + "plain_text": "// This is a code block\nfunction helloWorld() {\n console.log('Hello, World!');\n return 'Perfect spacing test';\n}\n\n// Multiple lines to test spacing\nconst result = helloWorld();" + } + ] + } + }, + { + "object": "block", + "id": "blk_to_do_1", + "type": "to_do", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "to_do": { + "checked": false, + "rich_text": [ + { + "type": "text", + "text": { + "content": "Unchecked to-do item" + }, + "annotations": {}, + "plain_text": "Unchecked to-do item" + } + ] + } + }, + { + "object": "block", + "id": "blk_to_do_2", + "type": "to_do", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "to_do": { + "checked": true, + "rich_text": [ + { + "type": "text", + "text": { + "content": "Checked to-do item" + }, + "annotations": {}, + "plain_text": "Checked to-do item" + } + ] + } + }, + { + "object": "block", + "id": "blk_to_do_3", + "type": "to_do", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "to_do": { + "checked": false, + "rich_text": [ + { + "type": "text", + "text": { + "content": "Another to-do with " + }, + "annotations": {}, + "plain_text": "Another to-do with " + }, + { + "type": "text", + "text": { + "content": "formatted text" + }, + "annotations": { + "bold": true, + "italic": true + }, + "plain_text": "formatted text" + } + ] + } + }, + { + "object": "block", + "id": "blk_divider_1", + "type": "divider", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "divider": {} + }, + { + "object": "block", + "id": "blk_paragraph_3", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This paragraph comes after a divider. The divider should have proper spacing above and below to separate content sections." + }, + "annotations": {}, + "plain_text": "This paragraph comes after a divider. The divider should have proper spacing above and below to separate content sections." + } + ] + } + }, + { + "object": "block", + "id": "blk_equation_1", + "type": "equation", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "equation": { + "expression": "E = mc^2" + } + }, + { + "object": "block", + "id": "blk_table_1", + "type": "table", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table": { + "table_width": 3, + "has_column_header": true, + "has_row_header": false + }, + "children": [ + { + "object": "block", + "id": "blk_table_row_1", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "Header 1" + }, + "annotations": { + "bold": true + }, + "plain_text": "Header 1" + } + ], + [ + { + "type": "text", + "text": { + "content": "Header 2" + }, + "annotations": { + "bold": true + }, + "plain_text": "Header 2" + } + ], + [ + { + "type": "text", + "text": { + "content": "Header 3" + }, + "annotations": { + "bold": true + }, + "plain_text": "Header 3" + } + ] + ] + } + }, + { + "object": "block", + "id": "blk_table_row_2", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "Row 1, Col 1" + }, + "annotations": {}, + "plain_text": "Row 1, Col 1" + } + ], + [ + { + "type": "text", + "text": { + "content": "Row 1, Col 2" + }, + "annotations": {}, + "plain_text": "Row 1, Col 2" + } + ], + [ + { + "type": "text", + "text": { + "content": "Row 1, Col 3" + }, + "annotations": {}, + "plain_text": "Row 1, Col 3" + } + ] + ] + } + }, + { + "object": "block", + "id": "blk_table_row_3", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "Row 2, Col 1" + }, + "annotations": {}, + "plain_text": "Row 2, Col 1" + } + ], + [ + { + "type": "text", + "text": { + "content": "Row 2, Col 2" + }, + "annotations": {}, + "plain_text": "Row 2, Col 2" + } + ], + [ + { + "type": "text", + "text": { + "content": "Row 2, Col 3" + }, + "annotations": {}, + "plain_text": "Row 2, Col 3" + } + ] + ] + } + }, + { + "object": "block", + "id": "blk_table_row_4", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "This is a very long cell content that should wrap properly within the table cell boundaries and test the word wrapping functionality" + }, + "annotations": {}, + "plain_text": "This is a very long cell content that should wrap properly within the table cell boundaries and test the word wrapping functionality" + } + ], + [ + { + "type": "text", + "text": { + "content": "Short" + }, + "annotations": {}, + "plain_text": "Short" + } + ], + [ + { + "type": "text", + "text": { + "content": "Medium length content here" + }, + "annotations": {}, + "plain_text": "Medium length content here" + } + ] + ] + } + }, + { + "object": "block", + "id": "blk_table_row_5", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "Normal text" + }, + "annotations": {}, + "plain_text": "Normal text" + } + ], + [ + { + "type": "text", + "text": { + "content": "This column has super long content that would normally cause horizontal overflow in a constrained container but should now wrap properly" + }, + "annotations": {}, + "plain_text": "This column has super long content that would normally cause horizontal overflow in a constrained container but should now wrap properly" + } + ], + [ + { + "type": "text", + "text": { + "content": "Another cell" + }, + "annotations": {}, + "plain_text": "Another cell" + } + ] + ] + } + }, + { + "object": "block", + "id": "blk_table_row_6", + "type": "table_row", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "table_row": { + "cells": [ + [ + { + "type": "text", + "text": { + "content": "URL Test" + }, + "annotations": {}, + "plain_text": "URL Test" + } + ], + [ + { + "type": "text", + "text": { + "content": "https://example.com/very-long-url-path/that-might-cause-overflow/if-not-handled-properly" + }, + "annotations": {}, + "plain_text": "https://example.com/very-long-url-path/that-might-cause-overflow/if-not-handled-properly" + } + ], + [ + { + "type": "text", + "text": { + "content": "Final column content that has moderate length" + }, + "annotations": {}, + "plain_text": "Final column content that has moderate length" + } + ] + ] + } + } + ] + }, + { + "object": "block", + "id": "blk_toggle_1", + "type": "toggle", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "toggle": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Toggle Block - Click to expand" + }, + "annotations": {}, + "plain_text": "Toggle Block - Click to expand" + } + ] + }, + "children": [ + { + "object": "block", + "id": "blk_toggle_child_1", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is hidden content inside the toggle block. It should have proper indentation and spacing." + }, + "annotations": {}, + "plain_text": "This is hidden content inside the toggle block. It should have proper indentation and spacing." + } + ] + } + }, + { + "object": "block", + "id": "blk_toggle_child_2", + "type": "bulleted_list_item", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "bulleted_list_item": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "Nested list item in toggle" + }, + "annotations": {}, + "plain_text": "Nested list item in toggle" + } + ] + } + } + ] + }, + { + "object": "block", + "id": "blk_column_list_1", + "type": "column_list", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "column_list": {}, + "children": [ + { + "object": "block", + "id": "blk_column_1", + "type": "column", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "column": {}, + "children": [ + { + "object": "block", + "id": "blk_column_1_paragraph_1", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is the first column. Columns should be displayed side by side with proper spacing and alignment." + }, + "annotations": {}, + "plain_text": "This is the first column. Columns should be displayed side by side with proper spacing and alignment." + } + ] + } + } + ] + }, + { + "object": "block", + "id": "blk_column_2", + "type": "column", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "column": {}, + "children": [ + { + "object": "block", + "id": "blk_column_2_paragraph_1", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is the second column. The spacing between columns should be consistent and visually appealing." + }, + "annotations": {}, + "plain_text": "This is the second column. The spacing between columns should be consistent and visually appealing." + } + ] + } + } + ] + } + ] + }, + { + "object": "block", + "id": "blk_image_1", + "type": "image", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "image": { + "type": "external", + "external": { + "url": "https://images.unsplash.com/photo-1503327431567-3ab5e6e79140?ixlib=rb-4.1.0&q=85&fm=jpg&crop=entropy&cs=srgb&w=4800" + }, + "caption": [ + { + "type": "text", + "text": { + "content": "This is a sample image with a caption. Image blocks should thiyyy This is a sample image with a caption. Image blocks should thiyyy" + }, + "annotations": {}, + "plain_text": "This is a sample image with a caption. Image blocks should" + } + ] + } + }, + { + "object": "block", + "id": "blk_paragraph_final", + "type": "paragraph", + "created_time": "2025-06-19T14:04:08.260514Z", + "created_by": { + "object": "user", + "id": "28a08aa3-192b-45e6-b6d3-32b8032d8c7b" + }, + "paragraph": { + "rich_text": [ + { + "type": "text", + "text": { + "content": "This is the final paragraph in our spacing test document. It demonstrates how all block types work together with consistent spacing throughout the document." + }, + "annotations": {}, + "plain_text": "This is the final paragraph in our spacing test document. It demonstrates how all block types work together with consistent spacing throughout the document." + } + ] + } + } + ] +} diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 2851e7e..9c994d6 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -1,15 +1,50 @@ import { JsonDocRenderer, PageDelimiter } from "@textcortex/jsondoc"; import "@textcortex/jsondoc/dist/index.css"; import { useState, useEffect } from "react"; +import DevPanel from "./components/DevPanel"; + +// Test backrefs for highlighting +const testBackrefs: Array<{ + end_idx: number; + block_id: string; + start_idx: number; +}> = [ + // { + // end_idx: 50, + // block_id: "blk_table_row_5", + // start_idx: 0, + // }, + // { + // end_idx: 40, + // block_id: "blk_toggle_1", + // start_idx: 12, + // }, + // { + // end_idx: 80, + // block_id: "bk_01jxwgvydze3bsy2p19cfteqge", + // start_idx: 20, + // }, + // { + // block_id: "bk_01jxwgvyehecbb2bv3jtnm9bzx", + // start_idx: 0, + // end_idx: 70, + // }, + // { + // block_id: "bk_01jxj01879f8cvyq2hqc6p37z2", + // start_idx: 0, + // end_idx: 170, + // }, +]; const App = () => { const [testPage, setTestPage] = useState(null); const [devMode, setDevMode] = useState(false); + const [theme, setTheme] = useState<"light" | "dark">("dark"); useEffect(() => { const loadData = async () => { try { - const response = await fetch("/test_document.json"); + const response = await fetch("/spacing_test.json"); const data = await response.json(); setTestPage(data); } catch (error) { @@ -23,70 +58,34 @@ const App = () => { return
Loading...
; } - // Test backrefs for highlighting - const testBackrefs = [ - { - end_idx: 50, - block_id: "bk_01jxwgvye6er08spmyxj99f6cp", - start_idx: 0, - }, - { - end_idx: 100, - block_id: "bk_01jxwgvydyfj6rhm125q1rd4h8", - start_idx: 70, - }, - { - end_idx: 80, - block_id: "bk_01jxwgvydze3bsy2p19cfteqge", - start_idx: 20, - }, - // { - // block_id: "bk_01jxwgvyehecbb2bv3jtnm9bzx", - // start_idx: 0, - // end_idx: 70, - // }, - // { - // block_id: "bk_01jxj01879f8cvyq2hqc6p37z2", - // start_idx: 0, - // end_idx: 170, - // }, - ]; - return (
-
-

JSON-DOC Renderer Development

- -
- -
+ +
void; + theme: "light" | "dark"; + setTheme: (theme: "light" | "dark") => void; +} + +const DevPanel: React.FC = ({ + devMode, + setDevMode, + theme, + setTheme, +}) => { + return ( + <> + {/* Floating Dev Mode Button */} + setDevMode(!devMode)} + backgroundColor={devMode ? "oklch(60% 0.2 250)" : "oklch(40% 0.2 250)"} + offset={{ x: 20, y: 20 }} + > + {devMode ? "Disable" : "Enable"} Dev Mode + + + {/* Floating Theme Toggle Button */} + setTheme(theme === "dark" ? "light" : "dark")} + backgroundColor={ + theme === "dark" ? "oklch(60% 0.2 50)" : "oklch(40% 0.2 50)" + } + offset={{ x: 200, y: 20 }} + > + {theme === "dark" ? "☀️ Light" : "🌙 Dark"} Mode + + + ); +}; + +export default DevPanel; diff --git a/typescript/examples/vite_basic/src/components/FloatingButton.tsx b/typescript/examples/vite_basic/src/components/FloatingButton.tsx new file mode 100644 index 0000000..1b8fe95 --- /dev/null +++ b/typescript/examples/vite_basic/src/components/FloatingButton.tsx @@ -0,0 +1,63 @@ +import React from "react"; + +interface FloatingButtonProps { + onClick: () => void; + children: React.ReactNode; + position?: "top-right" | "top-left" | "bottom-right" | "bottom-left"; + offset?: { x: number; y: number }; + backgroundColor?: string; + color?: string; + zIndex?: number; +} + +const FloatingButton: React.FC = ({ + onClick, + children, + position = "top-right", + offset = { x: 20, y: 20 }, + backgroundColor = "oklch(40% 0.2 250)", + color = "white", + zIndex = 1000, +}) => { + const getPositionStyles = () => { + switch (position) { + case "top-left": + return { top: offset.y, left: offset.x }; + case "bottom-right": + return { bottom: offset.y, right: offset.x }; + case "bottom-left": + return { bottom: offset.y, left: offset.x }; + default: + return { top: offset.y, right: offset.x }; + } + }; + + return ( + + ); +}; + +export default FloatingButton; diff --git a/typescript/package-lock.json b/typescript/package-lock.json index 3f0742e..04b271b 100644 --- a/typescript/package-lock.json +++ b/typescript/package-lock.json @@ -9,6 +9,7 @@ "version": "0.2.0-alpha.4", "license": "MIT", "dependencies": { + "@types/katex": "^0.16.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "katex": "^0.16.22", @@ -16,6 +17,7 @@ }, "devDependencies": { "@eslint/js": "^9.28.0", + "@size-limit/preset-small-lib": "^11.2.0", "@types/jest": "^29.5.14", "@types/node": "^22.15.27", "@types/react": "^19.1.5", @@ -40,6 +42,7 @@ "lint-staged": "^15.5.2", "prettier": "3.5.3", "puppeteer": "^24.9.0", + "size-limit": "^11.2.0", "strip-json-comments": "^5.0.2", "ts-jest": "^29.3.4", "ts-node": "^10.9.2", @@ -2160,6 +2163,66 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@size-limit/esbuild": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@size-limit/esbuild/-/esbuild-11.2.0.tgz", + "integrity": "sha512-vSg9H0WxGQPRzDnBzeDyD9XT0Zdq0L+AI3+77/JhxznbSCMJMMr8ndaWVQRhOsixl97N0oD4pRFw2+R1Lcvi6A==", + "dev": true, + "dependencies": { + "esbuild": "^0.25.0", + "nanoid": "^5.1.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "size-limit": "11.2.0" + } + }, + "node_modules/@size-limit/esbuild/node_modules/nanoid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@size-limit/file": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-11.2.0.tgz", + "integrity": "sha512-OZHE3putEkQ/fgzz3Tp/0hSmfVo3wyTpOJSRNm6AmcwX4Nm9YtTfbQQ/hZRwbBFR23S7x2Sd9EbqYzngKwbRoA==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "size-limit": "11.2.0" + } + }, + "node_modules/@size-limit/preset-small-lib": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@size-limit/preset-small-lib/-/preset-small-lib-11.2.0.tgz", + "integrity": "sha512-RFbbIVfv8/QDgTPyXzjo5NKO6CYyK5Uq5xtNLHLbw5RgSKrgo8WpiB/fNivZuNd/5Wk0s91PtaJ9ThNcnFuI3g==", + "dev": true, + "dependencies": { + "@size-limit/esbuild": "11.2.0", + "@size-limit/file": "11.2.0", + "size-limit": "11.2.0" + }, + "peerDependencies": { + "size-limit": "11.2.0" + } + }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", @@ -2316,6 +2379,11 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==" + }, "node_modules/@types/lodash": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", @@ -3645,6 +3713,15 @@ "esbuild": ">=0.18" } }, + "node_modules/bytes-iec": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes-iec/-/bytes-iec-3.1.1.tgz", + "integrity": "sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/c12": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/c12/-/c12-3.0.4.tgz", @@ -7611,7 +7688,6 @@ "https://opencollective.com/katex", "https://github.com/sponsors/katex" ], - "license": "MIT", "dependencies": { "commander": "^8.3.0" }, @@ -8425,6 +8501,15 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/nanospinner": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.2.2.tgz", + "integrity": "sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==", + "dev": true, + "dependencies": { + "picocolors": "^1.1.1" + } + }, "node_modules/napi-postinstall": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz", @@ -9870,6 +9955,27 @@ "dev": true, "license": "MIT" }, + "node_modules/size-limit": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/size-limit/-/size-limit-11.2.0.tgz", + "integrity": "sha512-2kpQq2DD/pRpx3Tal/qRW1SYwcIeQ0iq8li5CJHQgOC+FtPn2BVmuDtzUCgNnpCrbgtfEHqh+iWzxK+Tq6C+RQ==", + "dev": true, + "dependencies": { + "bytes-iec": "^3.1.1", + "chokidar": "^4.0.3", + "jiti": "^2.4.2", + "lilconfig": "^3.1.3", + "nanospinner": "^1.2.2", + "picocolors": "^1.1.1", + "tinyglobby": "^0.2.11" + }, + "bin": { + "size-limit": "bin.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", diff --git a/typescript/package.json b/typescript/package.json index 0f0cc66..f156384 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -20,7 +20,8 @@ "check": "tsc --noEmit", "lint": "eslint src --ext .ts,.tsx", "lint:fix": "eslint src --ext .ts,.tsx --fix", - "prepare": "husky" + "prepare": "husky", + "size": "npm run build && size-limit" }, "keywords": [ "json", @@ -32,6 +33,7 @@ "license": "MIT", "devDependencies": { "@eslint/js": "^9.28.0", + "@size-limit/preset-small-lib": "^11.2.0", "@types/jest": "^29.5.14", "@types/node": "^22.15.27", "@types/react": "^19.1.5", @@ -52,17 +54,19 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "json-schema-to-typescript": "^15.0.4", + "json5": "^2.2.3", "lint-staged": "^15.5.2", "prettier": "3.5.3", + "puppeteer": "^24.9.0", + "size-limit": "^11.2.0", + "strip-json-comments": "^5.0.2", "ts-jest": "^29.3.4", "ts-node": "^10.9.2", "tsup": "^8.5.0", - "typescript": "^5.8.3", - "puppeteer": "^24.9.0", - "strip-json-comments": "^5.0.2", - "json5": "^2.2.3" + "typescript": "^5.8.3" }, "dependencies": { + "@types/katex": "^0.16.7", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "katex": "^0.16.22", @@ -96,5 +100,19 @@ "*.{ts,tsx}": [ "eslint --fix" ] - } + }, + "size-limit": [ + { + "path": "dist/index.js", + "limit": "20 KB" + }, + { + "path": "dist/index.mjs", + "limit": "20 KB" + }, + { + "path": "dist/index.css", + "limit": "20 KB" + } + ] } diff --git a/typescript/src/index.ts b/typescript/src/index.ts index 3d13119..8b3c805 100644 --- a/typescript/src/index.ts +++ b/typescript/src/index.ts @@ -3,12 +3,7 @@ */ // Export utility functions -export { - loadJson, - getNestedValue, - setNestedValue, - deepClone, -} from "./utils/json"; +export { loadJson, deepClone } from "./utils/json"; // Export React renderer components export { diff --git a/typescript/src/renderer/JsonDocRenderer.tsx b/typescript/src/renderer/JsonDocRenderer.tsx index cc72773..e207a07 100644 --- a/typescript/src/renderer/JsonDocRenderer.tsx +++ b/typescript/src/renderer/JsonDocRenderer.tsx @@ -37,8 +37,6 @@ export const JsonDocRenderer = ({ viewJson = false, backrefs = [], }: JsonDocRendererProps) => { - console.log("page: ", page); - // Use the modular hooks for highlight management const { highlightCount, currentActiveIndex, navigateToHighlight } = useHighlights({ diff --git a/typescript/src/renderer/components/PageDelimiter.tsx b/typescript/src/renderer/components/PageDelimiter.tsx index 8a606c6..b583856 100644 --- a/typescript/src/renderer/components/PageDelimiter.tsx +++ b/typescript/src/renderer/components/PageDelimiter.tsx @@ -11,9 +11,8 @@ export const PageDelimiter: React.FC = ({ }) => { return (
-
- Page {pageNumber} -
+
+ Page {pageNumber}
); }; diff --git a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx index 80be805..72a5b41 100644 --- a/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ColumnListBlockRenderer.tsx @@ -22,7 +22,7 @@ export const ColumnListBlockRenderer: React.FC< >
{block.children?.map((child, index: number) => { if (child?.type === "column") { diff --git a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx index 7f26509..d798ba6 100644 --- a/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/EquationBlockRenderer.tsx @@ -1,4 +1,5 @@ -import React from "react"; +import React, { useEffect, useRef } from "react"; +import katex from "katex"; import { EquationBlock } from "@/models/generated"; @@ -14,6 +15,25 @@ export const EquationBlockRenderer: React.FC = ({ ...props }) => { const equationData = block.equation; + const containerRef = useRef(null); + + useEffect(() => { + if (containerRef.current && equationData?.expression) { + try { + katex.render(equationData.expression, containerRef.current, { + displayMode: true, + throwOnError: false, + errorColor: '#cc0000', + strict: 'warn' + }); + } catch (error) { + console.warn('KaTeX render error:', error); + if (containerRef.current) { + containerRef.current.textContent = equationData.expression; + } + } + } + }, [equationData?.expression]); return (
= ({ >
-
- {equationData?.expression || ""} -
+
diff --git a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx index 0f1991a..b26f70a 100644 --- a/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ImageBlockRenderer.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useRef } from "react"; import { useInView } from "react-intersection-observer"; import { useRenderer } from "../../context/RendererContext"; @@ -41,7 +41,9 @@ export const ImageBlockRenderer: React.FC = ({ const [isLoading, setIsLoading] = useState(false); const [hasError, setHasError] = useState(false); const [showFullCaption, setShowFullCaption] = useState(false); + const [needsTruncation, setNeedsTruncation] = useState(false); const { ref, inView } = useInView({ threshold: 0.1, triggerOnce: true }); + const captionRef = useRef(null); const getImageUrl = () => { if (imageData?.type === "external") { @@ -86,6 +88,14 @@ export const ImageBlockRenderer: React.FC = ({ }; }, [inView, imageUrl, resolveImageUrl]); + useEffect(() => { + if (captionRef.current && imageData?.caption && imageData.caption.length > 0) { + const element = captionRef.current; + const isOverflowing = element.scrollHeight > element.clientHeight; + setNeedsTruncation(isOverflowing); + } + }, [imageData?.caption]); + return (
= ({
- + {needsTruncation && ( + + )}
)} diff --git a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx index adc8483..3b9b4be 100644 --- a/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ListItemBlockRenderer.tsx @@ -39,7 +39,7 @@ export const ListItemBlockRenderer: React.FC = ({ {block.type === "bulleted_list_item" && (
)} -
+
diff --git a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx index ba0647b..8868671 100644 --- a/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/QuoteBlockRenderer.tsx @@ -27,10 +27,8 @@ export const QuoteBlockRenderer: React.FC = ({ data-block-id={block.id} >
-
-
- -
+
+
diff --git a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx index 97cb673..e82f094 100644 --- a/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/TableBlockRenderer.tsx @@ -26,71 +26,45 @@ export const TableBlockRenderer: React.FC = ({ className={`notion-selectable notion-table-block${className ? ` ${className}` : ""}`} data-block-id={block.id} > -
-
-
-
- - - {block.children?.map((child: any, index: number) => { - if (child?.type === "table_row") { - const rowData = child.table_row; - const isHeader = - index === 0 && tableData?.has_column_header; +
+
+
+ + {block.children?.map((child: any, index: number) => { + if (child?.type === "table_row") { + const rowData = child.table_row; + const isHeader = index === 0 && tableData?.has_column_header; - return ( - - {rowData?.cells?.map( - (cell: any, cellIndex: number) => { - const CellTag = isHeader ? "th" : "td"; - return ( - -
-
- -
-
-
- ); - } - )} - - ); - } - return null; - })} - -
-
-
+ return ( + + {rowData?.cells?.map((cell: any, cellIndex: number) => { + const CellTag = isHeader ? "th" : "td"; + return ( + +
+
+ +
+
+
+ ); + })} + + ); + } + return null; + })} + +
- - {/* Render other children blocks recursively (non-table-row blocks) */} - {block.children && block.children.length > 0 && ( -
- {block.children - .filter((child: any) => child?.type !== "table_row") - .map((child: any, index: number) => ( - - ))} -
- )}
); }; diff --git a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx index 4f0b7f8..efffbd0 100644 --- a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx @@ -27,54 +27,11 @@ export const ToDoBlockRenderer: React.FC = ({ className={`notion-selectable notion-to_do-block ${className || ""}`.trim()} data-block-id={block.id} > -
-
-
- - -
-
-
-
-
- -
-
-
+
+ +
+
+
{/* Render children blocks recursively */} diff --git a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx index 6d1c277..9b99c07 100644 --- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx @@ -32,61 +32,68 @@ export const ToggleBlockRenderer: React.FC = ({ className={`notion-selectable notion-toggle-block${className ? ` ${className}` : ""}`} data-block-id={block.id} > -
-
-
{ - if (e.key === "Enter" || e.key === " ") { - e.preventDefault(); - handleToggle(); - } +
{ + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleToggle(); + } + }} + style={{ + display: "flex", + alignItems: "center", + gap: 4, + cursor: "pointer", + }} + > +
+
+ +
-
-
-
- -
-
+ +
+
{/* Render children blocks recursively when toggle is open */} {isOpen && block.children && block.children.length > 0 && (
- {block.children.map((child: any, index: number) => ( - - ))} +
+ {block.children.map((child: any, index: number) => ( + + ))} +
)}
diff --git a/typescript/src/renderer/styles/base.css b/typescript/src/renderer/styles/base.css index 1a5c991..9d642dd 100644 --- a/typescript/src/renderer/styles/base.css +++ b/typescript/src/renderer/styles/base.css @@ -1,10 +1,12 @@ /* Base Layout and Page Styles */ +.json-doc-renderer { + max-width: inherit; +} .json-doc-page { max-width: var(--jsondoc-page-max-width); + max-width: inherit; margin: 0 auto; - /* padding: var(--jsondoc-page-padding-desktop) - var(--jsondoc-page-padding-desktop) var(--jsondoc-page-bottom-padding); */ color: var(--jsondoc-text-primary); font-family: var(--jsondoc-font-family-sans); } @@ -19,17 +21,13 @@ font-size: var(--jsondoc-font-size-page-title); line-height: var(--jsondoc-line-height-normal); font-weight: var(--jsondoc-font-weight-bold); - margin: 0 0 var(--jsondoc-spacing-xs); + margin: 0px 0px var(--jsondoc-spacing-lg) 0px; padding: var(--jsondoc-spacing-sm) 0px; } -.json-doc-page-content { - margin-top: var(--jsondoc-spacing-lg); -} - /* Base Block Styles */ .notion-selectable { - position: relative; + /* position: relative; */ margin: 0; padding: var(--jsondoc-spacing-sm) 0px; } diff --git a/typescript/src/renderer/styles/blocks.css b/typescript/src/renderer/styles/blocks.css index a90da43..c19baf7 100644 --- a/typescript/src/renderer/styles/blocks.css +++ b/typescript/src/renderer/styles/blocks.css @@ -36,7 +36,7 @@ /* Quote Block */ .notion-quote-block { - padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs); + padding: var(--jsondoc-spacing-md) var(--jsondoc-spacing-xs); } .notion-quote-block blockquote { @@ -60,9 +60,10 @@ /* To-do Block */ .notion-to_do-block { display: flex; - align-items: flex-start; - padding: 1px var(--jsondoc-spacing-xs); + align-items: center; + padding: 3px var(--jsondoc-spacing-xs); margin: 0; + gap: 8px; } .notion-to_do-block .checkboxSquare, @@ -76,6 +77,10 @@ color: var(--jsondoc-accent-checkbox); } +.notion-to_do-block .checked { + text-decoration: line-through; +} + .pseudoHover.pseudoActive { position: relative; display: flex; @@ -85,15 +90,13 @@ /* Toggle Block */ .notion-toggle-block { - display: flex; - align-items: flex-start; padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs); } -.notion-toggle-block .arrowCaretDownFillSmall { +.notion-toggle-block svg.arrowCaretDownFillSmall { width: var(--jsondoc-icon-size); height: var(--jsondoc-icon-size); - color: var(--jsondoc-text-muted); + fill: var(--jsondoc-text-muted); } .notion-toggle-content { @@ -112,6 +115,15 @@ flex: 1; } +.notion-toggle-block div[role="button"] { + display: flex; + justify-content: center; + align-items: center; + padding: 4px; +} +.notion-toggle-block div[role="button"]:hover { + background-color: var(--jsondoc-bg); +} /* Equation Block */ .notion-equation-block { padding: var(--jsondoc-spacing-sm) var(--jsondoc-spacing-xs); @@ -121,7 +133,6 @@ .notion-equation-display { text-align: center; padding: var(--jsondoc-spacing-lg); - background: var(--jsondoc-bg-code); border-radius: var(--jsondoc-radius-sm); } diff --git a/typescript/src/renderer/styles/index.css b/typescript/src/renderer/styles/index.css index a3aa8d0..8772d4e 100644 --- a/typescript/src/renderer/styles/index.css +++ b/typescript/src/renderer/styles/index.css @@ -1,5 +1,8 @@ /* JSON-DOC Renderer Styles */ +/* Import KaTeX styles for equations */ +@import "katex/dist/katex.min.css"; + /* Import design tokens first */ @import "./variables.css"; diff --git a/typescript/src/renderer/styles/layout.css b/typescript/src/renderer/styles/layout.css index 6d391ba..d0575bd 100644 --- a/typescript/src/renderer/styles/layout.css +++ b/typescript/src/renderer/styles/layout.css @@ -3,21 +3,15 @@ /* Page Delimiter */ .jsondoc-page-delimiter { margin: var(--jsondoc-spacing-xl) 0; - margin-bottom: var(--jsondoc-spacing-3xl); - position: relative; + margin-bottom: var(--jsondoc-spacing-xl); display: flex; - align-items: center; - justify-content: center; + flex-direction: column; } .jsondoc-page-delimiter-line { - position: absolute; - top: 50%; - left: 0; - right: 0; + width: 100%; height: 1px; background: var(--jsondoc-border-light); - z-index: var(--jsondoc-z-base); } .jsondoc-page-number { @@ -27,9 +21,7 @@ font-size: var(--jsondoc-font-size-caption); font-weight: var(--jsondoc-font-weight-normal); border-radius: var(--jsondoc-radius-sm); - position: relative; - z-index: var(--jsondoc-z-elevated); - display: inline-block; + width: fit-content; } /* Dark theme support for page delimiter */ diff --git a/typescript/src/renderer/styles/lists.css b/typescript/src/renderer/styles/lists.css index e4797e9..e1ca4b7 100644 --- a/typescript/src/renderer/styles/lists.css +++ b/typescript/src/renderer/styles/lists.css @@ -6,6 +6,7 @@ line-height: var(--jsondoc-line-height-very-loose); list-style-type: none; display: flex; + margin-bottom: 2px; } /* @@ -85,9 +86,10 @@ padding: 0px; text-indent: 0px; font-size: var(--jsondoc-font-size-h2); - margin-right: var(--jsondoc-spacing-sm); line-height: var(--jsondoc-line-height-tight); - margin-left: 1em; + margin-left: 8px; + margin-right: 10px; + margin-bottom: 4px; } /* @@ -103,8 +105,9 @@ content: counter(list-number) ". "; font-size: var(--jsondoc-font-size-body); margin-right: var(--jsondoc-spacing-sm); - min-width: 2em; text-align: right; + margin-left: 8px; + margin-right: 10px; } .notion-checkbox { diff --git a/typescript/src/renderer/styles/media.css b/typescript/src/renderer/styles/media.css index e4c5a6a..387311f 100644 --- a/typescript/src/renderer/styles/media.css +++ b/typescript/src/renderer/styles/media.css @@ -161,18 +161,45 @@ } button.caption-toggle-btn { - background: none; - border: none; - color: var(--jsondoc-text-muted); + background: rgba(55, 53, 47, 0.08); + border: 1px solid rgba(55, 53, 47, 0.16); + border-radius: 6px; + color: var(--jsondoc-text-secondary); cursor: pointer; - font-size: 0.875rem; - margin-top: 4px; - padding: 2px 4px; - text-decoration: underline; - transition: color 0.2s ease; + font-size: 0.75rem; + font-weight: 500; + margin-top: 8px; + padding: 6px 10px; + transition: all 0.15s ease; margin-left: auto; + display: inline-flex; + align-items: center; + gap: 4px; + text-decoration: none; + outline: none; } .caption-toggle-btn:hover { - color: var(--jsondoc-text-muted); + background: rgba(55, 53, 47, 0.12); + border-color: rgba(55, 53, 47, 0.24); + color: var(--jsondoc-text-primary); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.caption-toggle-btn:active { + transform: translateY(0); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.caption-toggle-btn .btn-text { + line-height: 1; +} + +.caption-toggle-btn .btn-icon { + /* transition: transform 0.4s ease; */ + flex-shrink: 0; +} + +.caption-toggle-btn .btn-icon.rotated { + transform: rotate(180deg); } diff --git a/typescript/src/renderer/styles/table.css b/typescript/src/renderer/styles/table.css index 099512a..3c56b6c 100644 --- a/typescript/src/renderer/styles/table.css +++ b/typescript/src/renderer/styles/table.css @@ -7,7 +7,6 @@ .notion-scroller.horizontal { overflow-x: auto; - overflow-y: hidden; width: 100%; } @@ -21,25 +20,28 @@ border-collapse: collapse; border-spacing: 0; table-layout: auto; - min-width: 600px; + min-width: max-content; } .notion-table-row th, .notion-table-row td { - border: 1px solid var(--jsondoc-border-medium); + border: 1px solid var(--jsondoc-border-light); padding: 8px 12px; vertical-align: top; - white-space: nowrap; - min-width: 120px; + white-space: normal; + min-width: 80px; + max-width: 200px; + word-wrap: break-word; + overflow-wrap: break-word; } .notion-table-row th { - background-color: var(--jsondoc-bg-code); font-weight: var(--jsondoc-font-weight-semibold); + text-align: left; } .notion-table-cell-text { - overflow: hidden; - text-overflow: ellipsis; - max-width: 300px; + word-wrap: break-word; + overflow-wrap: break-word; + white-space: normal; } diff --git a/typescript/src/renderer/styles/typography.css b/typescript/src/renderer/styles/typography.css index 9622f00..4eddb25 100644 --- a/typescript/src/renderer/styles/typography.css +++ b/typescript/src/renderer/styles/typography.css @@ -1,3 +1,8 @@ +.notion-list-content { + display: flex; + align-items: center; +} + /* Heading Blocks */ .notion-header-block, .notion-sub_header-block { @@ -14,6 +19,7 @@ margin: 0; font-weight: var(--jsondoc-font-weight-semibold); line-height: var(--jsondoc-line-height-relaxed); + margin-top: 32px; } .notion-sub_header-block h3 { @@ -21,6 +27,7 @@ margin: 0; font-weight: var(--jsondoc-font-weight-semibold); line-height: var(--jsondoc-line-height-relaxed); + margin-top: 22px; } .notion-sub_header-block h4 { @@ -28,6 +35,7 @@ margin: 0; font-weight: var(--jsondoc-font-weight-semibold); line-height: var(--jsondoc-line-height-relaxed); + margin-top: 16px; } .notion-link a { @@ -39,8 +47,9 @@ transition: text-decoration-color var(--jsondoc-transition-fast); } -.notion-text-block div { +.notion-text-block { color: var(--jsondoc-text-primary); + line-height: var(--jsondoc-line-height-very-loose); } .notion-link:hover { @@ -50,8 +59,6 @@ .notion-equation { background: var(--jsondoc-bg-inline-code); border-radius: var(--jsondoc-radius-sm); - padding: 0.2em 0.4em; - font-family: var(--jsondoc-font-family-serif); } /* Text Colors */ diff --git a/typescript/src/renderer/styles/variables.css b/typescript/src/renderer/styles/variables.css index 1fecad8..33137d9 100644 --- a/typescript/src/renderer/styles/variables.css +++ b/typescript/src/renderer/styles/variables.css @@ -11,9 +11,9 @@ --jsondoc-bg-code: rgb(247, 246, 243); --jsondoc-bg-inline-code: rgba(135, 131, 120, 0.15); --jsondoc-bg-unsupported: rgba(255, 0, 0, 0.1); - - /* Text Colors */ - --jsondoc-color-gray: rgba(120, 119, 116, 1); + --jsondoc-bg: rgba(55, 53, 47, 0.45); + --jsondoc-foreground: #37352f /* Text Colors */ + --jsondoc-color-gray: rgba(120, 119, 116, 1); --jsondoc-color-brown: rgba(159, 107, 83, 1); --jsondoc-color-orange: rgba(217, 115, 13, 1); --jsondoc-color-yellow: rgba(203, 145, 47, 1); @@ -109,14 +109,18 @@ --jsondoc-border-medium: rgb(233, 233, 231); --jsondoc-bg-code: rgb(247, 246, 243); --jsondoc-bg-inline-code: rgba(135, 131, 120, 0.15); + --jsondoc-bg: rgba(255, 255, 255, 0.8); + --jsondoc-foreground: #37352f; } .jsondoc-theme-dark { - --jsondoc-text-primary: #ffffff; + --jsondoc-text-primary: rgba(255, 255, 255, 0.81); --jsondoc-text-secondary: rgba(255, 255, 255, 0.65); --jsondoc-text-muted: rgba(255, 255, 255, 0.45); --jsondoc-border-light: rgba(255, 255, 255, 0.16); --jsondoc-border-medium: rgba(255, 255, 255, 0.2); --jsondoc-bg-code: rgba(255, 255, 255, 0.05); --jsondoc-bg-inline-code: rgba(255, 255, 255, 0.1); + --jsondoc-bg: rgba(55, 53, 47, 0.45); + --jsondoc-foreground: #37352f; } diff --git a/typescript/tsup.config.ts b/typescript/tsup.config.ts index 5788121..13b40b6 100644 --- a/typescript/tsup.config.ts +++ b/typescript/tsup.config.ts @@ -5,7 +5,7 @@ export default defineConfig({ format: ["cjs", "esm"], dts: true, splitting: false, - sourcemap: true, + // sourcemap: true, clean: true, external: ["react", "react-dom"], esbuildOptions(options) {