From 510e75528ab15cfcde06556b2e7dbfe5dd8ff489 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 15:20:14 +0300 Subject: [PATCH 01/10] mirrored block spcing of notion polished styles equation and table wip --- .../vite_basic/public/spacing_test.json | 924 ++++++++++++++++++ typescript/examples/vite_basic/src/App.tsx | 84 +- typescript/src/index.ts | 7 +- .../blocks/ColumnListBlockRenderer.tsx | 2 +- .../blocks/ListItemBlockRenderer.tsx | 2 +- .../components/blocks/QuoteBlockRenderer.tsx | 6 +- .../components/blocks/ToDoBlockRenderer.tsx | 53 +- .../components/blocks/ToggleBlockRenderer.tsx | 115 ++- typescript/src/renderer/styles/base.css | 4 - typescript/src/renderer/styles/blocks.css | 13 +- typescript/src/renderer/styles/lists.css | 8 +- typescript/src/renderer/styles/typography.css | 8 + 12 files changed, 1069 insertions(+), 157 deletions(-) create mode 100644 typescript/examples/vite_basic/public/spacing_test.json 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..6b1365b --- /dev/null +++ b/typescript/examples/vite_basic/public/spacing_test.json @@ -0,0 +1,924 @@ +{ + "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_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 have proper spacing above and below." + }, + "annotations": {}, + "plain_text": "This is a sample image with a caption. Image blocks should have proper spacing above and below." + } + ] + } + }, + { + "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..8668689 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -9,7 +9,7 @@ const App = () => { 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) { @@ -55,46 +55,60 @@ const App = () => { return (
-
-

JSON-DOC Renderer Development

+ {/* Floating Dev Mode Button */} + -
- + />
- - { - return ; - }, - }} - />
); 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/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/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/ToDoBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx index 4f0b7f8..e66fa36 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..4bf1518 100644 --- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx @@ -32,61 +32,80 @@ 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(); - } - }} - style={{ cursor: "pointer" }} - > - -
-
-
-
-
- -
-
+
{ + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleToggle(); + } + }} + style={{ cursor: "pointer", display: "flex", alignItems: "center" }} + > + {/* */} + + +
+
{/* 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..dd82899 100644 --- a/typescript/src/renderer/styles/base.css +++ b/typescript/src/renderer/styles/base.css @@ -23,10 +23,6 @@ padding: var(--jsondoc-spacing-sm) 0px; } -.json-doc-page-content { - margin-top: var(--jsondoc-spacing-lg); -} - /* Base Block Styles */ .notion-selectable { position: relative; diff --git a/typescript/src/renderer/styles/blocks.css b/typescript/src/renderer/styles/blocks.css index a90da43..4937ae8 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, @@ -85,15 +86,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 { diff --git a/typescript/src/renderer/styles/lists.css b/typescript/src/renderer/styles/lists.css index e4797e9..38e62b9 100644 --- a/typescript/src/renderer/styles/lists.css +++ b/typescript/src/renderer/styles/lists.css @@ -85,9 +85,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: 12px; + margin-right: 10px; + margin-bottom: 4px; } /* @@ -103,8 +104,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: 12px; + margin-right: 10px; } .notion-checkbox { diff --git a/typescript/src/renderer/styles/typography.css b/typescript/src/renderer/styles/typography.css index 9622f00..7f0aa8a 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 { From f8e2404c65d4ec1a16ca688d696e3477cf3fd25a Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 15:25:01 +0300 Subject: [PATCH 02/10] add size check --- .github/workflows/preview.yml | 30 +++++++++- typescript/package-lock.json | 108 +++++++++++++++++++++++++++++++++- typescript/package.json | 30 ++++++++-- 3 files changed, 160 insertions(+), 8 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 02a80f8..423292d 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -40,7 +40,35 @@ jobs: run: | npm pack - + - name: Check package size and create comment + working-directory: ./typescript + run: | + # Run size-limit to get detailed size analysis + SIZE_OUTPUT=$(npm run size 2>&1 || echo "Size check failed") + + # Get package file info + PACKAGE_FILE=$(ls *.tgz | head -1) + PACKAGE_SIZE=$(stat -c%s "$PACKAGE_FILE" 2>/dev/null || stat -f%z "$PACKAGE_FILE") + PACKAGE_SIZE_KB=$((PACKAGE_SIZE / 1024)) + + # Create comment body + cat > /tmp/size_comment.md << EOF + ## 📦 Package Size Report + + **Package:** \`$PACKAGE_FILE\` (${PACKAGE_SIZE_KB} KB compressed) + + ### Size Limit Analysis: + \`\`\` + $SIZE_OUTPUT + \`\`\` + + Preview package is ready for testing! 🚀 + EOF + + # Post comment to PR + gh pr comment --body-file /tmp/size_comment.md + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: List files in typescript dir working-directory: ./typescript 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..761b876 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": "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" + } + ] } From ada149b291562a650b1cc9a49814052e65fbffe7 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 18:44:02 +0300 Subject: [PATCH 03/10] add katex for equation fix image caption --- .../blocks/EquationBlockRenderer.tsx | 29 +++++++-- .../components/blocks/ToggleBlockRenderer.tsx | 62 ++++++++----------- typescript/src/renderer/styles/blocks.css | 10 ++- typescript/src/renderer/styles/index.css | 3 + typescript/src/renderer/styles/variables.css | 10 ++- typescript/tsup.config.ts | 2 +- 6 files changed, 70 insertions(+), 46 deletions(-) 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/ToggleBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx index 4bf1518..90ac5ee 100644 --- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx @@ -35,52 +35,40 @@ export const ToggleBlockRenderer: React.FC = ({
{ if (e.key === "Enter" || e.key === " ") { e.preventDefault(); handleToggle(); } }} - style={{ cursor: "pointer", display: "flex", alignItems: "center" }} + style={{ + display: "flex", + alignItems: "center", + gap: 4, + cursor: "pointer", + }} > - {/* */} +
+ +
-
diff --git a/typescript/src/renderer/styles/blocks.css b/typescript/src/renderer/styles/blocks.css index 4937ae8..c23b17d 100644 --- a/typescript/src/renderer/styles/blocks.css +++ b/typescript/src/renderer/styles/blocks.css @@ -111,6 +111,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); @@ -120,7 +129,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/variables.css b/typescript/src/renderer/styles/variables.css index 1fecad8..fa7bf20 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,6 +109,8 @@ --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 { @@ -119,4 +121,6 @@ --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) { From b2a8f5c351e2fc7958914c55512fc6375160007d Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 18:56:49 +0300 Subject: [PATCH 04/10] checkpoint --- .../components/blocks/TableBlockRenderer.tsx | 98 +++++++------------ typescript/src/renderer/styles/table.css | 16 +-- 2 files changed, 45 insertions(+), 69 deletions(-) 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/styles/table.css b/typescript/src/renderer/styles/table.css index 099512a..c8395bb 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,7 +20,7 @@ border-collapse: collapse; border-spacing: 0; table-layout: auto; - min-width: 600px; + min-width: max-content; } .notion-table-row th, @@ -29,8 +28,11 @@ border: 1px solid var(--jsondoc-border-medium); 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 { @@ -39,7 +41,7 @@ } .notion-table-cell-text { - overflow: hidden; - text-overflow: ellipsis; - max-width: 300px; + word-wrap: break-word; + overflow-wrap: break-word; + white-space: normal; } From 16e7927aa4d5bc6bc1546b3455353ba6e89f8a7c Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 20:14:33 +0300 Subject: [PATCH 05/10] checkpoint --- .github/workflows/preview.yml | 30 ------------------------------ typescript/package.json | 2 +- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 423292d..c84258b 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -40,36 +40,6 @@ jobs: run: | npm pack - - name: Check package size and create comment - working-directory: ./typescript - run: | - # Run size-limit to get detailed size analysis - SIZE_OUTPUT=$(npm run size 2>&1 || echo "Size check failed") - - # Get package file info - PACKAGE_FILE=$(ls *.tgz | head -1) - PACKAGE_SIZE=$(stat -c%s "$PACKAGE_FILE" 2>/dev/null || stat -f%z "$PACKAGE_FILE") - PACKAGE_SIZE_KB=$((PACKAGE_SIZE / 1024)) - - # Create comment body - cat > /tmp/size_comment.md << EOF - ## 📦 Package Size Report - - **Package:** \`$PACKAGE_FILE\` (${PACKAGE_SIZE_KB} KB compressed) - - ### Size Limit Analysis: - \`\`\` - $SIZE_OUTPUT - \`\`\` - - Preview package is ready for testing! 🚀 - EOF - - # Post comment to PR - gh pr comment --body-file /tmp/size_comment.md - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: List files in typescript dir working-directory: ./typescript run: | diff --git a/typescript/package.json b/typescript/package.json index 761b876..f156384 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -21,7 +21,7 @@ "lint": "eslint src --ext .ts,.tsx", "lint:fix": "eslint src --ext .ts,.tsx --fix", "prepare": "husky", - "size": "size-limit" + "size": "npm run build && size-limit" }, "keywords": [ "json", From e8a17f5b2b097c75c23cf875c48a361095bcfd91 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 20:25:13 +0300 Subject: [PATCH 06/10] image caption button --- typescript/examples/vite_basic/src/App.tsx | 4 +- .../components/blocks/ImageBlockRenderer.tsx | 38 +++++++++++++--- typescript/src/renderer/styles/media.css | 45 +++++++++++++++---- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 8668689..40c7a3e 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -88,12 +88,12 @@ const App = () => {
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/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); } From 200a0138bea4f9e97241b1c6b64c308aac606f11 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 21:15:21 +0300 Subject: [PATCH 07/10] checkpoint --- typescript/examples/vite_basic/src/App.tsx | 72 +++++++++++++++------ typescript/src/renderer/JsonDocRenderer.tsx | 2 - typescript/src/renderer/styles/base.css | 2 +- typescript/src/renderer/styles/table.css | 4 +- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 40c7a3e..0db5bde 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -5,6 +5,7 @@ import { useState, useEffect } from "react"; const App = () => { const [testPage, setTestPage] = useState(null); const [devMode, setDevMode] = useState(false); + const [theme, setTheme] = useState<"light" | "dark">("dark"); useEffect(() => { const loadData = async () => { @@ -24,22 +25,26 @@ const App = () => { } // 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, - }, + 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, @@ -55,7 +60,7 @@ const App = () => { return (
{/* Floating Dev Mode Button */} @@ -85,21 +90,50 @@ const App = () => { {devMode ? "Disable" : "Enable"} Dev Mode + {/* Floating Theme Toggle Button */} + +
{ - console.log("page: ", page); - // Use the modular hooks for highlight management const { highlightCount, currentActiveIndex, navigateToHighlight } = useHighlights({ diff --git a/typescript/src/renderer/styles/base.css b/typescript/src/renderer/styles/base.css index dd82899..ecb161f 100644 --- a/typescript/src/renderer/styles/base.css +++ b/typescript/src/renderer/styles/base.css @@ -19,7 +19,7 @@ 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; } diff --git a/typescript/src/renderer/styles/table.css b/typescript/src/renderer/styles/table.css index c8395bb..3c56b6c 100644 --- a/typescript/src/renderer/styles/table.css +++ b/typescript/src/renderer/styles/table.css @@ -25,7 +25,7 @@ .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: normal; @@ -36,8 +36,8 @@ } .notion-table-row th { - background-color: var(--jsondoc-bg-code); font-weight: var(--jsondoc-font-weight-semibold); + text-align: left; } .notion-table-cell-text { From 702ee20fe49b9d206fd868d4fbfe276d549ca480 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Thu, 19 Jun 2025 21:39:06 +0300 Subject: [PATCH 08/10] checkpoint --- .../vite_basic/public/spacing_test.json | 136 ++++++++++++++++- typescript/examples/vite_basic/src/App.tsx | 142 ++++++++++-------- .../components/blocks/ToDoBlockRenderer.tsx | 2 +- .../components/blocks/ToggleBlockRenderer.tsx | 4 +- typescript/src/renderer/styles/blocks.css | 4 + typescript/src/renderer/styles/lists.css | 5 +- 6 files changed, 226 insertions(+), 67 deletions(-) diff --git a/typescript/examples/vite_basic/public/spacing_test.json b/typescript/examples/vite_basic/public/spacing_test.json index 6b1365b..9f3247c 100644 --- a/typescript/examples/vite_basic/public/spacing_test.json +++ b/typescript/examples/vite_basic/public/spacing_test.json @@ -718,6 +718,138 @@ ] ] } + }, + { + "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" + } + ] + ] + } } ] }, @@ -890,10 +1022,10 @@ { "type": "text", "text": { - "content": "This is a sample image with a caption. Image blocks should have proper spacing above and below." + "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 have proper spacing above and below." + "plain_text": "This is a sample image with a caption. Image blocks should" } ] } diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 0db5bde..6ee1db0 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -2,6 +2,66 @@ import { JsonDocRenderer, PageDelimiter } from "@textcortex/jsondoc"; import "@textcortex/jsondoc/dist/index.css"; import { useState, useEffect } 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 ( + + ); +}; + const App = () => { const [testPage, setTestPage] = useState(null); const [devMode, setDevMode] = useState(false); @@ -64,65 +124,29 @@ const App = () => { }} > {/* Floating Dev Mode Button */} - + {/* Floating Theme Toggle Button */} - +
{ paddingTop: 160, }} > -
- { - return ; - }, - }} - /> -
+ { + return ; + }, + }} + />
); diff --git a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx index e66fa36..efffbd0 100644 --- a/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToDoBlockRenderer.tsx @@ -30,7 +30,7 @@ export const ToDoBlockRenderer: React.FC = ({
-
+
diff --git a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx index 90ac5ee..9b99c07 100644 --- a/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx +++ b/typescript/src/renderer/components/blocks/ToggleBlockRenderer.tsx @@ -56,8 +56,8 @@ export const ToggleBlockRenderer: React.FC = ({ viewBox="0 0 16 16" className="arrowCaretDownFillSmall" style={{ - width: "1.2em", - height: "1.2em", + width: "14px", + height: "14px", display: "block", flexShrink: 0, transition: "transform 200ms ease-out", diff --git a/typescript/src/renderer/styles/blocks.css b/typescript/src/renderer/styles/blocks.css index c23b17d..c19baf7 100644 --- a/typescript/src/renderer/styles/blocks.css +++ b/typescript/src/renderer/styles/blocks.css @@ -77,6 +77,10 @@ color: var(--jsondoc-accent-checkbox); } +.notion-to_do-block .checked { + text-decoration: line-through; +} + .pseudoHover.pseudoActive { position: relative; display: flex; diff --git a/typescript/src/renderer/styles/lists.css b/typescript/src/renderer/styles/lists.css index 38e62b9..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; } /* @@ -86,7 +87,7 @@ text-indent: 0px; font-size: var(--jsondoc-font-size-h2); line-height: var(--jsondoc-line-height-tight); - margin-left: 12px; + margin-left: 8px; margin-right: 10px; margin-bottom: 4px; } @@ -105,7 +106,7 @@ font-size: var(--jsondoc-font-size-body); margin-right: var(--jsondoc-spacing-sm); text-align: right; - margin-left: 12px; + margin-left: 8px; margin-right: 10px; } From 9bb5ba8b1937599d99b2272a8fcb9cbb24eb907b Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Fri, 20 Jun 2025 00:06:28 +0300 Subject: [PATCH 09/10] fix some annoying css issues --- typescript/examples/vite_basic/src/App.tsx | 155 +++++------------- .../vite_basic/src/components/DevPanel.tsx | 42 +++++ .../src/components/FloatingButton.tsx | 63 +++++++ .../src/renderer/components/PageDelimiter.tsx | 5 +- typescript/src/renderer/styles/base.css | 6 +- typescript/src/renderer/styles/layout.css | 16 +- 6 files changed, 158 insertions(+), 129 deletions(-) create mode 100644 typescript/examples/vite_basic/src/components/DevPanel.tsx create mode 100644 typescript/examples/vite_basic/src/components/FloatingButton.tsx diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 6ee1db0..0806584 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -1,66 +1,40 @@ import { JsonDocRenderer, PageDelimiter } from "@textcortex/jsondoc"; import "@textcortex/jsondoc/dist/index.css"; import { useState, useEffect } from "react"; +import DevPanel from "./components/DevPanel"; -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 ( - - ); -}; +// 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); @@ -70,7 +44,7 @@ const App = () => { useEffect(() => { const loadData = async () => { try { - const response = await fetch("/spacing_test.json"); + const response = await fetch("/test_document.json"); const data = await response.json(); setTestPage(data); } catch (error) { @@ -84,74 +58,29 @@ const App = () => { return
Loading...
; } - // 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, - // }, - ]; - 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 - +
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/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/styles/base.css b/typescript/src/renderer/styles/base.css index ecb161f..ec14c6b 100644 --- a/typescript/src/renderer/styles/base.css +++ b/typescript/src/renderer/styles/base.css @@ -1,7 +1,11 @@ /* 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); */ @@ -25,7 +29,7 @@ /* Base Block Styles */ .notion-selectable { - position: relative; + /* position: relative; */ margin: 0; padding: var(--jsondoc-spacing-sm) 0px; } 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 */ From afca71ea4f714f999fd843a3a1c7c04a92228742 Mon Sep 17 00:00:00 2001 From: Abreham Gezahegn Date: Fri, 20 Jun 2025 00:35:43 +0300 Subject: [PATCH 10/10] checkpoint --- typescript/examples/vite_basic/src/App.tsx | 4 ++-- typescript/src/renderer/styles/base.css | 2 -- typescript/src/renderer/styles/typography.css | 5 ++--- typescript/src/renderer/styles/variables.css | 2 +- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/typescript/examples/vite_basic/src/App.tsx b/typescript/examples/vite_basic/src/App.tsx index 0806584..9c994d6 100644 --- a/typescript/examples/vite_basic/src/App.tsx +++ b/typescript/examples/vite_basic/src/App.tsx @@ -44,7 +44,7 @@ const App = () => { 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) { @@ -80,7 +80,7 @@ const App = () => { display: "flex", justifyContent: "center", paddingTop: 160, - background: "rgba(0,0,0,0.3)", + // background: "rgba(0,0,0,0.3)", }} >