diff --git a/demo/uploader.py b/demo/uploader.py index cc0875ee8..a3257b5eb 100644 --- a/demo/uploader.py +++ b/demo/uploader.py @@ -19,20 +19,24 @@ class State: ) def app(): state = me.state(State) - me.uploader( - label="Upload Image", - accepted_file_types=["image/jpeg", "image/png"], - on_upload=handle_upload, - ) - - if state.contents: - with me.box(style=me.Style(margin=me.Margin.all(10))): - me.text(f"File name: {state.name}") - me.text(f"File size: {state.size}") - me.text(f"File type: {state.mime_type}") - - with me.box(style=me.Style(margin=me.Margin.all(10))): - me.image(src=state.contents) + with me.box(style=me.Style(padding=me.Padding.all(15))): + me.uploader( + label="Upload Image", + accepted_file_types=["image/jpeg", "image/png"], + on_upload=handle_upload, + type="flat", + color="primary", + style=me.Style(font_weight="bold"), + ) + + if state.contents: + with me.box(style=me.Style(margin=me.Margin.all(10))): + me.text(f"File name: {state.name}") + me.text(f"File size: {state.size}") + me.text(f"File type: {state.mime_type}") + + with me.box(style=me.Style(margin=me.Margin.all(10))): + me.image(src=state.contents) def handle_upload(event: me.UploadEvent): diff --git a/mesop/components/uploader/uploader.ng.html b/mesop/components/uploader/uploader.ng.html index 4cf5172dd..a78bca7dc 100644 --- a/mesop/components/uploader/uploader.ng.html +++ b/mesop/components/uploader/uploader.ng.html @@ -5,8 +5,53 @@ #fileUpload />
- - {{ filename() || "No file chosen" }} + + } @if(config().getTypeIndex() === 1) { + + + } @if(config().getTypeIndex() === 2) { + + + } @if(config().getTypeIndex() === 3) { + + + } {{ filename() || "No file chosen" }}
diff --git a/mesop/components/uploader/uploader.proto b/mesop/components/uploader/uploader.proto index b42d9170d..25ad01c3c 100644 --- a/mesop/components/uploader/uploader.proto +++ b/mesop/components/uploader/uploader.proto @@ -15,8 +15,18 @@ message UploadEvent { } +// Next ID: 9 message UploaderType { optional string label = 1; repeated string accepted_file_type = 2; optional string on_upload_event_handler_id = 3; + optional string color = 4; + optional bool disable_ripple = 5; + optional bool disabled = 6; + + // Type has two properties: + // |type_index| is used for rendering + // |type| is used for editor value + optional int32 type_index = 7; + optional string type = 8; } diff --git a/mesop/components/uploader/uploader.py b/mesop/components/uploader/uploader.py index d4424b13f..9b32ad696 100644 --- a/mesop/components/uploader/uploader.py +++ b/mesop/components/uploader/uploader.py @@ -1,9 +1,10 @@ import io from dataclasses import dataclass -from typing import Any, Callable, Sequence +from typing import Any, Callable, Literal, Sequence import mesop.components.uploader.uploader_pb2 as uploader_pb from mesop.component_helpers import ( + Style, insert_component, register_event_handler, register_event_mapper, @@ -72,6 +73,11 @@ def uploader( accepted_file_types: Sequence[str] | None = None, key: str | None = None, on_upload: Callable[[UploadEvent], Any] | None = None, + type: Literal["raised", "flat", "stroked"] | None = None, + color: Literal["primary", "accent", "warn"] | None = None, + disable_ripple: bool = False, + disabled: bool = False, + style: Style | None = None, ): """ This function creates an uploader. @@ -79,7 +85,13 @@ def uploader( Args: label: Upload button label. accepted_file_types: List of accepted file types. See the [accept parameter](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept). + key: The component [key](../components/index.md#component-key). on_upload: File upload event handler. + type: Type of button style to use + color: Theme color palette of the button + disable_ripple: Whether the ripple effect is disabled or not. + disabled: Whether the button is disabled. + style: Style for the component. """ insert_component( key=key, @@ -92,5 +104,25 @@ def uploader( ) if on_upload else "", + type_index=_get_type_index(type), + type=type, + color=color, + disable_ripple=disable_ripple, + disabled=disabled, ), + style=style, ) + + +def _get_type_index( + type: Literal["raised", "flat", "stroked"] | None, +) -> int: + if type is None: + return 0 + if type == "raised": + return 1 + if type == "flat": + return 2 + if type == "stroked": + return 3 + raise Exception("Unexpected type: " + type) diff --git a/mesop/components/uploader/uploader.ts b/mesop/components/uploader/uploader.ts index 54c485199..ba4725602 100644 --- a/mesop/components/uploader/uploader.ts +++ b/mesop/components/uploader/uploader.ts @@ -4,6 +4,7 @@ import { Key, Type, UserEvent, + Style, } from 'mesop/mesop/protos/ui_jspb_proto_pb/mesop/protos/ui_pb'; import { UploaderType, @@ -11,6 +12,7 @@ import { UploadedFile, } from 'mesop/mesop/components/uploader/uploader_jspb_proto_pb/mesop/components/uploader/uploader_pb'; import {Channel} from '../../web/src/services/channel'; +import {formatStyle} from '../../web/src/utils/styles'; @Component({ selector: 'mesop-uploader', @@ -22,6 +24,7 @@ import {Channel} from '../../web/src/services/channel'; export class UploaderComponent { @Input({required: true}) type!: Type; @Input() key!: Key; + @Input() style!: Style; private _config!: UploaderType; private _filename = ''; @@ -76,4 +79,8 @@ export class UploaderComponent { userEvent.setBytesValue(uploadEvent.serializeBinary()); this.channel.dispatch(userEvent); } + + getStyle(): string { + return formatStyle(this.style); + } }