File size: 4,724 Bytes
03d0e97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env python3
"""
Example API Usage for Editable MarkdownLabel Component
Shows the recommended event handling pattern to avoid infinite loops.
"""

import gradio as gr
from gradio_markdownlabel import MarkdownLabel

def main():
    # Sample document with highlights
    document = {
        "markdown_content": """# Project Documentation

## Overview

This is an **editable document** that demonstrates the MarkdownLabel component's capabilities.

## Features

- Interactive editing with save/cancel workflow
- Position-based and term-based highlighting  
- Live preview during editing
- Manual save to prevent accidental changes

## Instructions

Click "Edit" to modify this content, then "Save" to apply changes.
""",
        "highlights": [
            {
                "term": "editable document", 
                "title": "Editable Document",
                "content": "Documents that can be modified by users through the interface.",
                "category": "feature",
                "color": "#e3f2fd"
            },
            {
                "position": [200, 220],  # "MarkdownLabel component"
                "title": "MarkdownLabel Component",
                "content": "The custom Gradio component for displaying markdown with interactive highlights.",
                "category": "technical",
                "color": "#f3e5f5"  
            }
        ]
    }

    # Event handlers - NO change handler to prevent loops
    def on_edit_start(data):
        """Called when user clicks Edit button"""
        print(f"πŸ“ User started editing document")
        # Could initialize editing session, backup content, etc.
        return gr.update()  # No changes to component
    
    def on_save(data):
        """Called when user clicks Save button"""
        print(f"πŸ’Ύ Document saved with {len(data['markdown_content'])} characters")
        # Here you could:
        # - Validate the content
        # - Save to database  
        # - Update version history
        # - Send notifications
        gr.Info("Document saved successfully!")
        return data  # Return the saved data
    
    def on_cancel(data):
        """Called when user clicks Cancel button"""
        print(f"❌ Edit cancelled")
        gr.Info("Changes discarded")
        return gr.update()  # No changes needed

    def on_highlight_select(selection_data):
        """Called when user clicks a highlight"""
        print(f"🎯 Highlight selected: {selection_data}")
        return gr.update()

    # Create the interface
    with gr.Blocks(title="MarkdownLabel API Example") as demo:
        gr.Markdown("# MarkdownLabel API Usage Example")
        gr.Markdown("Demonstrates proper event handling without infinite loops.")
        
        # The component
        editor = MarkdownLabel(
            value=document,
            interactive=True,           # Enable editing
            edit_mode="split",          # Split view: editor + preview
            show_preview=True,          # Show live preview
            show_side_panel=True,       # Show highlight details
            panel_width="350px",
            label="Interactive Document Editor"
        )
        
        # Event handlers - IMPORTANT: No .change() handler during editing!
        editor.edit(
            fn=on_edit_start,
            inputs=[editor]
            # No outputs = no component update
        )
        
        editor.submit(  # This is the "Save" button
            fn=on_save,
            inputs=[editor],
            outputs=[editor]  # Update component with saved data
        )
        
        editor.clear(  # This is the "Cancel" button  
            fn=on_cancel,
            inputs=[editor]
            # No outputs = revert handled internally
        )
        
        editor.select(  # Highlight selection
            fn=on_highlight_select,
            inputs=[editor]
        )
        
        # Status display
        gr.Markdown("""
        ### Event Flow:
        1. **Edit**: User clicks edit β†’ `on_edit_start()` called
        2. **Type**: User types β†’ Only visual preview updates (no events)
        3. **Save**: User clicks save β†’ `on_save()` called β†’ Changes applied  
        4. **Cancel**: User clicks cancel β†’ `on_cancel()` called β†’ Changes reverted
        
        ### Key Points:
        - ❌ **DON'T** use `.change()` handlers during editing (causes loops)
        - βœ… **DO** use `.submit()` for save actions 
        - βœ… **DO** use `.clear()` for cancel actions
        - βœ… **DO** use `.edit()` for edit start actions
        - βœ… **DO** use `.select()` for highlight interactions
        """)

    return demo

if __name__ == "__main__":
    demo = main()
    demo.launch()