|
2 | 2 | import type { HTMLInputAttributes } from 'svelte/elements'; |
3 | 3 | import { type FullFieldConfig, type ValidationResult } from '$lib/components/Form/FieldsConfig'; |
4 | 4 | import FieldHint from '../FieldHint.svelte'; |
5 | | - import { getAccessToken } from '../../../context/TokenContext.svelte'; |
6 | | - import { getHighestRole } from '../../../util'; |
| 5 | + import { getAccessToken } from '$lib/context/TokenContext.svelte'; |
| 6 | + import { getHighestRole } from '$lib/util'; |
| 7 | + import { onMount } from 'svelte'; |
7 | 8 |
|
8 | 9 | type InputProps = { |
9 | 10 | value?: string; |
|
26 | 27 | ...restProps |
27 | 28 | }: InputProps = $props(); |
28 | 29 |
|
| 30 | + let inputElement: HTMLInputElement; |
| 31 | + let isActive = $state(false); |
| 32 | +
|
29 | 33 | const token = $derived(getAccessToken()); |
30 | 34 | const highestRole = $derived(getHighestRole(token)); |
31 | 35 |
|
| 36 | + // This special handling is needed as the input[type="date"] is not automatically |
| 37 | + // focused when the datepicker is opened. |
| 38 | + onMount(() => { |
| 39 | + const handleFocus = () => (isActive = true); |
| 40 | + const handleBlur = () => (isActive = false); |
| 41 | +
|
| 42 | + inputElement.addEventListener('focus', handleFocus); |
| 43 | + inputElement.addEventListener('blur', handleBlur); |
| 44 | +
|
| 45 | + return () => { |
| 46 | + inputElement.removeEventListener('focus', handleFocus); |
| 47 | + inputElement.removeEventListener('blur', handleBlur); |
| 48 | + }; |
| 49 | + }); |
| 50 | +
|
32 | 51 | let invalid = $derived.by(() => { |
33 | 52 | if (!fieldConfig) return false; |
34 | 53 | const { editingRoles } = fieldConfig; |
|
42 | 61 | <fieldset class={['date-input', wrapperClass, invalid && 'invalid']}> |
43 | 62 | <legend>{label}</legend> |
44 | 63 | <input |
| 64 | + class={[isActive && 'active']} |
| 65 | + bind:this={inputElement} |
45 | 66 | type="date" |
46 | 67 | id={key} |
47 | 68 | name={key} |
|
78 | 99 | margin-top: 0.5em; |
79 | 100 | outline-width: 0; |
80 | 101 | align-self: flex-start; |
| 102 | +
|
| 103 | + &.active, |
| 104 | + &:focus, |
| 105 | + &:focus-visible { |
| 106 | + border-color: var(--mdc-theme-primary); |
| 107 | + outline: 1px solid var(--mdc-theme-primary); |
| 108 | + } |
81 | 109 | } |
82 | 110 |
|
83 | 111 | .field-footer { |
|
0 commit comments