Skip to content

Commit 4822048

Browse files
make block container div open for modification + make blocks overriable
1 parent 38dc6cb commit 4822048

23 files changed

+4285
-57
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
title: "Component Override Example for JSON-DOC TypeScript"
3+
author: "Abreham <abreham@textcortex.com> and Claude Code"
4+
date: "2025-01-05"
5+
---
6+
7+
# Component Override Example
8+
9+
This demonstrates how users can now override specific block components in the JSON-DOC renderer.
10+
11+
## Usage Example
12+
13+
```typescript
14+
import {
15+
JsonDocRenderer,
16+
ParagraphBlockRenderer,
17+
HeadingBlockRenderer
18+
} from 'jsondoc/renderer';
19+
20+
// Example: Override paragraph with custom className
21+
const CustomParagraph = (props) => (
22+
<ParagraphBlockRenderer
23+
{...props}
24+
className="my-custom-paragraph-style"
25+
/>
26+
);
27+
28+
// Example: Override heading with wrapper div and custom styling
29+
const CustomHeading = (props) => (
30+
<div className="my-heading-wrapper">
31+
<HeadingBlockRenderer
32+
{...props}
33+
className="my-custom-heading"
34+
style={{ color: 'blue' }}
35+
/>
36+
</div>
37+
);
38+
39+
// Usage
40+
<JsonDocRenderer
41+
page={jsonDocPage}
42+
components={{
43+
paragraph: CustomParagraph,
44+
heading_1: CustomHeading,
45+
heading_2: CustomHeading,
46+
heading_3: CustomHeading
47+
}}
48+
/>
49+
```
50+
51+
## What This Enables
52+
53+
1. **Custom Styling**: Users can add their own CSS classes and styles
54+
2. **Wrapper Components**: Add additional markup around blocks
55+
3. **Custom Logic**: Add click handlers, analytics, etc.
56+
4. **Design System Integration**: Easy integration with Tailwind, styled-components, etc.
57+
5. **Progressive Enhancement**: Override only what you need, keep defaults for the rest
58+
59+
## Example with Tailwind CSS
60+
61+
```typescript
62+
const TailwindParagraph = (props) => (
63+
<ParagraphBlockRenderer
64+
{...props}
65+
className="prose prose-lg text-gray-700 leading-relaxed"
66+
/>
67+
);
68+
69+
const TailwindHeading = (props) => (
70+
<HeadingBlockRenderer
71+
{...props}
72+
className="font-bold text-gray-900 border-b border-gray-200 pb-2"
73+
/>
74+
);
75+
```
76+
77+
## Example with Styled Components
78+
79+
```typescript
80+
const StyledParagraph = styled(ParagraphBlockRenderer)`
81+
font-family: 'Inter', sans-serif;
82+
line-height: 1.6;
83+
color: ${props => props.theme.colors.text};
84+
`;
85+
86+
const StyledHeading = styled(HeadingBlockRenderer)`
87+
font-family: 'Playfair Display', serif;
88+
color: ${props => props.theme.colors.primary};
89+
border-bottom: 2px solid ${props => props.theme.colors.accent};
90+
`;
91+
```
92+
93+
## Benefits of This Approach
94+
95+
- **Verbose but Explicit**: Clear what each override does
96+
- **Type Safe**: Full TypeScript support for component props
97+
- **React Standard**: Follows familiar React patterns
98+
- **Composable**: Can wrap, extend, or completely replace components
99+
- **Flexible**: Access to all HTML attributes via props spreading
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---
2+
title: "Complete Component Override System for JSON-DOC TypeScript"
3+
author: "Abreham <abreham@textcortex.com> and Claude Code"
4+
date: "2025-01-05"
5+
---
6+
7+
# Complete Component Override System
8+
9+
**Implementation Complete!** All block components now support the react-markdown style component override pattern.
10+
11+
## 🚀 Usage Examples
12+
13+
### Basic Component Overrides
14+
15+
```typescript
16+
import {
17+
JsonDocRenderer,
18+
ParagraphBlockRenderer,
19+
HeadingBlockRenderer,
20+
CodeBlockRenderer,
21+
QuoteBlockRenderer,
22+
type BlockComponents
23+
} from 'jsondoc/renderer';
24+
25+
// Custom paragraph with Tailwind styling
26+
const CustomParagraph = (props) => (
27+
<ParagraphBlockRenderer
28+
{...props}
29+
className="prose prose-lg text-gray-700 leading-relaxed my-4"
30+
/>
31+
);
32+
33+
// Custom heading with icon and custom styling
34+
const CustomHeading = (props) => (
35+
<div className="heading-wrapper">
36+
<span className="heading-icon">📝</span>
37+
<HeadingBlockRenderer
38+
{...props}
39+
className="font-bold text-blue-600 border-b-2 border-blue-200"
40+
onClick={() => console.log('Heading clicked:', props.block.id)}
41+
/>
42+
</div>
43+
);
44+
45+
// Custom code block with syntax highlighting
46+
const CustomCodeBlock = (props) => (
47+
<div className="code-wrapper">
48+
<div className="code-header">
49+
<span>💻 Code</span>
50+
<button onClick={() => navigator.clipboard.writeText(props.block.code?.rich_text?.[0]?.plain_text)}>
51+
Copy
52+
</button>
53+
</div>
54+
<CodeBlockRenderer
55+
{...props}
56+
className="bg-gray-900 text-green-400 rounded-lg p-4"
57+
/>
58+
</div>
59+
);
60+
61+
// Usage with multiple overrides
62+
<JsonDocRenderer
63+
page={jsonDocPage}
64+
components={{
65+
paragraph: CustomParagraph,
66+
heading_1: CustomHeading,
67+
heading_2: CustomHeading,
68+
heading_3: CustomHeading,
69+
code: CustomCodeBlock,
70+
quote: (props) => (
71+
<QuoteBlockRenderer
72+
{...props}
73+
className="border-l-4 border-blue-500 bg-blue-50 p-4 italic"
74+
/>
75+
)
76+
}}
77+
/>
78+
```
79+
80+
## 🎨 Design System Integration
81+
82+
### Tailwind CSS
83+
```typescript
84+
const tailwindComponents: BlockComponents = {
85+
paragraph: (props) => (
86+
<ParagraphBlockRenderer
87+
{...props}
88+
className="text-gray-800 leading-7 mb-4"
89+
/>
90+
),
91+
heading_1: (props) => (
92+
<HeadingBlockRenderer
93+
{...props}
94+
className="text-4xl font-bold text-gray-900 mb-6 border-b pb-2"
95+
/>
96+
),
97+
code: (props) => (
98+
<CodeBlockRenderer
99+
{...props}
100+
className="bg-gray-100 rounded-md p-4 font-mono text-sm overflow-x-auto"
101+
/>
102+
),
103+
quote: (props) => (
104+
<QuoteBlockRenderer
105+
{...props}
106+
className="border-l-4 border-indigo-500 pl-4 italic text-gray-600"
107+
/>
108+
),
109+
to_do: (props) => (
110+
<ToDoBlockRenderer
111+
{...props}
112+
className="flex items-start space-x-2 my-2 hover:bg-gray-50 p-2 rounded"
113+
/>
114+
)
115+
};
116+
```
117+
118+
### Styled Components
119+
```typescript
120+
import styled from 'styled-components';
121+
122+
const StyledParagraph = styled(ParagraphBlockRenderer)`
123+
font-family: 'Georgia', serif;
124+
line-height: 1.8;
125+
color: ${props => props.theme.colors.text};
126+
margin-bottom: 1.5rem;
127+
`;
128+
129+
const StyledHeading = styled(HeadingBlockRenderer)`
130+
font-family: 'Playfair Display', serif;
131+
color: ${props => props.theme.colors.primary};
132+
border-bottom: 2px solid ${props => props.theme.colors.accent};
133+
padding-bottom: 0.5rem;
134+
margin-bottom: 1rem;
135+
`;
136+
137+
const styledComponents: BlockComponents = {
138+
paragraph: StyledParagraph,
139+
heading_1: StyledHeading,
140+
heading_2: StyledHeading,
141+
heading_3: StyledHeading,
142+
};
143+
```
144+
145+
## 🔧 All Supported Block Types
146+
147+
Every block type supports component overrides:
148+
149+
```typescript
150+
type BlockComponents = {
151+
// Text blocks
152+
paragraph?: React.ComponentType<...>;
153+
heading_1?: React.ComponentType<...>;
154+
heading_2?: React.ComponentType<...>;
155+
heading_3?: React.ComponentType<...>;
156+
157+
// List blocks
158+
bulleted_list_item?: React.ComponentType<...>;
159+
numbered_list_item?: React.ComponentType<...>;
160+
unordered_list?: React.ComponentType<...>;
161+
ordered_list?: React.ComponentType<...>;
162+
163+
// Media blocks
164+
code?: React.ComponentType<...>;
165+
image?: React.ComponentType<...>;
166+
equation?: React.ComponentType<...>;
167+
168+
// Layout blocks
169+
table?: React.ComponentType<...>;
170+
column_list?: React.ComponentType<...>;
171+
172+
// Interactive blocks
173+
quote?: React.ComponentType<...>;
174+
divider?: React.ComponentType<...>;
175+
to_do?: React.ComponentType<...>;
176+
toggle?: React.ComponentType<...>;
177+
};
178+
```
179+
180+
## 🌟 Advanced Use Cases
181+
182+
### Analytics Integration
183+
```typescript
184+
const AnalyticsWrapper = ({ children, blockType, blockId }) => {
185+
const trackBlockView = () => {
186+
analytics.track('block_viewed', { blockType, blockId });
187+
};
188+
189+
useEffect(trackBlockView, []);
190+
191+
return <div onIntersectionObserver={trackBlockView}>{children}</div>;
192+
};
193+
194+
const analyticsComponents: BlockComponents = {
195+
heading_1: (props) => (
196+
<AnalyticsWrapper blockType="heading_1" blockId={props.block.id}>
197+
<HeadingBlockRenderer {...props} />
198+
</AnalyticsWrapper>
199+
),
200+
code: (props) => (
201+
<AnalyticsWrapper blockType="code" blockId={props.block.id}>
202+
<CodeBlockRenderer {...props} />
203+
</AnalyticsWrapper>
204+
)
205+
};
206+
```
207+
208+
### Dark Mode Support
209+
```typescript
210+
const DarkModeComponents: BlockComponents = {
211+
paragraph: (props) => (
212+
<ParagraphBlockRenderer
213+
{...props}
214+
className="dark:text-gray-200 text-gray-800"
215+
/>
216+
),
217+
code: (props) => (
218+
<CodeBlockRenderer
219+
{...props}
220+
className="dark:bg-gray-800 bg-gray-100 dark:text-green-400 text-gray-800"
221+
/>
222+
),
223+
quote: (props) => (
224+
<QuoteBlockRenderer
225+
{...props}
226+
className="dark:border-gray-600 border-gray-300 dark:bg-gray-800 bg-gray-50"
227+
/>
228+
)
229+
};
230+
```
231+
232+
## ✨ Features Accomplished
233+
234+
✅ **All block types support component overrides**
235+
✅ **Full React HTML attributes support** (className, style, onClick, etc.)
236+
✅ **TypeScript type safety** with full prop typing
237+
✅ **Recursive component propagation** - overrides apply to nested blocks
238+
✅ **Individual component exports** for maximum flexibility
239+
✅ **Zero breaking changes** - existing usage continues to work
240+
✅ **React-markdown compatibility** - familiar API patterns
241+
242+
## 🎯 Migration Path
243+
244+
**Existing users:** No changes needed - everything works as before
245+
246+
**New users wanting customization:**
247+
1. Import the components you want to override
248+
2. Create wrapper components with your styling
249+
3. Pass them via the `components` prop
250+
251+
**Advanced users:**
252+
- Mix and match individual components
253+
- Create design system integrations
254+
- Build interactive enhancements
255+
- Add analytics and tracking
256+
257+
The implementation provides maximum flexibility while maintaining simplicity and performance!

typescript/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
"scripts": {
99
"clean": "rm -rf dist",
1010
"build": "tsup",
11-
"dev": "tsup --watch",
12-
"dev:full": "concurrently \"npm run dev\" \"npm run lint:watch\" \"npm run type-check:watch\"",
11+
"dev": "concurrently \"tsup --watch\" \"npm run lint:watch\" \"npm run type-check:watch\"",
1312
"type-check:watch": "tsc --noEmit --watch --pretty",
1413
"lint:watch": "eslint src --ext .ts,.tsx --cache",
1514
"dev:example": "vite --config vite.dev.config.ts",

0 commit comments

Comments
 (0)