Skip to content
Open
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
3 changes: 3 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<template>
<h3>Fields</h3>
<QuesoTextField name="textfield" label="QuesoTextField" v-model="TextField" />
<QuesoTextField name="textfield" label="QuesoTextField" v-model="TextField">
<template #afterInput>test</template>
</QuesoTextField>
<QuesoPassword name="password" label="QuesoPassword" v-model="PasswordField" />
<QuesoTextArea name="textarea" label="QuesoTextArea" v-model="TextArea" />
<QuesoCheckbox
Expand Down
29 changes: 29 additions & 0 deletions src/components/QuesoField/QuesoField.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,33 @@ describe("QuesoField", () => {
});
expect(wrapper.vm).toBeTruthy();
});

test("applies has-value class when hasValue prop is true", () => {
const wrapper = mount(QuesoField, {
props: {
name: "field-name",
hasValue: true,
},
});
expect(wrapper.classes()).toContain("has-value");
});

test("does not apply has-value class when hasValue prop is false", () => {
const wrapper = mount(QuesoField, {
props: {
name: "field-name",
hasValue: false,
},
});
expect(wrapper.classes()).not.toContain("has-value");
});

test("does not apply has-value class when hasValue prop is undefined", () => {
const wrapper = mount(QuesoField, {
props: {
name: "field-name",
},
});
expect(wrapper.classes()).not.toContain("has-value");
});
});
3 changes: 2 additions & 1 deletion src/components/QuesoField/QuesoField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const emit = defineEmits<{
/**
* STATES
*/
const { isRequired, isDisabled, isError, isReadOnly } = toRefs(props);
const { isRequired, isDisabled, isError, isReadOnly, hasValue } = toRefs(props);

// Active
const isActive = ref<boolean>(false);
Expand Down Expand Up @@ -93,6 +93,7 @@ const fieldClasses = computed<HTMLAttributes["class"]>(() => ({
"is-active": isActive.value,
"is-hover": isHover.value,
"is-read-only": isReadOnly.value,
"has-value": hasValue.value,
}));

/**
Expand Down
1 change: 1 addition & 0 deletions src/components/QuesoField/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface QuesoFieldProps {

export interface QuesoFieldPrivateProps extends QuesoFieldProps {
hasStaticLabel?: boolean;
hasValue?: boolean;
}

// Typeguard
Expand Down
22 changes: 22 additions & 0 deletions src/components/QuesoPassword/QuesoPassword.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,26 @@ describe("QuesoPassword", () => {
});
expect(wrapper.find(".queso-field__input").exists()).toBe(true);
});

test("applies has-value class when model has content", () => {
const wrapper = mount(QuesoPassword, {
props: {
name: "field-name",
modelValue: "secret",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("has-value");
});

test("does not apply has-value class when model is empty", () => {
const wrapper = mount(QuesoPassword, {
props: {
name: "field-name",
modelValue: "",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});
});
3 changes: 2 additions & 1 deletion src/components/QuesoPassword/QuesoPassword.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<queso-field class="-password" v-bind="extendedProps">
<queso-field class="-password" v-bind="{ ...extendedProps, hasValue: hasContent }">
<template #beforeLabel="exposedData">
<slot name="beforeLabel" v-bind="exposedData"></slot>
</template>
Expand Down Expand Up @@ -92,6 +92,7 @@ const props = withDefaults(defineProps<QuesoPasswordProps>(), {});
const extendedProps = useExtendedFieldProps(props);

const model = defineModel<QuesoPasswordModel>({ required: true, default: "" });
const hasContent = computed(() => String(model.value ?? "").trim().length > 0);

const isPasswordShow = ref<boolean>(false);
const type = computed(() => (isPasswordShow.value ? "text" : "password"));
Expand Down
24 changes: 24 additions & 0 deletions src/components/QuesoSelect/QuesoSelect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@ describe("QuesoSelect", () => {
expect(field.classes()).toContain("is-disabled");
});

test("applies has-value class when model has a selected value", () => {
const wrapper = mount(QuesoSelect, {
props: {
...props,
modelValue: "1",
},
});

const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("has-value");
});

test("does not apply has-value class when model is empty", () => {
const wrapper = mount(QuesoSelect, {
props: {
...props,
modelValue: "",
},
});

const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});

// Hiding it for now
// test("renders correctly the label", () => {
// const wrapper = shallowMount(QuesoSelect, {
Expand Down
7 changes: 6 additions & 1 deletion src/components/QuesoSelect/QuesoSelect.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<queso-field class="-select" v-bind="extendedProps">
<queso-field class="-select" v-bind="{ ...extendedProps, hasValue: hasContent }">
<template #beforeLabel="exposedData">
<slot name="beforeLabel" v-bind="exposedData"></slot>
</template>
Expand Down Expand Up @@ -98,6 +98,11 @@ const extendedProps = useExtendedFieldProps(props);

const model = defineModel<QuesoSelectModel>({ required: true });

const hasContent = computed(() => {
const val = model.value;
return val != null && val !== "";
});

// Writable computed because QuesoDropdown expects an array
const dropdownModel = computed<QuesoDropdownOptionValues>({
get() {
Expand Down
24 changes: 24 additions & 0 deletions src/components/QuesoSelectMultiple/QuesoSelectMultiple.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,28 @@ describe("QuesoSelectMultiple.vue", () => {
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("is-disabled");
});

test("applies has-value class when model has selected values", () => {
const wrapper = mount(QuesoSelectMultiple, {
props: {
...props,
modelValue: ["option1"],
},
});

const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("has-value");
});

test("does not apply has-value class when model is empty", () => {
const wrapper = mount(QuesoSelectMultiple, {
props: {
...props,
modelValue: [],
},
});

const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});
});
4 changes: 3 additions & 1 deletion src/components/QuesoSelectMultiple/QuesoSelectMultiple.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<queso-field class="-select-multiple" v-bind="extendedProps">
<queso-field class="-select-multiple" v-bind="{ ...extendedProps, hasValue: hasContent }">
<template #beforeLabel="exposedData">
<slot name="beforeLabel" v-bind="exposedData"></slot>
</template>
Expand Down Expand Up @@ -85,6 +85,7 @@
</template>

<script setup lang="ts" generic="TOptionData extends Record<string, any> = Record<string, any>">
import { computed } from "vue";
import { useExtendedFieldProps } from "@composables/fields";

import type { QuesoSelectMultipleModel, QuesoSelectMultipleProps } from "./types";
Expand All @@ -96,6 +97,7 @@ const props = defineProps<QuesoSelectMultipleProps<TOptionData>>();
const extendedProps = useExtendedFieldProps(props);

const model = defineModel<QuesoSelectMultipleModel>({ required: true, default: [] });
const hasContent = computed(() => Array.isArray(model.value) && model.value.length > 0);
</script>

<style lang="scss">
Expand Down
22 changes: 22 additions & 0 deletions src/components/QuesoTextArea/QuesoTextArea.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,26 @@ describe("QuesoTextArea", () => {
});
expect(wrapper.find(".queso-field__input").exists()).toBe(true);
});

test("applies has-value class when model has content", () => {
const wrapper = mount(QuesoTextArea, {
props: {
name: "field-name",
modelValue: "hello",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("has-value");
});

test("does not apply has-value class when model is empty", () => {
const wrapper = mount(QuesoTextArea, {
props: {
name: "field-name",
modelValue: "",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});
});
4 changes: 3 additions & 1 deletion src/components/QuesoTextArea/QuesoTextArea.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<queso-field class="-text-area" v-bind="extendedProps">
<queso-field class="-text-area" v-bind="{ ...extendedProps, hasValue: hasContent }">
<template #beforeLabel="exposedData">
<slot name="beforeLabel" v-bind="exposedData"></slot>
</template>
Expand Down Expand Up @@ -54,6 +54,7 @@
</template>

<script setup lang="ts">
import { computed } from "vue";
import { useExtendedFieldProps } from "@composables/fields";

import type { QuesoTextAreaModel, QuesoTextAreaProps } from "./types";
Expand All @@ -64,6 +65,7 @@ const props = defineProps<QuesoTextAreaProps>();
const extendedProps = useExtendedFieldProps(props);

const model = defineModel<QuesoTextAreaModel>({ required: true, default: "" });
const hasContent = computed(() => String(model.value ?? "").trim().length > 0);
</script>

<style lang="scss">
Expand Down
33 changes: 33 additions & 0 deletions src/components/QuesoTextField/QuesoTextField.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,37 @@ describe("QuesoTextField", () => {
});
expect(wrapper.find(".queso-field__input").exists()).toBe(true);
});

test("applies has-value class when model has content", () => {
const wrapper = mount(QuesoTextField, {
props: {
name: "field-name",
modelValue: "hello",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).toContain("has-value");
});

test("does not apply has-value class when model is empty", () => {
const wrapper = mount(QuesoTextField, {
props: {
name: "field-name",
modelValue: "",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});

test("does not apply has-value class when model has only whitespace", () => {
const wrapper = mount(QuesoTextField, {
props: {
name: "field-name",
modelValue: " ",
},
});
const field = wrapper.findComponent({ name: "QuesoField" });
expect(field.classes()).not.toContain("has-value");
});
});
5 changes: 4 additions & 1 deletion src/components/QuesoTextField/QuesoTextField.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<queso-field class="-text-field" v-bind="extendedProps">
<queso-field class="-text-field" v-bind="{ ...extendedProps, hasValue: hasContent }">
<template #beforeLabel="exposedData">
<slot name="beforeLabel" v-bind="exposedData"></slot>
</template>
Expand Down Expand Up @@ -55,6 +55,7 @@
</template>

<script setup lang="ts">
import { computed } from "vue";
import { useExtendedFieldProps } from "@composables/fields";

import type { QuesoTextFieldModel, QuesoTextFieldProps } from "./types";
Expand All @@ -67,6 +68,8 @@ const props = withDefaults(defineProps<QuesoTextFieldProps>(), {
const extendedProps = useExtendedFieldProps(props);

const model = defineModel<QuesoTextFieldModel>({ required: true, default: "" });

const hasContent = computed(() => String(model.value ?? "").trim().length > 0);
</script>

<style lang="scss">
Expand Down