Skip to content

Commit

Permalink
chore: WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Hellstrand committed Nov 25, 2024
1 parent 0dc6086 commit 507e696
Show file tree
Hide file tree
Showing 14 changed files with 520 additions and 152 deletions.
47 changes: 47 additions & 0 deletions packages/ffe-datepicker-react/src/v2/CalenderWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { useImperativeHandle, useRef, useState } from 'react';

export interface CalendarWrapperProps {
children: React.ReactNode;
}

export type CalendarWrapperHandle = {
readonly open: ({ left, top }: { left: number; top: number }) => void;
readonly close: () => void;
};

export const CalendarWrapper = React.forwardRef<
CalendarWrapperHandle,
CalendarWrapperProps
>(({ children }, ref) => {
const dialogRef = useRef<HTMLDialogElement>(null);
const [style, setStyle] = useState<React.CSSProperties>();

useImperativeHandle(ref, () => ({
open: ({ top, left }) => {
setStyle({
'--top': `${top}px`,
'--left': `${left}px`,
} as React.CSSProperties);
dialogRef.current?.showModal();
},
close: () => {
dialogRef.current?.close();
},
}));

return (
<dialog
style={style}
className="ffe-datepicker__dialog"
ref={dialogRef}
onClick={event => {
const target = event.target as HTMLDialogElement;
if (target.nodeName === 'DIALOG') {
target.close();
}
}}
>
{children}
</dialog>
);
});
4 changes: 2 additions & 2 deletions packages/ffe-datepicker-react/src/v2/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ interface Props {
locale?: 'nb' | 'nn' | 'en';
}

export const DatePicker: React.FC<Props> = () => {
export const DatePicker: React.FC<Props> = ({ locale = 'nb' }) => {
return (
<DatePickerProvider>
<DatePickerProvider locale={locale}>
<DatePickerComp />
</DatePickerProvider>
);
Expand Down
117 changes: 46 additions & 71 deletions packages/ffe-datepicker-react/src/v2/DatePickerComp.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,69 @@
import React, { useContext, useRef } from 'react';
import React, { useContext, useRef, useState } from 'react';
import { DatePickerContext } from './DatePickerContext';
import { SpinnButton } from './SpinnButton';
import { PadZero } from './PadZero';
import { Button } from '../button';
import { Calendar } from './calendar';
import { CalendarWrapper, CalendarWrapperHandle } from './CalenderWrapper';

export const DatePickerComp: React.FC = () => {
/*
const dayRef = useRef<HTMLSpanElement>(null);
*/
const containerRef = useRef<HTMLDivElement>(null);
const monthRef = useRef<HTMLSpanElement>(null);
const yearRef = useRef<HTMLSpanElement>(null);
const { day, setDay, year, setYear, month, setMonth } =
const { day, setDay, year, setYear, month, setMonth, locale } =
useContext(DatePickerContext);

const handleDayChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
evt.stopPropagation();
if (/\d/.test(evt.key)) {
setDay(parseInt(evt.key), () =>
monthRef.current?.focus({ preventScroll: true }),
);
}
};

const handleMonthChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
evt.stopPropagation();
if (/\d/.test(evt.key)) {
setMonth(parseInt(evt.key), () =>
yearRef.current?.focus({ preventScroll: true }),
);
}
};

const handleYearChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
evt.stopPropagation();
if (/\d/.test(evt.key)) {
setYear(parseInt(evt.key));
}
};
const calendarRef = useRef<CalendarWrapperHandle>(null);

return (
<div className="ffe-datepicker--wrapper">
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<div
className="ffe-input-field ffe-dateinput"
/* tabIndex={0}*/
>
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
{/* <span
className="ffe-dateinput__field"
tabIndex={0}
onKeyDown={handleDayChange}
>
{typeof day === 'number'
? `${day < 10 ? '0' : ''}${day}`
: 'dd'}
</span>*/}
<div className="ffe-datepicker" ref={containerRef}>
<div className="ffe-input-field ffe-dateinput">
<SpinnButton
onChange={history => {
console.log(history);
onChange={value => {
setDay(value, () =>
monthRef.current?.focus({ preventScroll: true }),
);
}}
maxLength={2}
>
{typeof day === 'number'
? `${day < 10 ? '0' : ''}${day}`
: 'dd'}
{day ? <PadZero value={day} /> : 'dd'}
</SpinnButton>
.
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<span
className="ffe-dateinput__field"
tabIndex={0}
<SpinnButton
ref={monthRef}
onKeyDown={handleMonthChange}
onChange={value => {
setMonth(value, () =>
yearRef.current?.focus({ preventScroll: true }),
);
}}
maxLength={2}
>
{month ?? 'mm'}
</span>
{month ? <PadZero value={month} /> : 'mm'}
</SpinnButton>
.
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<span
className="ffe-dateinput__field"
tabIndex={0}
<SpinnButton
ref={yearRef}
onKeyDown={handleYearChange}
onChange={value => {
setYear(value);
}}
maxLength={4}
>
{year ?? 'yyyy'}
</span>
{year ? year : 'yyyy'}
</SpinnButton>
</div>
{/* <Button
onClick={calendarButtonClickHandler}
value={value}
locale={locale}
ref={buttonRef}
/>*/}
<Button
onClick={() => {
const rect = containerRef.current?.getBoundingClientRect();
calendarRef.current?.open({
top: rect?.bottom ?? 0,
left: rect?.left ?? 0,
});
}}
value={'TODO'}
locale={locale}
/>
<CalendarWrapper ref={calendarRef}>
<Calendar />
</CalendarWrapper>
</div>
);
};
81 changes: 48 additions & 33 deletions packages/ffe-datepicker-react/src/v2/DatePickerContext.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { createContext, useState } from 'react';
import { Locale } from './types';

interface DatePickerContextInterface {
day?: number | null;
month?: number | null;
year?: number | null;
setDay: (value: number, focusNext: () => void) => void;
setMonth: (value: number, focusNext: () => void) => void;
setYear: (value: number) => void;
setDay: (value: number[], focusNext: () => void) => void;
setMonth: (value: number[], focusNext: () => void) => void;
setYear: (value: number[]) => void;
locale: Locale;
}

export const DatePickerContext = createContext<DatePickerContextInterface>({
Expand All @@ -16,68 +18,81 @@ export const DatePickerContext = createContext<DatePickerContextInterface>({
setDay: () => null,
setMonth: () => null,
setYear: () => null,
locale: 'nb',
});

interface Props {
locale: Locale;
children: React.ReactNode;
}

const MONTHS_PER_YEAR = 12;
const MAX_MONTH = 31; // TODO noen logik her avhenge av månad?
const MAX_DAYS = 31;

export const DatePickerProvider: React.FC<Props> = ({ children }) => {
const [day, setDay] = useState<number>([]);
export const DatePickerProvider: React.FC<Props> = ({ children, locale }) => {
const [day, setDay] = useState<number>();
const [month, setMonth] = useState<number>();
const [year, setYear] = useState<number>();

const getTotal = (numbers: (number | undefined)[]) => {
const validNumbers = numbers.filter(it => typeof it === 'number');
return validNumbers
.map(
(it, index) =>
it * Math.pow(10, validNumbers.length - index - 1),
)
.reduce((acc, curr) => acc + curr, 0);
};

return (
<DatePickerContext.Provider
value={{
day,
month,
year,
setDay: (value, focusNext) => {
const next = parseInt(`${day ?? 0}${value}`);
if (next > MAX_MONTH) {
console.log('her nå', next);
setDay(value);
/* focusNext();*/
const numbers = value.slice(-2);
const [first, second] = numbers;
const total = getTotal(numbers);
if (total > MAX_DAYS) {
focusNext();
} else if (first > 3) {
setDay(total);
focusNext();
} else {
console.log(value, day, next);
setDay(next);
setDay(total);
if (second !== undefined) {
focusNext();
}
}
},
setMonth: (value, focusNext) => {
const numbers = value.slice(-2);
const [first, second] = numbers;
const total = getTotal(numbers);

/* const parsedCurrent = parseInt(day);
const parsedNext = parseInt(`${value}${parsedCurrent}`);
if (day === 'dd' || parsedNext < 10) {
setDay(`0${value}`);
} else if (value >= 4 || parsedCurrent >= 4) {
setDay(`0${value}`);
if (total > MONTHS_PER_YEAR) {
focusNext();
} else {
setDay(`${parsedNext}`);
} else if (first > 1) {
setMonth(total);
focusNext();
}*/
},
setMonth: (value, focusNext) => {
/* const current = parseInt(month);
if (
month === 'mm' ||
parseInt(`${current}${value}`) > MONTHS_PER_YEAR
) {
setMonth(`0${value}`);
} else {
setMonth(`${current}${value}`);
focusNext();
}*/
setMonth(total);
if (second !== undefined) {
focusNext();
}
}
},
setYear: value => {
setYear(getTotal(value.slice(-4)));

/* if (year === 'yyyy' || `${year}${value}`.length > 4) {
setYear(`${value}`);
} else {
setYear(`${year}${value}`);
}*/
},
locale,
}}
>
{children}
Expand Down
12 changes: 12 additions & 0 deletions packages/ffe-datepicker-react/src/v2/PadZero.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';

interface Props {
value: number;
}

export const PadZero: React.FC<Props> = ({ value }) => {
if (value < 10) {
return `0${value}`;
}
return value;
};
34 changes: 17 additions & 17 deletions packages/ffe-datepicker-react/src/v2/SpinnButton.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import React, { useState } from 'react';
import React, { useRef } from 'react';

interface Props {
onChange: (date: number) => void;
onChange: (value: number[]) => void;
children: React.ReactNode;
maxLength: number;
}

export const SpinnButton = React.forwardRef<HTMLSpanElement, Props>(
({ onChange, children }, ref) => {
const [, setHistory] = useState<string[]>([]);
({ onChange, maxLength, children }, ref) => {
const history = useRef<number[]>([]);

return (
<span
className="ffe-dateinput__field"
tabIndex={0}
onFocus={() => setHistory([])}
/* onFocus={() => dayRef.current?.focus()}*/
/* onKeyDown={handleDayChange}*/
/* ref={dayRef}*/
onFocus={() => {
history.current = [];
}}
ref={ref}
onKeyDown={evt => {
evt.stopPropagation();
if (/\d/.test(evt.key)) {
setHistory(prev => {
const newHistory = prev.concat(evt.key);
console.log(newHistory);
const [first, second] = newHistory.slice(-2);
console.log(first, second);

// onChange(newHistory);
return newHistory;
});
if (/\d/.test(evt.key)) {
history.current =
history.current.length === maxLength
? (history.current = [parseInt(evt.key)])
: history.current.concat(parseInt(evt.key));
onChange(history.current);
} else if (evt.key === 'Backspace') {
history.current = [];
onChange(history.current);
}
}}
>
Expand Down
Loading

0 comments on commit 507e696

Please sign in to comment.