Skip to content

Commit

Permalink
Merge pull request #486 from madeindjs/WF-9
Browse files Browse the repository at this point in the history
feat(ui): introduce `CoreColorInput`. WF-9
  • Loading branch information
ramedina86 authored Jul 23, 2024
2 parents 86f28ed + c47ba50 commit dba74df
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 4 deletions.
Binary file added docs/framework/public/components/colorinput.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/ui/src/core/templateMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import CoreAvatar from "../core_components/content/CoreAvatar.vue";
import CoreJsonViewer from "../core_components/content/CoreJsonViewer.vue";
// input
import CoreCheckboxInput from "../core_components/input/CoreCheckboxInput.vue";
import CoreColorInput from "../core_components/input/CoreColorInput.vue";
import CoreDateInput from "../core_components/input/CoreDateInput.vue";
import CoreDropdownInput from "../core_components/input/CoreDropdownInput.vue";
import CoreFileInput from "../core_components/input/CoreFileInput.vue";
Expand Down Expand Up @@ -94,6 +95,7 @@ const templateMap = {
textareainput: CoreTextareaInput,
numberinput: CoreNumberInput,
sliderinput: CoreSliderInput,
colorinput: CoreColorInput,
dateinput: CoreDateInput,
timeinput: CoreTimeInput,
radioinput: CoreRadioInput,
Expand Down
53 changes: 53 additions & 0 deletions src/ui/src/core_components/base/BaseInputColor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<input
ref="pickerEl"
type="color"
class="BaseInputColor"
:value="value"
:list="datalistId"
@input="handleInput"
@change="handleChange"
/>
<datalist v-if="datalistId" :id="datalistId">
<option v-for="color of customColors" :key="color">{{ color }}</option>
</datalist>
</template>

<script setup lang="ts">
import { PropType, computed, inject, ref } from "vue";
import injectionKeys from "../../injectionKeys";
const props = defineProps({
value: { type: String, required: false, default: undefined },
customColors: { type: Array as PropType<string[]>, default: () => [] },
});
const emit = defineEmits({
"update:value": (value: string) => typeof value === "string",
change: (value: string) => typeof value === "string",
});
const pickerEl = ref<HTMLInputElement | undefined>();
const flattenedInstancePath = inject(injectionKeys.flattenedInstancePath);
const datalistId = computed(() =>
props.customColors?.length ? `${flattenedInstancePath}_datalist` : null,
);
function handleInput(event: Event) {
emit("update:value", (event.target as HTMLInputElement).value);
}
function handleChange(event: Event) {
emit("change", (event.target as HTMLInputElement).value);
}
</script>

<style scoped>
.BaseInputColor {
width: 12ch;
border: 0;
outline: none;
}
</style>
100 changes: 100 additions & 0 deletions src/ui/src/core_components/input/CoreColorInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<template>
<BaseInputWrapper
ref="rootInstance"
:label="fields.label.value"
class="CoreColorInput"
>
<BaseInputColor
:value="formValue"
:custom-colors="colorList"
@update:value="handleInput($event, 'wf-change')"
@change="handleInput($event, 'wf-change-finish')"
/>
</BaseInputWrapper>
</template>

<script lang="ts">
import { ComponentPublicInstance } from "vue";
import { cssClasses } from "../../renderer/sharedStyleFields";
import { FieldType, WriterComponentDefinition } from "../../writerTypes";
import BaseInputColor from "../base/BaseInputColor.vue";
import BaseInputWrapper from "../base/BaseInputWrapper.vue";
const description =
"A user input component that allows users to select a color using a color picker interface.";
const onChangeHandlerStub = `
def onchange_handler(state, payload):
# Set the state variable "new_color" to the new value, provided as string.
state["new_color"] = payload`;
const definition = {
name: "Color Input",
description,
category: "Input",
fields: {
label: {
name: "Label",
init: "Input Label",
type: FieldType.Text,
},
colorList: {
name: "Color List",
desc: "List of predefined colors",
type: FieldType.Object,
init: JSON.stringify([
"#5551ff",
"#3be19b",
"#ff3d00",
"#333333",
"#0094d1",
]),
},
cssClasses,
},
events: {
"wf-change": {
desc: "Capture changes as they happen.",
stub: onChangeHandlerStub,
bindable: true,
},
"wf-change-finish": {
desc: "Capture changes once this control has lost focus.",
stub: onChangeHandlerStub,
},
},
} satisfies WriterComponentDefinition;
export default { writer: definition };
</script>
<script setup lang="ts">
import { computed, inject, ref } from "vue";
import injectionKeys from "../../injectionKeys";
import { useFormValueBroker } from "../../renderer/useFormValueBroker";
const fields = inject(injectionKeys.evaluatedFields);
const rootInstance = ref<ComponentPublicInstance | null>(null);
const wf = inject(injectionKeys.core);
const instancePath = inject(injectionKeys.instancePath);
const colorList = computed(() =>
Array.isArray(fields.colorList.value) ? fields.colorList.value : undefined,
);
const { formValue, handleInput } = useFormValueBroker<string>(
wf,
instancePath,
rootInstance,
);
</script>

<style scoped>
@import "../../renderer/sharedStyles.css";
@import "../../renderer/colorTransformations.css";
.CoreColorInput {
width: fit-content;
}
</style>
8 changes: 4 additions & 4 deletions src/ui/src/renderer/useFormValueBroker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentPublicInstance, computed, Ref, ref, watch } from "vue";
import { Core, InstancePath } from "../writerTypes";
import { useEvaluator } from "../renderer/useEvaluator";
import { Core, InstancePath } from "../writerTypes";

/**
*
Expand All @@ -10,14 +10,14 @@ import { useEvaluator } from "../renderer/useEvaluator";
* @param componentId
* @returns
*/
export function useFormValueBroker(
export function useFormValueBroker<T = any>(
wf: Core,
instancePath: InstancePath,
emitterEl: Ref<HTMLElement | ComponentPublicInstance>,
) {
const formValue: Ref<any> = ref();
const formValue: Ref<T> = ref();
const isBusy = ref(false);
const queuedEvent: Ref<{ eventValue: any; emitEventType: string }> =
const queuedEvent: Ref<{ eventValue: T; emitEventType: string }> =
ref(null);

const componentId = instancePath.at(-1).componentId;
Expand Down

0 comments on commit dba74df

Please sign in to comment.