Przeglądaj źródła

#439 introduce element_example

Falko Schindler 2 lat temu
rodzic
commit
6d3d00efad
3 zmienionych plików z 65 dodań i 28 usunięć
  1. 1 0
      website/example.py
  2. 26 26
      website/reference.py
  3. 38 2
      website/reference_tools.py

+ 1 - 0
website/example.py

@@ -51,6 +51,7 @@ def add_html_with_anchor_link(html: str, menu: Optional[ui.drawer]) -> str:
 
 class example:
 
+    # TODO: simplify API
     def __init__(self,
                  content: Union[Callable, type, str],
                  menu: Optional[ui.drawer] = None,

+ 26 - 26
website/reference.py

@@ -6,7 +6,7 @@ from nicegui.elements.markdown import prepare_content
 
 from . import more_reference
 from .example import add_html_with_anchor_link, bash_window, example, python_window
-from .reference_tools import heading, intro_example
+from .reference_tools import element_example, heading, intro_example
 
 CONSTANT_UUID = str(uuid.uuid4())
 
@@ -64,127 +64,127 @@ def create_full(menu: ui.element) -> None:
 
     heading('Basic Elements')
 
-    @example(ui.label, menu)
+    @element_example(ui.label)
     def label_example():
         ui.label('some label')
 
-    @example(ui.icon, menu)
+    @element_example(ui.icon)
     def icon_example():
         ui.icon('thumb_up')
 
-    @example(ui.avatar, menu)
+    @element_example(ui.avatar)
     def avatar_example():
         ui.avatar('favorite_border', text_color='grey-11', square=True)
         ui.avatar('img:https://nicegui.io/logo_square.png', color='blue-2')
 
-    @example(ui.link, menu)
+    @element_example(ui.link)
     def link_example():
         ui.link('NiceGUI on GitHub', 'https://github.com/zauberzeug/nicegui')
 
-    @example(ui.button, menu)
+    @element_example(ui.button)
     def button_example():
         ui.button('Click me!', on_click=lambda: ui.notify(f'You clicked me!'))
 
-    @example(ui.badge, menu)
+    @element_example(ui.badge)
     def badge_example():
         with ui.button('Click me!', on_click=lambda: badge.set_text(int(badge.text) + 1)):
             badge = ui.badge('0', color='red').props('floating')
 
-    @example(ui.toggle, menu)
+    @element_example(ui.toggle)
     def toggle_example():
         toggle1 = ui.toggle([1, 2, 3], value=1)
         toggle2 = ui.toggle({1: 'A', 2: 'B', 3: 'C'}).bind_value(toggle1, 'value')
 
-    @example(ui.radio, menu)
+    @element_example(ui.radio)
     def radio_example():
         radio1 = ui.radio([1, 2, 3], value=1).props('inline')
         radio2 = ui.radio({1: 'A', 2: 'B', 3: 'C'}).props('inline').bind_value(radio1, 'value')
 
-    @example(ui.select, menu)
+    @element_example(ui.select)
     def select_example():
         select1 = ui.select([1, 2, 3], value=1)
         select2 = ui.select({1: 'One', 2: 'Two', 3: 'Three'}).bind_value(select1, 'value')
 
-    @example(ui.checkbox, menu)
+    @element_example(ui.checkbox)
     def checkbox_example():
         checkbox = ui.checkbox('check me')
         ui.label('Check!').bind_visibility_from(checkbox, 'value')
 
-    @example(ui.switch, menu)
+    @element_example(ui.switch)
     def switch_example():
         switch = ui.switch('switch me')
         ui.label('Switch!').bind_visibility_from(switch, 'value')
 
-    @example(ui.slider, menu)
+    @element_example(ui.slider)
     def slider_example():
         slider = ui.slider(min=0, max=100, value=50)
         ui.label().bind_text_from(slider, 'value')
 
-    @example(ui.joystick, menu)
+    @element_example(ui.joystick)
     def joystick_example():
         ui.joystick(color='blue', size=50,
                     on_move=lambda e: coordinates.set_text(f"{e.x:.3f}, {e.y:.3f}"),
                     on_end=lambda _: coordinates.set_text('0, 0'))
         coordinates = ui.label('0, 0')
 
-    @example(ui.input, menu)
+    @element_example(ui.input)
     def input_example():
         ui.input(label='Text', placeholder='start typing',
                  on_change=lambda e: result.set_text('you typed: ' + e.value),
                  validation={'Input too long': lambda value: len(value) < 20})
         result = ui.label()
 
-    @example(ui.textarea, menu)
+    @element_example(ui.textarea)
     def textarea_example():
         ui.textarea(label='Text', placeholder='start typing',
                     on_change=lambda e: result.set_text('you typed: ' + e.value))
         result = ui.label()
 
-    @example(ui.number, menu)
+    @element_example(ui.number)
     def number_example():
         ui.number(label='Number', value=3.1415927, format='%.2f',
                   on_change=lambda e: result.set_text(f'you entered: {e.value}'))
         result = ui.label()
 
-    @example(ui.knob, menu)
+    @element_example(ui.knob)
     def knob_example():
         knob = ui.knob(0.3, show_value=True)
 
         with ui.knob(color='orange', track_color='grey-2').bind_value(knob, 'value'):
             ui.icon('volume_up')
 
-    @example(ui.color_input, menu)
+    @element_example(ui.color_input)
     def color_input_example():
         label = ui.label('Change my color!')
         ui.color_input(label='Color', value='#000000',
                        on_change=lambda e: label.style(f'color:{e.value}'))
 
-    @example(ui.color_picker, menu)
+    @element_example(ui.color_picker)
     def color_picker_example():
         picker = ui.color_picker(on_pick=lambda e: button.style(f'background-color:{e.color}!important'))
         button = ui.button(on_click=picker.open).props('icon=colorize')
 
-    @example(ui.date, menu)
+    @element_example(ui.date)
     def date_example():
         ui.date(value='2023-01-01', on_change=lambda e: result.set_text(e.value))
         result = ui.label()
 
-    @example(ui.time, menu)
+    @element_example(ui.time)
     def time_example():
         ui.time(value='12:00', on_change=lambda e: result.set_text(e.value))
         result = ui.label()
 
-    @example(ui.upload, menu)
+    @element_example(ui.upload)
     def upload_example():
         ui.upload(on_upload=lambda e: ui.notify(f'Uploaded {e.name}')).classes('max-w-full')
 
     heading('Markdown and HTML')
 
-    @example(ui.markdown, menu)
+    @element_example(ui.markdown)
     def markdown_example():
         ui.markdown('''This is **Markdown**.''')
 
-    @example(ui.mermaid, menu)
+    @element_example(ui.mermaid)
     def mermaid_example():
         ui.mermaid('''
         graph LR;
@@ -192,7 +192,7 @@ def create_full(menu: ui.element) -> None:
             A --> C;
         ''')
 
-    @example(ui.html, menu)
+    @element_example(ui.html)
     def html_example():
         ui.html('This is <strong>HTML</strong>.')
 

+ 38 - 2
website/reference_tools.py

@@ -1,13 +1,27 @@
 import re
 from typing import Callable
 
+import docutils.core
+
 from nicegui import globals, ui
+from nicegui.elements.markdown import apply_tailwind
 
 from .example import example
 
 SPECIAL_CHARACTERS = re.compile('[^(a-z)(A-Z)(0-9)-]')
 
 
+def remove_indentation(text: str) -> str:
+    """Remove indentation from a multi-line string based on the indentation of the first line."""
+    lines = text.splitlines()
+    while lines and not lines[0].strip():
+        lines.pop(0)
+    if not lines:
+        return ''
+    indentation = len(lines[0]) - len(lines[0].lstrip())
+    return '\n'.join(line[indentation:] for line in lines)
+
+
 def get_menu() -> ui.left_drawer:
     return [element for element in globals.get_client().elements.values() if isinstance(element, ui.left_drawer)][0]
 
@@ -27,8 +41,12 @@ def subheading(text: str, *, make_menu_entry: bool = True) -> None:
         with ui.link(target=f'#{target.id}'):
             ui.icon('link', size='sm').classes('text-gray-400 hover:text-gray-800')
     if make_menu_entry:
-        with get_menu():
-            ui.link(text, target=f'#{target.id}').classes('block py-1 px-2 hover:bg-gray-100')
+        with get_menu() as menu:
+            async def click():
+                if await ui.run_javascript(f'!!document.querySelector("div.q-drawer__backdrop")'):
+                    menu.hide()
+                    ui.open(f'#{target.id}')
+            ui.link(text, target=f'#{target.id}').props('data-close-overlay').on('click', click)
 
 
 class intro_example:
@@ -41,3 +59,21 @@ class intro_example:
         subheading(self.title, make_menu_entry=False)
         ui.label(self.explanation)
         return example(None, None)(f)
+
+
+class element_example:
+
+    def __init__(self, element_class: type) -> None:
+        self.element_class = element_class
+
+    def __call__(self, f: Callable) -> Callable:
+        doc = self.element_class.__init__.__doc__
+        title, documentation = doc.split('\n', 1)
+        documentation = remove_indentation(documentation)
+        documentation = documentation.replace('param ', '')
+        html = docutils.core.publish_parts(documentation, writer_name='html5_polyglot')['html_body']
+        html = apply_tailwind(html)
+        with ui.column().classes('w-full mb-8 gap-2'):
+            subheading(title)
+            ui.html(html).classes('documentation bold-links arrow-links')
+            return example(None, None)(f)