Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Switch input component #292

Merged
merged 3 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/streamsync/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,10 @@ def _transform_options_change(self, ev: StreamsyncEvent) -> Optional[List[str]]:
raise ValueError("Unauthorised option")
return payload

def _transform_toggle(self, ev: StreamsyncEvent) -> bool:
payload = bool(ev.payload)
return payload

def _transform_keydown(self, ev) -> Dict:
payload = ev.payload
key = str(payload.get("key"))
Expand Down
4 changes: 3 additions & 1 deletion ui/src/core/templateMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import CoreSliderInput from "../core_components/input/CoreSliderInput.vue";
import CoreTextInput from "../core_components/input/CoreTextInput.vue";
import CoreTextareaInput from "../core_components/input/CoreTextareaInput.vue";
import CoreRating from "../core_components/input/CoreRatingInput.vue";
import CoreSwitchInput from "../core_components/input/CoreSwitchInput.vue";
// layout
import CoreColumn from "../core_components/layout/CoreColumn.vue";
import CoreColumns from "../core_components/layout/CoreColumns.vue";
Expand Down Expand Up @@ -104,7 +105,8 @@ const templateMap = {
chat: CoreChat,
step: CoreStep,
steps: CoreSteps,
ratinginput: CoreRating
ratinginput: CoreRating,
switchinput: CoreSwitchInput,
};

if (STREAMSYNC_LIVE_CCT === "yes") {
Expand Down
4 changes: 4 additions & 0 deletions ui/src/core_components/input/CoreRatingInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ label {
}

.unit.stars {
box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.2) inset;
clip-path: polygon(
50% 0%,
61% 35%,
Expand All @@ -281,10 +282,12 @@ label {
}

.unit.faces {
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2) inset;
clip-path: circle(50%);
}

.unit.hearts {
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2) inset;
clip-path: path(
"M2.54139 14.2987C0.97724 12.7905 0 10.646 0 8.26667C0 3.70111 3.5983 0 8.03704 0C10.4025 0 12.5293 1.05112 14 2.72404C15.4707 1.05112 17.5975 0 19.963 0C24.4017 0 28 3.70111 28 8.26667C28 10.6181 27.0455 12.7402 25.5133 14.2455L14.0815 28L2.54139 14.2987Z"
);
Expand All @@ -297,6 +300,7 @@ label {
width: 28px;
height: 28px;
background: var(--accentColor);
box-shadow: none;
}

.unit .filler.light {
Expand Down
126 changes: 126 additions & 0 deletions ui/src/core_components/input/CoreSwitchInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<template>
<div ref="rootEl" class="CoreSwitchInput">
<div
class="switch"
:class="{ on: toggleValue }"
tabindex="0"
role="switch"
:aria-checked="toggleValue"
@click="handleToggle"
@keydown.enter.space="handleToggle"
>
<div class="toggle"></div>
</div>
<label @click="handleToggle">
{{ fields.label.value }}
</label>
</div>
</template>

<script lang="ts">
import { inject, Ref } from "vue";
import { ref } from "vue";
import { FieldType } from "../../streamsyncTypes";
import {
accentColor,
primaryTextColor,
separatorColor,
cssClasses,
} from "../../renderer/sharedStyleFields";

const description = "A user input component with a simple on/off status.";

const onToggleHandlerStub = `
def handle_toggle(state, payload):

# The payload will be a bool

state["its_on"] = payload`;

export default {
streamsync: {
name: "Switch Input",
description,
category: "Input",
fields: {
label: {
name: "Label",
init: "Input Label",
type: FieldType.Text,
},
accentColor,
primaryTextColor,
separatorColor,
cssClasses,
},
events: {
"ss-toggle": {
desc: "Sent when the switch is toggled.",
stub: onToggleHandlerStub.trim(),
bindable: true,
},
},
},
};
</script>

<script setup lang="ts">
import injectionKeys from "../../injectionKeys";
import { useFormValueBroker } from "../../renderer/useFormValueBroker";

const fields = inject(injectionKeys.evaluatedFields);
const rootEl: Ref<HTMLElement> = ref(null);
const ss = inject(injectionKeys.core);
const instancePath = inject(injectionKeys.instancePath);
const { handleInput } = useFormValueBroker(ss, instancePath, rootEl);
const toggleValue = ref(false);

function handleToggle() {
toggleValue.value = !toggleValue.value;
handleInput(toggleValue.value, "ss-toggle");
}
</script>

<style scoped>
@import "../../renderer/sharedStyles.css";
.CoreSwitchInput {
display: flex;
gap: 8px;
align-items: center;
}

.switch {
background: var(--separatorColor);
width: 32px;
height: 16px;
padding: 1px;
border-radius: 8px;
cursor: pointer;
box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.2) inset;
overflow: hidden;
}

.switch:focus-visible {
outline: 1px solid var(--primaryTextColor);
}

.switch.on {
background: var(--accentColor);
}

.toggle {
width: 14px;
height: 14px;
background: var(--containerBackgroundColor);
border-radius: 8px;
transition: 0.2s margin ease-in-out;
}

.switch.on .toggle {
margin-left: 16px;
}

label {
cursor: pointer;
}
</style>
Loading