Skip to content

Commit

Permalink
feature(#1005): provide a click handler for click on right icon for K…
Browse files Browse the repository at this point in the history
…tField

This is needed for KtPassword to reveal/hide passwords to user
  • Loading branch information
RueRivoli committed Dec 3, 2024
1 parent c961866 commit a1191a0
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 8 deletions.
27 changes: 25 additions & 2 deletions packages/documentation/pages/usage/components/form-fields.vue
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,18 @@
:minimum="1"
:step="1"
/>

<KtFieldToggle
v-if="
componentDefinition.additionalProps.includes(
'showVisibilityToggle',
)
"
formKey="showVisibilityToggle"
helpText="For Password: display an eye icon to reveal/hide the content"
isOptional
label="Show visibility toggle"
type="switch"
/>
<h4>Additional Slots</h4>
<KtFieldText
v-if="
Expand Down Expand Up @@ -901,7 +912,7 @@ const components: Array<{
supports: KtFieldNumber.meta.supports,
},
{
additionalProps: [],
additionalProps: ['showVisibilityToggle'],
formKey: 'textValue',
name: 'KtFieldPassword',
supports: KtFieldPassword.meta.supports,
Expand Down Expand Up @@ -1210,6 +1221,7 @@ export default defineComponent({
rows: Kotti.FieldNumber.Value
shortcuts: Kotti.FieldToggleGroup.Value
showHeaderSideSlot: ComponentValue['showHeaderSideSlot']
showVisibilityToggle: boolean
toggleType: 'checkbox' | 'switch'
}
autoComplete: Kotti.FieldSingleSelect.Value
Expand Down Expand Up @@ -1277,6 +1289,7 @@ export default defineComponent({
rows: null,
shortcuts: null,
showHeaderSideSlot: false,
showVisibilityToggle: false,
toggleType: 'checkbox',
},
autoComplete: Kotti.Field.AutoComplete.OFF,
Expand Down Expand Up @@ -1394,6 +1407,16 @@ export default defineComponent({
autoSize: settings.value.additionalProps.autoSize,
})
}
if (
componentDefinition.value.additionalProps.includes(
'showVisibilityToggle',
)
) {
Object.assign(additionalProps, {
showVisibilityToggle:
settings.value.additionalProps.showVisibilityToggle,
})
}
if (componentDefinition.value.additionalProps.includes('rows'))
Object.assign(additionalProps, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
v-bind="{ field }"
:getEmptyValue="() => null"
:helpTextSlot="$slots.helpText"
@visibilityChange="handleVisibilityChange"
>
<input v-bind="inputProps" @input="onInput" />
</KtField>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue'
import { computed, defineComponent, ref } from 'vue'
import type { InputHTMLAttributes } from 'vue/types/jsx'
import { KtField } from '../kotti-field'
Expand All @@ -31,9 +32,8 @@ export default defineComponent({
props,
supports: KOTTI_FIELD_PASSWORD_SUPPORTS,
})
const fieldType = ref('password')
const { forceUpdate, forceUpdateKey } = useForceUpdate()
return {
field,
inputProps: computed(
Expand All @@ -47,7 +47,7 @@ export default defineComponent({
forceUpdateKey: forceUpdateKey.value,
placeholder: props.placeholder ?? undefined,
size: 1,
type: 'password',
type: fieldType.value,
value: field.currentValue ?? '',
}),
),
Expand All @@ -57,6 +57,10 @@ export default defineComponent({
forceUpdate()
},
handleVisibilityChange: () => {
const isValueHidden = fieldType.value === 'password'
fieldType.value = isValueHidden ? 'text' : 'password'
},
}
},
})
Expand Down
1 change: 1 addition & 0 deletions packages/kotti-ui/source/kotti-field-password/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export module KottiFieldPassword {
.extend({
autoComplete: createLooseZodEnumSchema(AutoComplete),
placeholder: z.string().nullable().default(null),
showVisibilityToggle: z.boolean().default(false),
value: valueSchema.default(null),
})

Expand Down
22 changes: 20 additions & 2 deletions packages/kotti-ui/source/kotti-field/KtField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@
<i class="yoco" v-text="Yoco.Icon.CLOSE" />
</div>
</slot>
<div
v-if="field.showVisibilityToggle"
:class="iconClasses('input-container', ['right', 'interactive'])"
@click.stop="handleVisibilityChange"
>
<i
v-if="valueVisibility"
class="yoco"
v-text="Yoco.Icon.EYE_SLASHED"
/>
<i v-else class="yoco" v-text="Yoco.Icon.EYE" />
</div>
<div
v-if="field.rightIcon"
:class="iconClasses('input-container', ['right'])"
Expand Down Expand Up @@ -149,13 +161,14 @@ export default defineComponent({
isRange: { default: false, type: Boolean },
useFieldset: { default: false, type: Boolean },
},
emits: ['click', 'mousedown'],
setup(props) {
emits: ['click', 'mousedown', 'visibilityChange'],
setup(props, { emit }) {
const inputId = computed(() =>
props.isRange
? `${props.field.inputProps.id}-start`
: props.field.inputProps.id,
)
const valueVisibility = ref(false)
const validationType = computed(() => props.field.validation.type)
const showValidation = computed(
() => !(props.field.hideValidation || validationType.value === 'empty'),
Expand Down Expand Up @@ -191,6 +204,10 @@ export default defineComponent({
props.field.setValue(props.getEmptyValue())
focusInput()
},
handleVisibilityChange: () => {
if (props.field.showVisibilityToggle) emit('visibilityChange')
valueVisibility.value = !valueVisibility.value
},
hasHelpText: computed(
() => props.helpTextSlot.length > 0 || props.field.helpText !== null,
),
Expand Down Expand Up @@ -245,6 +262,7 @@ export default defineComponent({
warning: Yoco.Icon.CIRCLE_ATTENTION,
})[validationType.value],
),
valueVisibility,
wrapperClasses: computed(() => {
const classes = ['kt-field__wrapper']
Expand Down
3 changes: 3 additions & 0 deletions packages/kotti-ui/source/kotti-field/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const useDecoration = <DATA_TYPE>({
leftIcon: computed(() => (supports.decoration ? props.leftIcon : null)),
prefix: computed(() => (supports.decoration ? props.prefix : null)),
rightIcon: computed(() => (supports.decoration ? props.rightIcon : null)),
showVisibilityToggle: computed(() =>
supports.decoration ? props.showVisibilityToggle : false,
),
suffix: computed(() => (supports.decoration ? props.suffix : null)),
}
}
Expand Down
9 changes: 9 additions & 0 deletions packages/kotti-ui/source/kotti-field/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export module KottiField {
| 'prefix'
| 'rightIcon'
| 'size'
| 'showVisibilityToggle'

Check warning on line 83 in packages/kotti-ui/source/kotti-field/types.ts

View workflow job for this annotation

GitHub Actions / eslint

Expected "'showVisibilityToggle'" to come before "'size'"
| 'suffix'
> & {
currentValue: DATA_TYPE
Expand Down Expand Up @@ -134,6 +135,7 @@ export module KottiField {
leftIcon: yocoIconSchema.nullable().default(null),
prefix: z.string().nullable().default(null),
rightIcon: yocoIconSchema.nullable().default(null),
showVisibilityToggle: z.boolean().default(false),
suffix: z.string().nullable().default(null),
tabIndex: z.number().default(0),
})
Expand Down Expand Up @@ -168,6 +170,7 @@ export module KottiField {
* Prevents the validation (e.g. color, text) from being shown
*/
hideValidation: z.boolean().default(false),
showVisibilityToggle: z.boolean().default(false),

/**
* Defines the size of the field which influences child styles
Expand Down Expand Up @@ -239,6 +242,12 @@ export module KottiField {

rightIcon: z.never(),

/**
* Show some an eye icon on the right side of the field to hide/show the field content
*
* This is false by default and is meant to be used for KtFieldPassword
*/
showVisibilityToggle: z.boolean().default(false),
/**
* Show some string before the field
*
Expand Down
1 change: 1 addition & 0 deletions packages/kotti-ui/source/kotti-form/KtForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export default defineComponent({
hideValidation: props.hideValidation,
isDisabled: props.isDisabled,
isLoading: props.isLoading,
showVisibilityToggle: props.showVisibilityToggle,
size: props.size,
})),
formPath: computed(() => [props.formId]),
Expand Down
1 change: 1 addition & 0 deletions packages/kotti-ui/source/test-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const getMockContext = ({ validators = {}, values = {} } = {}): Pick<
hideValidation: false,
isDisabled: false,
isLoading: false,
showVisibilityToggle: true,
size: KottiField.Size.MEDIUM,
},
},
Expand Down
1 change: 1 addition & 0 deletions packages/yoco/source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export module Yoco {
EMAIL = 'email',
EXIT_FULLSCREEN = 'exit_fullscreen',
EYE = 'eye',
EYE_SLASHED = 'eye_slashed',
FILE = 'file',
FILTER = 'filter',
FIX_RIGHT = 'fix_right',
Expand Down
8 changes: 8 additions & 0 deletions packages/yoco/svg/eye_slashed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a1191a0

Please sign in to comment.