Skip to content

Commit

Permalink
feat: lock non editable segments
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Mar 2, 2025
1 parent 73907a0 commit 3f95b66
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
14 changes: 10 additions & 4 deletions packages/core/src/useDateTimeField/useDateTimeSegment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ export function useDateTimeSegment(_props: Reactivify<DateTimeSegmentProps>) {
const segmentEl = shallowRef<HTMLSpanElement>();
const segmentGroup = inject(DateTimeSegmentGroupKey, null);
const isDisabled = createDisabledContext(props.disabled);
const isNonEditable = () => isDisabled.value || !isEditableSegmentType(toValue(props.type));

if (!segmentGroup) {
throw new Error('DateTimeSegmentGroup is not provided');
Expand All @@ -75,6 +74,7 @@ export function useDateTimeSegment(_props: Reactivify<DateTimeSegmentProps>) {
isLast,
focusNext,
isNumeric,
isLockedByRange,
} = segmentGroup.useDateSegmentRegistration({
id,
getElem: () => segmentEl.value,
Expand All @@ -83,13 +83,19 @@ export function useDateTimeSegment(_props: Reactivify<DateTimeSegmentProps>) {

let currentInput = '';

function isNonEditable() {
return (
!isEditableSegmentType(toValue(props.type)) || isDisabled.value || toValue(props.readonly) || isLockedByRange()
);
}

const handlers = {
onFocus() {
// Reset the current input when the segment is focused
currentInput = '';
},
onBeforeinput(evt: InputEvent) {
if (toValue(props.readonly) || isDisabled.value) {
if (isNonEditable()) {
blockEvent(evt);
return;
}
Expand Down Expand Up @@ -143,7 +149,7 @@ export function useDateTimeSegment(_props: Reactivify<DateTimeSegmentProps>) {
currentInput = '';
},
onKeydown(evt: KeyboardEvent) {
if (toValue(props.readonly) || isDisabled.value) {
if (isNonEditable()) {
return;
}

Expand Down Expand Up @@ -185,7 +191,7 @@ export function useDateTimeSegment(_props: Reactivify<DateTimeSegmentProps>) {
id,
tabindex: isNonEditable() ? -1 : 0,
contenteditable: isNonEditable() ? undefined : ceValue,
'aria-disabled': isDisabled.value,
'aria-disabled': isNonEditable(),
'data-segment-type': toValue(props.type),
'aria-label': isNonEditable() ? undefined : toValue(props.type),
'aria-readonly': toValue(props.readonly) ? true : undefined,
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/useDateTimeField/useDateTimeSegmentGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useEventListener } from '../helpers/useEventListener';
import {
getSegmentTypePlaceholder,
isEditableSegmentType,
isEqualPart,
isNumericByDefault,
isOptionalSegmentType,
segmentTypeToDurationLike,
Expand Down Expand Up @@ -34,6 +35,7 @@ export interface DateTimeSegmentGroupContext {
onTouched(): void;
isLast(): boolean;
focusNext(): void;
isLockedByRange(): boolean;
};
}

Expand Down Expand Up @@ -166,6 +168,18 @@ export function useDateTimeSegmentGroup({
onValueChange(withAllPartsSet(date));
}

function isLockedByRange() {
const type = segment.getType();
const minDate = toValue(min);
const maxDate = toValue(max);
// Can't be locked when either bound is open.
if (!minDate || !maxDate) {
return false;
}

return isEqualPart(minDate, maxDate, type);
}

function getMetadata() {
const type = segment.getType();
const date = toValue(temporalValue);
Expand Down Expand Up @@ -252,6 +266,7 @@ export function useDateTimeSegmentGroup({
isLast,
focusNext,
isNumeric,
isLockedByRange,
};
}

Expand Down

0 comments on commit 3f95b66

Please sign in to comment.