def Scene(): position, set_position = use_state(Position(100, 100, 0)) return html.div( {"style": {"width": "225px"}}, html.div( { "style": { "width": "200px", "height": "200px", "backgroundColor": "slategray", } }, image( "png", CHARACTER_IMAGE, { "style": { "position": "relative", "left": f"{position.x}px", "top": f"{position.y}.px", "transform": f"rotate({position.angle}deg) scale(2, 2)", } }, ), ), html.button({"onClick": lambda e: set_position(translate(x=-10))}, "Move Left"), html.button({"onClick": lambda e: set_position(translate(x=10))}, "Move Right"), html.button({"onClick": lambda e: set_position(translate(y=-10))}, "Move Up"), html.button({"onClick": lambda e: set_position(translate(y=10))}, "Move Down"), html.button({"onClick": lambda e: set_position(rotate(-30))}, "Rotate Left"), html.button({"onClick": lambda e: set_position(rotate(30))}, "Rotate Right"), )
def Grid(): line_size = 5 selected_indices, set_selected_indices = use_state({1, 2, 4}) def make_handle_click(index): def handle_click(event): if index in selected_indices: set_selected_indices(selected_indices - {index}) else: set_selected_indices(selected_indices | {index}) return handle_click return html.div( {"style": {"display": "flex", "flex-direction": "row"}}, [ html.div( { "onClick": make_handle_click(index), "style": { "height": "30px", "width": "30px", "backgroundColor": ( "black" if index in selected_indices else "white" ), "outline": "1px solid grey", "cursor": "pointer", }, }, key=index, ) for index in range(line_size) ], )
def Root(): toggle, toggle_type.current = use_toggle(True) handler = element_static_handler.use(lambda: None) if toggle: return html.div(html.button({"onEvent": handler})) else: return html.div(SomeComponent())
def MovingDot(): position, set_position = use_state({"x": 0, "y": 0}) async def handle_pointer_move(event): outer_div_info = event["currentTarget"] outer_div_bounds = outer_div_info["boundingClientRect"] set_position({ "x": event["clientX"] - outer_div_bounds["x"], "y": event["clientY"] - outer_div_bounds["y"], }) return html.div( { "onPointerMove": handle_pointer_move, "style": { "position": "relative", "height": "200px", "width": "100%", "backgroundColor": "white", }, }, html.div({ "style": { "position": "absolute", "backgroundColor": "red", "borderRadius": "50%", "width": "20px", "height": "20px", "left": "-10px", "top": "-10px", "transform": f"translate({position['x']}px, {position['y']}px)", }, }), )
def HasScript(): src_id, incr_src_id.current = use_counter(0) if src_id == 0: # on initial display we haven't added the file yet. return html.div() else: return html.div( html.div({"id": "run-count", "data-value": 0}), html.script( {"src": f"/_api/modules/{file_name_template.format(src_id=src_id)}"} ), )
def Definitions(): term_to_add, set_term_to_add = use_state(None) definition_to_add, set_definition_to_add = use_state(None) all_terms, set_all_terms = use_state({}) def handle_term_to_add_change(event): set_term_to_add(event["target"]["value"]) def handle_definition_to_add_change(event): set_definition_to_add(event["target"]["value"]) def handle_add_click(event): if term_to_add and definition_to_add: set_all_terms({**all_terms, term_to_add: definition_to_add}) set_term_to_add(None) set_definition_to_add(None) def make_delete_click_handler(term_to_delete): def handle_click(event): set_all_terms({t: d for t, d in all_terms.items() if t != term_to_delete}) return handle_click return html.div( html.button({"onClick": handle_add_click}, "add term"), html.label( "Term: ", html.input({"value": term_to_add, "onChange": handle_term_to_add_change}), ), html.label( "Definition: ", html.input( { "value": definition_to_add, "onChange": handle_definition_to_add_change, } ), ), html.hr(), [ html.div( html.button( {"onClick": make_delete_click_handler(term)}, "delete term" ), html.dt(term), html.dd(definition), key=term, ) for term, definition in all_terms.items() ], )
def HasScript(): count, incr_count.current = use_counter(1) return html.div( html.div({"id": "mount-count", "data-value": 0}), html.div({"id": "unmount-count", "data-value": 0}), html.script( f"""() => {{ const mountCountEl = document.getElementById("mount-count"); const unmountCountEl = document.getElementById("unmount-count"); mountCountEl.setAttribute("data-value", {count}); return () => unmountCountEl.setAttribute("data-value", {count});; }}""" ), )
def App(): is_sent, set_is_sent = use_state(False) message, set_message = use_state("") if is_sent: return html.div( html.h1("Message sent!"), html.button( {"onClick": lambda event: set_is_sent(False)}, "Send new message?" ), ) @event(prevent_default=True) def handle_submit(event): set_message("") set_is_sent(True) return html.form( {"onSubmit": handle_submit, "style": {"display": "inline-grid"}}, html.textarea( { "placeholder": "Your message here...", "value": message, "onChange": lambda event: set_message(event["target"]["value"]), } ), html.button({"type": "submit"}, "Send"), )
def Gallery(): index, set_index = hooks.use_state(0) def handle_click(event): set_index(index + 1) bounded_index = index % len(sculpture_data) sculpture = sculpture_data[bounded_index] alt = sculpture["alt"] artist = sculpture["artist"] description = sculpture["description"] name = sculpture["name"] url = sculpture["url"] return html.div( html.button({"onClick": handle_click}, "Next"), html.h2(name, " by ", artist), html.p(f"({bounded_index + 1} of {len(sculpture_data)})"), html.img({ "src": url, "alt": alt, "style": { "height": "200px" } }), html.p(description), )
def ColorButton(): color, set_color = use_state("gray") def handle_click(event): set_color("orange") set_color("pink") set_color("blue") def handle_reset(event): set_color("gray") return html.div( html.button( { "onClick": handle_click, "style": { "backgroundColor": color } }, "Set Color"), html.button( { "onClick": handle_reset, "style": { "backgroundColor": color } }, "Reset"), )
def ArtistList(): artist_to_add, set_artist_to_add = use_state("") artists, set_artists = use_state( ["Marta Colvin Andrade", "Lamidi Olonade Fakeye", "Louise Nevelson"]) def handle_change(event): set_artist_to_add(event["target"]["value"]) def handle_add_click(event): if artist_to_add not in artists: set_artists([*artists, artist_to_add]) set_artist_to_add("") def make_handle_delete_click(index): def handle_click(event): set_artists(artists[:index] + artists[index + 1:]) return handle_click return html.div( html.h1("Inspiring sculptors:"), html.input({ "value": artist_to_add, "onChange": handle_change }), html.button({"onClick": handle_add_click}, "add"), html.ul([ html.li( name, html.button({"onClick": make_handle_delete_click(index)}, "delete"), key=name, ) for index, name in enumerate(artists) ]), )
async def show( self, component: RootComponentConstructor, ) -> None: self._next_view_id += 1 view_id = f"display-{self._next_view_id}" self.backend.mount(lambda: html.div({"id": view_id}, component())) await self.goto("/") await self.page.wait_for_selector(f"#{view_id}", state="attached")
def DivInDiv(): stop_propagatation, set_stop_propagatation = hooks.use_state(True) inner_count, set_inner_count = hooks.use_state(0) outer_count, set_outer_count = hooks.use_state(0) div_in_div = html.div( { "onClick": lambda event: set_outer_count(outer_count + 1), "style": { "height": "100px", "width": "100px", "backgroundColor": "red" }, }, html.div( { "onClick": event( lambda event: set_inner_count(inner_count + 1), stop_propagation=stop_propagatation, ), "style": { "height": "50px", "width": "50px", "backgroundColor": "blue" }, }, ), ) return html.div( html.button( { "onClick": lambda event: set_stop_propagatation(not stop_propagatation) }, "Toggle Propogation", ), html.pre(f"Will propagate: {not stop_propagatation}"), html.pre(f"Inner click count: {inner_count}"), html.pre(f"Outer click count: {outer_count}"), div_in_div, )
def App(): return html.div( html.section({"style": { "width": "50%", "float": "left" }}, Gallery()), html.section({"style": { "width": "50%", "float": "left" }}, Gallery()), )
def DoNotChangePages(): return html.div( html.p("Normally clicking this link would take you to a new page"), html.a( { "onClick": event(lambda event: None, prevent_default=True), "href": "https://google.com", }, "https://google.com", ), )
def Counter(): number, set_number = use_state(0) async def handle_click(event): await asyncio.sleep(3) set_number(lambda old_number: old_number + 1) return html.div( html.h1(number), html.button({"onClick": handle_click}, "Increment"), )
def Counter(): number, set_number = use_state(0) def handle_click(event): set_number(number + 5) print(number) return html.div( html.h1(number), html.button({"onClick": handle_click}, "Increment"), )
def Parent(): state, set_state = use_state(0) return html.div( html.button( { "onClick": set_child_key_num.use(lambda: set_state(state + 1)) }, "click me", ), Child("some-key"), Child(f"key-{state}"), )
def Counter(): number, set_number = use_state(0) async def handle_click(event): set_number(number + 5) print("about to print...") await asyncio.sleep(3) print(number) return html.div( html.h1(number), html.button({"onClick": handle_click}, "Increment"), )
def Gallery(): index, set_index = hooks.use_state(0) show_more, set_show_more = hooks.use_state(False) def handle_next_click(event): set_index(index + 1) def handle_more_click(event): set_show_more(not show_more) bounded_index = index % len(sculpture_data) sculpture = sculpture_data[bounded_index] alt = sculpture["alt"] artist = sculpture["artist"] description = sculpture["description"] name = sculpture["name"] url = sculpture["url"] return html.div( html.button({"onClick": handle_next_click}, "Next"), html.h2(name, " by ", artist), html.p(f"({bounded_index + 1} or {len(sculpture_data)})"), html.img({ "src": url, "alt": alt, "style": { "height": "200px" } }), html.div( html.button( {"onClick": handle_more_click}, f"{'Show' if show_more else 'Hide'} details", ), (html.p(description) if show_more else ""), ), )
def Child(child_key): state, set_state = use_state(0) @use_effect async def record_if_state_is_reset(): if state: return effect_calls_without_state.append(child_key) set_state(1) did_call_effect.set() return html.div( child_key, key=child_key, )
def ArtistList(): artists, set_artists = use_state( ["Marta Colvin Andrade", "Lamidi Olonade Fakeye", "Louise Nevelson"]) def handle_sort_click(event): set_artists(list(sorted(artists))) def handle_reverse_click(event): set_artists(list(reversed(artists))) return html.div( html.h1("Inspiring sculptors:"), html.button({"onClick": handle_sort_click}, "sort"), html.button({"onClick": handle_reverse_click}, "reverse"), html.ul([html.li(name, key=name) for name in artists]), )
def Form(): person, set_person = use_state({ "first_name": "Barbara", "last_name": "Hepworth", "email": "*****@*****.**", }) def handle_first_name_change(event): set_person({**person, "first_name": event["target"]["value"]}) def handle_last_name_change(event): set_person({**person, "last_name": event["target"]["value"]}) def handle_email_change(event): set_person({**person, "email": event["target"]["value"]}) return html.div( html.label( "First name: ", html.input( { "value": person["first_name"], "onChange": handle_first_name_change }, ), ), html.label( "First name: ", html.input( { "value": person["last_name"], "onChange": handle_last_name_change }, ), ), html.label( "First name: ", html.input( { "value": person["email"], "onChange": handle_email_change }, ), ), html.p( f"{person['first_name']} {person['last_name']} {person['email']}"), )
def ArtistList(): artist_to_add, set_artist_to_add = use_state("") artists, set_artists = use_state([]) def handle_change(event): set_artist_to_add(event["target"]["value"]) def handle_click(event): if artist_to_add and artist_to_add not in artists: set_artists([*artists, artist_to_add]) set_artist_to_add("") return html.div( html.h1("Inspiring sculptors:"), html.input({ "value": artist_to_add, "onChange": handle_change }), html.button({"onClick": handle_click}, "add"), html.ul([html.li(name, key=name) for name in artists]), )
), ( """html(f"<div><!-->slight deviation from HTML comments<--></div>")""", {}, { "tagName": "div" }, ), ) test_component = make_html_dialect_test( ( 'html(f"<{MyComponentWithChildren}>hello<//>")', { "MyComponentWithChildren": lambda children: html.div(children + ["world"]) }, { "tagName": "div", "children": ["hello", "world"] }, ), ( 'html(f"<{MyComponentWithAttributes} x=2 y=3 />")', { "MyComponentWithAttributes": lambda x, y: html.div({ "x": int(x) * 2, "y": int(y) * 2 }) },
def App(): return html.div( PrintButton("Play", "Playing"), PrintButton("Pause", "Paused"), )
def App(): return html.div( ButtonWithDelay("print 3 seconds later", delay=3), ButtonWithDelay("print immediately", delay=0), )
def MyTodoList(): return html.div( html.h1("My Todo List"), html.img({"src": "https://picsum.photos/id/0/500/300"}), html.ul(html.li("The first thing I need to do is...")), )
def Root(): is_mounted, toggle_is_mounted.current = use_toggle() return html.div( html.div({"id": "mount-state", "data-value": False}), HasScript() if is_mounted else html.div(), )
def App(): return html.div(GoodComponent(), BadComponent())