Skip to content

Commit 39228da

Browse files
author
Peter Hellstrand
committed
chore: WIP
1 parent 0dc6086 commit 39228da

17 files changed

+601
-175
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,23 +0,0 @@
1-
const fs = require('fs').promises;
2-
const less = require('less');
3-
4-
/**
5-
* Takes less variables from a given file and generates a css stylesheet with
6-
* these variables as custom properties on the :root pseudo-class.
7-
*/
8-
module.exports = async inputFile => {
9-
const data = await fs.readFile(inputFile, 'utf8');
10-
const root = await less.parse(data, { filename: inputFile });
11-
12-
const propertyNames = root.rules
13-
.filter(r => r.variable)
14-
.map(n => n.name.slice(1));
15-
16-
const { css } = await less.render(
17-
`@import '${inputFile}';` +
18-
`@props: ${propertyNames.join(', ')};` +
19-
`:root, :host { each(@props, { --@{value}: @@value; }); }`,
20-
);
21-
22-
return css;
23-
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React, { useImperativeHandle, useRef, useState } from 'react';
2+
3+
export interface CalendarWrapperProps {
4+
children: React.ReactNode;
5+
}
6+
7+
export type CalendarWrapperHandle = {
8+
readonly open: ({ left, top }: { left: number; top: number }) => void;
9+
readonly close: () => void;
10+
};
11+
12+
export const CalendarWrapper = React.forwardRef<
13+
CalendarWrapperHandle,
14+
CalendarWrapperProps
15+
>(({ children }, ref) => {
16+
const dialogRef = useRef<HTMLDialogElement>(null);
17+
const [style, setStyle] = useState<React.CSSProperties>();
18+
19+
useImperativeHandle(ref, () => ({
20+
open: ({ top, left }) => {
21+
setStyle({
22+
'--top': `${top}px`,
23+
'--left': `${left}px`,
24+
} as React.CSSProperties);
25+
dialogRef.current?.showModal();
26+
},
27+
close: () => {
28+
dialogRef.current?.close();
29+
},
30+
}));
31+
32+
return (
33+
<dialog
34+
style={style}
35+
className="ffe-datepicker__dialog"
36+
ref={dialogRef}
37+
onClick={event => {
38+
const target = event.target as HTMLDialogElement;
39+
if (target.nodeName === 'DIALOG') {
40+
target.close();
41+
}
42+
}}
43+
>
44+
{children}
45+
</dialog>
46+
);
47+
});

packages/ffe-datepicker-react/src/v2/DatePicker.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ interface Props {
66
locale?: 'nb' | 'nn' | 'en';
77
}
88

9-
export const DatePicker: React.FC<Props> = () => {
9+
export const DatePicker: React.FC<Props> = ({ locale = 'nb' }) => {
1010
return (
11-
<DatePickerProvider>
11+
<DatePickerProvider locale={locale}>
1212
<DatePickerComp />
1313
</DatePickerProvider>
1414
);
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,69 @@
1-
import React, { useContext, useRef } from 'react';
1+
import React, { useContext, useRef, useState } from 'react';
22
import { DatePickerContext } from './DatePickerContext';
33
import { SpinnButton } from './SpinnButton';
4+
import { PadZero } from './PadZero';
5+
import { Button } from '../button';
6+
import { Calendar } from './calendar';
7+
import { CalendarWrapper, CalendarWrapperHandle } from './CalenderWrapper';
48

59
export const DatePickerComp: React.FC = () => {
6-
/*
7-
const dayRef = useRef<HTMLSpanElement>(null);
8-
*/
10+
const containerRef = useRef<HTMLDivElement>(null);
911
const monthRef = useRef<HTMLSpanElement>(null);
1012
const yearRef = useRef<HTMLSpanElement>(null);
11-
const { day, setDay, year, setYear, month, setMonth } =
13+
const { day, setDay, year, setYear, month, setMonth, locale } =
1214
useContext(DatePickerContext);
13-
14-
const handleDayChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
15-
evt.stopPropagation();
16-
if (/\d/.test(evt.key)) {
17-
setDay(parseInt(evt.key), () =>
18-
monthRef.current?.focus({ preventScroll: true }),
19-
);
20-
}
21-
};
22-
23-
const handleMonthChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
24-
evt.stopPropagation();
25-
if (/\d/.test(evt.key)) {
26-
setMonth(parseInt(evt.key), () =>
27-
yearRef.current?.focus({ preventScroll: true }),
28-
);
29-
}
30-
};
31-
32-
const handleYearChange = (evt: React.KeyboardEvent<HTMLSpanElement>) => {
33-
evt.stopPropagation();
34-
if (/\d/.test(evt.key)) {
35-
setYear(parseInt(evt.key));
36-
}
37-
};
15+
const calendarRef = useRef<CalendarWrapperHandle>(null);
3816

3917
return (
40-
<div className="ffe-datepicker--wrapper">
41-
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
42-
<div
43-
className="ffe-input-field ffe-dateinput"
44-
/* tabIndex={0}*/
45-
>
46-
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
47-
{/* <span
48-
className="ffe-dateinput__field"
49-
tabIndex={0}
50-
onKeyDown={handleDayChange}
51-
>
52-
{typeof day === 'number'
53-
? `${day < 10 ? '0' : ''}${day}`
54-
: 'dd'}
55-
</span>*/}
18+
<div className="ffe-datepicker" ref={containerRef}>
19+
<div className="ffe-input-field ffe-dateinput">
5620
<SpinnButton
57-
onChange={history => {
58-
console.log(history);
21+
onChange={value => {
22+
setDay(value, () =>
23+
monthRef.current?.focus({ preventScroll: true }),
24+
);
5925
}}
26+
maxLength={2}
6027
>
61-
{typeof day === 'number'
62-
? `${day < 10 ? '0' : ''}${day}`
63-
: 'dd'}
28+
{day ? <PadZero value={day} /> : 'dd'}
6429
</SpinnButton>
6530
.
66-
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
67-
<span
68-
className="ffe-dateinput__field"
69-
tabIndex={0}
31+
<SpinnButton
7032
ref={monthRef}
71-
onKeyDown={handleMonthChange}
33+
onChange={value => {
34+
setMonth(value, () =>
35+
yearRef.current?.focus({ preventScroll: true }),
36+
);
37+
}}
38+
maxLength={2}
7239
>
73-
{month ?? 'mm'}
74-
</span>
40+
{month ? <PadZero value={month} /> : 'mm'}
41+
</SpinnButton>
7542
.
76-
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
77-
<span
78-
className="ffe-dateinput__field"
79-
tabIndex={0}
43+
<SpinnButton
8044
ref={yearRef}
81-
onKeyDown={handleYearChange}
45+
onChange={value => {
46+
setYear(value);
47+
}}
48+
maxLength={4}
8249
>
83-
{year ?? 'yyyy'}
84-
</span>
50+
{year ? year : 'yyyy'}
51+
</SpinnButton>
8552
</div>
86-
{/* <Button
87-
onClick={calendarButtonClickHandler}
88-
value={value}
89-
locale={locale}
90-
ref={buttonRef}
91-
/>*/}
53+
<Button
54+
onClick={() => {
55+
const rect = containerRef.current?.getBoundingClientRect();
56+
calendarRef.current?.open({
57+
top: rect?.bottom ?? 0,
58+
left: rect?.left ?? 0,
59+
});
60+
}}
61+
value={'TODO'}
62+
locale={locale}
63+
/>
64+
<CalendarWrapper ref={calendarRef}>
65+
<Calendar />
66+
</CalendarWrapper>
9267
</div>
9368
);
9469
};

packages/ffe-datepicker-react/src/v2/DatePickerContext.tsx

+48-33
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import React, { createContext, useState } from 'react';
2+
import { Locale } from './types';
23

34
interface DatePickerContextInterface {
45
day?: number | null;
56
month?: number | null;
67
year?: number | null;
7-
setDay: (value: number, focusNext: () => void) => void;
8-
setMonth: (value: number, focusNext: () => void) => void;
9-
setYear: (value: number) => void;
8+
setDay: (value: number[], focusNext: () => void) => void;
9+
setMonth: (value: number[], focusNext: () => void) => void;
10+
setYear: (value: number[]) => void;
11+
locale: Locale;
1012
}
1113

1214
export const DatePickerContext = createContext<DatePickerContextInterface>({
@@ -16,68 +18,81 @@ export const DatePickerContext = createContext<DatePickerContextInterface>({
1618
setDay: () => null,
1719
setMonth: () => null,
1820
setYear: () => null,
21+
locale: 'nb',
1922
});
2023

2124
interface Props {
25+
locale: Locale;
2226
children: React.ReactNode;
2327
}
2428

2529
const MONTHS_PER_YEAR = 12;
26-
const MAX_MONTH = 31; // TODO noen logik her avhenge av månad?
30+
const MAX_DAYS = 31;
2731

28-
export const DatePickerProvider: React.FC<Props> = ({ children }) => {
29-
const [day, setDay] = useState<number>([]);
32+
export const DatePickerProvider: React.FC<Props> = ({ children, locale }) => {
33+
const [day, setDay] = useState<number>();
3034
const [month, setMonth] = useState<number>();
3135
const [year, setYear] = useState<number>();
3236

37+
const getTotal = (numbers: (number | undefined)[]) => {
38+
const validNumbers = numbers.filter(it => typeof it === 'number');
39+
return validNumbers
40+
.map(
41+
(it, index) =>
42+
it * Math.pow(10, validNumbers.length - index - 1),
43+
)
44+
.reduce((acc, curr) => acc + curr, 0);
45+
};
46+
3347
return (
3448
<DatePickerContext.Provider
3549
value={{
3650
day,
3751
month,
3852
year,
3953
setDay: (value, focusNext) => {
40-
const next = parseInt(`${day ?? 0}${value}`);
41-
if (next > MAX_MONTH) {
42-
console.log('her nå', next);
43-
setDay(value);
44-
/* focusNext();*/
54+
const numbers = value.slice(-2);
55+
const [first, second] = numbers;
56+
const total = getTotal(numbers);
57+
if (total > MAX_DAYS) {
58+
focusNext();
59+
} else if (first > 3) {
60+
setDay(total);
61+
focusNext();
4562
} else {
46-
console.log(value, day, next);
47-
setDay(next);
63+
setDay(total);
64+
if (second !== undefined) {
65+
focusNext();
66+
}
4867
}
68+
},
69+
setMonth: (value, focusNext) => {
70+
const numbers = value.slice(-2);
71+
const [first, second] = numbers;
72+
const total = getTotal(numbers);
4973

50-
/* const parsedCurrent = parseInt(day);
51-
const parsedNext = parseInt(`${value}${parsedCurrent}`);
52-
if (day === 'dd' || parsedNext < 10) {
53-
setDay(`0${value}`);
54-
} else if (value >= 4 || parsedCurrent >= 4) {
55-
setDay(`0${value}`);
74+
if (total > MONTHS_PER_YEAR) {
5675
focusNext();
57-
} else {
58-
setDay(`${parsedNext}`);
76+
} else if (first > 1) {
77+
setMonth(total);
5978
focusNext();
60-
}*/
61-
},
62-
setMonth: (value, focusNext) => {
63-
/* const current = parseInt(month);
64-
if (
65-
month === 'mm' ||
66-
parseInt(`${current}${value}`) > MONTHS_PER_YEAR
67-
) {
68-
setMonth(`0${value}`);
6979
} else {
70-
setMonth(`${current}${value}`);
71-
focusNext();
72-
}*/
80+
setMonth(total);
81+
if (second !== undefined) {
82+
focusNext();
83+
}
84+
}
7385
},
7486
setYear: value => {
87+
setYear(getTotal(value.slice(-4)));
88+
7589
/* if (year === 'yyyy' || `${year}${value}`.length > 4) {
7690
setYear(`${value}`);
7791
} else {
7892
setYear(`${year}${value}`);
7993
}*/
8094
},
95+
locale,
8196
}}
8297
>
8398
{children}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React from 'react';
2+
3+
interface Props {
4+
value: number;
5+
}
6+
7+
export const PadZero: React.FC<Props> = ({ value }) => {
8+
if (value < 10) {
9+
return `0${value}`;
10+
}
11+
return value;
12+
};

0 commit comments

Comments
 (0)