@a-type/ui 3.0.31 → 3.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/datePicker/Calendar.d.ts +11 -0
- package/dist/cjs/components/datePicker/Calendar.js +37 -0
- package/dist/cjs/components/datePicker/Calendar.js.map +1 -0
- package/dist/cjs/components/datePicker/DatePicker.d.ts +42 -13
- package/dist/cjs/components/datePicker/DatePicker.js +31 -71
- package/dist/cjs/components/datePicker/DatePicker.js.map +1 -1
- package/dist/cjs/components/datePicker/DatePicker.stories.d.ts +36 -1
- package/dist/cjs/components/datePicker/DatePicker.stories.js +18 -2
- package/dist/cjs/components/datePicker/DatePicker.stories.js.map +1 -1
- package/dist/cjs/components/datePicker/DateRangePicker.d.ts +55 -0
- package/dist/cjs/components/datePicker/DateRangePicker.js +89 -0
- package/dist/cjs/components/datePicker/DateRangePicker.js.map +1 -0
- package/dist/cjs/components/datePicker/index.d.ts +2 -0
- package/dist/cjs/components/datePicker/index.js +1 -0
- package/dist/cjs/components/datePicker/index.js.map +1 -1
- package/dist/cjs/components/forms/EmojiField.js +5 -1
- package/dist/cjs/components/forms/EmojiField.js.map +1 -1
- package/dist/cjs/uno/preflights/fonts.d.ts +2 -2
- package/dist/cjs/uno/preflights/fonts.js +1 -3
- package/dist/cjs/uno/preflights/fonts.js.map +1 -1
- package/dist/css/main.css +1 -1
- package/dist/esm/components/datePicker/Calendar.d.ts +11 -0
- package/dist/esm/components/datePicker/Calendar.js +32 -0
- package/dist/esm/components/datePicker/Calendar.js.map +1 -0
- package/dist/esm/components/datePicker/DatePicker.d.ts +42 -13
- package/dist/esm/components/datePicker/DatePicker.js +32 -68
- package/dist/esm/components/datePicker/DatePicker.js.map +1 -1
- package/dist/esm/components/datePicker/DatePicker.stories.d.ts +36 -1
- package/dist/esm/components/datePicker/DatePicker.stories.js +19 -3
- package/dist/esm/components/datePicker/DatePicker.stories.js.map +1 -1
- package/dist/esm/components/datePicker/DateRangePicker.d.ts +55 -0
- package/dist/esm/components/datePicker/DateRangePicker.js +83 -0
- package/dist/esm/components/datePicker/DateRangePicker.js.map +1 -0
- package/dist/esm/components/datePicker/index.d.ts +2 -0
- package/dist/esm/components/datePicker/index.js +1 -0
- package/dist/esm/components/datePicker/index.js.map +1 -1
- package/dist/esm/components/forms/EmojiField.js +5 -1
- package/dist/esm/components/forms/EmojiField.js.map +1 -1
- package/dist/esm/uno/preflights/fonts.d.ts +2 -2
- package/dist/esm/uno/preflights/fonts.js +1 -3
- package/dist/esm/uno/preflights/fonts.js.map +1 -1
- package/package.json +1 -1
- package/src/components/datePicker/Calendar.tsx +83 -0
- package/src/components/datePicker/DatePicker.stories.tsx +37 -2
- package/src/components/datePicker/DatePicker.tsx +77 -222
- package/src/components/datePicker/DateRangePicker.tsx +161 -0
- package/src/components/datePicker/index.ts +2 -0
- package/src/components/forms/EmojiField.tsx +5 -1
- package/src/uno/preflights/fonts.ts +4 -7
|
@@ -13,6 +13,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
import clsx from 'clsx';
|
|
15
15
|
import { useField } from 'formik';
|
|
16
|
+
import { useState } from 'react';
|
|
16
17
|
import { useIdOrGenerated } from '../../hooks/useIdOrGenerated.js';
|
|
17
18
|
import { Box } from '../box/Box.js';
|
|
18
19
|
import { Button } from '../button/Button.js';
|
|
@@ -24,12 +25,15 @@ export function EmojiField(_a) {
|
|
|
24
25
|
var { name, label, className, required, id: providedId } = _a, rest = __rest(_a, ["name", "label", "className", "required", "id"]);
|
|
25
26
|
const [props, _, tools] = useField({ name });
|
|
26
27
|
const id = useIdOrGenerated(providedId);
|
|
27
|
-
|
|
28
|
+
const [open, setOpen] = useState(false);
|
|
29
|
+
return (_jsxs(Box, { gap: "sm", className: className, children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(Popover.Trigger, { asChild: true, children: _jsx(Button, Object.assign({ id: id, "aria-label": "Select emoji", size: "small", className: clsx('p-0 transition-color', className) }, rest, { children: _jsx(Button.Icon, { className: "text-[19px] w-touch h-touch flex items-center justify-center", children: props.value || _jsx(Icon, { name: "smile" }) }) })) }), _jsx(Popover.Content, { children: _jsx(EmojiPicker, { onValueChange: (v) => {
|
|
28
30
|
tools.setValue(v);
|
|
31
|
+
setOpen(false);
|
|
29
32
|
}, onClear: required
|
|
30
33
|
? undefined
|
|
31
34
|
: () => {
|
|
32
35
|
tools.setValue('');
|
|
36
|
+
setOpen(false);
|
|
33
37
|
}, id: id }) })] }), label && (_jsx(HorizontalFieldLabel, { htmlFor: id, children: label }))] }));
|
|
34
38
|
}
|
|
35
39
|
//# sourceMappingURL=EmojiField.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiField.js","sourceRoot":"","sources":["../../../../src/components/forms/EmojiField.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAQvD,MAAM,UAAU,UAAU,CAAC,EAOT;QAPS,EAC1B,IAAI,EACJ,KAAK,EACL,SAAS,EACT,QAAQ,EACR,EAAE,EAAE,UAAU,OAEG,EADd,IAAI,cANmB,gDAO1B,CADO;IAEP,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACxC,OAAO,CACN,MAAC,GAAG,IAAC,GAAG,EAAC,IAAI,EAAC,SAAS,EAAE,SAAS,aACjC,MAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"EmojiField.js","sourceRoot":"","sources":["../../../../src/components/forms/EmojiField.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAQvD,MAAM,UAAU,UAAU,CAAC,EAOT;QAPS,EAC1B,IAAI,EACJ,KAAK,EACL,SAAS,EACT,QAAQ,EACR,EAAE,EAAE,UAAU,OAEG,EADd,IAAI,cANmB,gDAO1B,CADO;IAEP,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,CACN,MAAC,GAAG,IAAC,GAAG,EAAC,IAAI,EAAC,SAAS,EAAE,SAAS,aACjC,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACzC,KAAC,OAAO,CAAC,OAAO,IAAC,OAAO,kBACvB,KAAC,MAAM,kBACN,EAAE,EAAE,EAAE,gBACK,cAAc,EACzB,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAC,IAC9C,IAAI,cAER,KAAC,MAAM,CAAC,IAAI,IAAC,SAAS,EAAC,8DAA8D,YACnF,KAAK,CAAC,KAAK,IAAI,KAAC,IAAI,IAAC,IAAI,EAAC,OAAO,GAAG,GACxB,IACN,GACQ,EAClB,KAAC,OAAO,CAAC,OAAO,cACf,KAAC,WAAW,IACX,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;gCACpB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gCAClB,OAAO,CAAC,KAAK,CAAC,CAAC;4BAChB,CAAC,EACD,OAAO,EACN,QAAQ;gCACP,CAAC,CAAC,SAAS;gCACX,CAAC,CAAC,GAAG,EAAE;oCACL,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;oCACnB,OAAO,CAAC,KAAK,CAAC,CAAC;gCACf,CAAC,EAEL,EAAE,EAAE,EAAE,GACL,GACe,IACT,EACT,KAAK,IAAI,CACT,KAAC,oBAAoB,IAAC,OAAO,EAAE,EAAE,YAAG,KAAK,GAAwB,CACjE,IACI,CACN,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export interface FontsPreflightOptions {
|
|
2
|
-
interFontLocation
|
|
2
|
+
interFontLocation?: string;
|
|
3
3
|
}
|
|
4
|
-
export declare const fontsPreflight: ({ interFontLocation }?: FontsPreflightOptions) => import("unocss").Preflight<object>;
|
|
4
|
+
export declare const fontsPreflight: ({ interFontLocation, }?: FontsPreflightOptions) => import("unocss").Preflight<object>;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// @unocss-include
|
|
2
2
|
import { preflight } from './_util.js';
|
|
3
|
-
export const fontsPreflight = ({ interFontLocation } = {
|
|
4
|
-
interFontLocation: 'https://resources.biscuits.club/fonts/Inter-VariableFont_slnt,wght.ttf',
|
|
5
|
-
}) => preflight({
|
|
3
|
+
export const fontsPreflight = ({ interFontLocation = 'https://resources.biscuits.club/fonts/Inter-VariableFont_slnt,wght.ttf', } = {}) => preflight({
|
|
6
4
|
getCSS: () => `
|
|
7
5
|
@font-face {
|
|
8
6
|
font-family: "Inter";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../../../src/uno/preflights/fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,MAAM,CAAC,MAAM,cAAc,GAAG,
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../../../src/uno/preflights/fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMvC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC9B,iBAAiB,GAAG,wEAAwE,MAClE,EAAE,EAAE,EAAE,CAChC,SAAS,CAAC;IACT,MAAM,EAAE,GAAG,EAAE,CAAC;;;eAGD,iBAAiB;;;;;EAK9B;CACA,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CalendarDay as BaseCalendarDay,
|
|
3
|
+
CalendarDays,
|
|
4
|
+
CalendarDaysProps,
|
|
5
|
+
} from 'calendar-blocks';
|
|
6
|
+
import { withClassName } from '../../hooks.js';
|
|
7
|
+
import { Button } from '../button/index.js';
|
|
8
|
+
|
|
9
|
+
export const MonthRow = withClassName(
|
|
10
|
+
'div',
|
|
11
|
+
'flex flex-row justify-between items-center w-full',
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
export const MonthLabel = withClassName(
|
|
15
|
+
'span',
|
|
16
|
+
'text-sm font-bold min-w-0 overflow-hidden text-center text-ellipsis',
|
|
17
|
+
'self-center',
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const MonthButton = withClassName(Button, 'self-center');
|
|
21
|
+
|
|
22
|
+
export const CalendarGridRoot = withClassName(
|
|
23
|
+
'div',
|
|
24
|
+
'grid grid-cols-[repeat(7,var(--day-size,32px))] [grid-auto-rows:var(--day-size,32px)]',
|
|
25
|
+
'height-[calc(var(--day-size,32px)*7)] rounded overflow-hidden p-2',
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
export const DayLabel = withClassName(
|
|
29
|
+
'div',
|
|
30
|
+
'flex items-center justify-center text-sm color-gray-dark',
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const DayLabels = () => (
|
|
34
|
+
<>
|
|
35
|
+
<DayLabel>S</DayLabel>
|
|
36
|
+
<DayLabel>M</DayLabel>
|
|
37
|
+
<DayLabel>T</DayLabel>
|
|
38
|
+
<DayLabel>W</DayLabel>
|
|
39
|
+
<DayLabel>T</DayLabel>
|
|
40
|
+
<DayLabel>F</DayLabel>
|
|
41
|
+
<DayLabel>S</DayLabel>
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
export function CalendarGrid({
|
|
46
|
+
className,
|
|
47
|
+
...props
|
|
48
|
+
}: CalendarDaysProps & { className?: string }) {
|
|
49
|
+
return (
|
|
50
|
+
<CalendarGridRoot className={className}>
|
|
51
|
+
<DayLabels />
|
|
52
|
+
<CalendarDays {...props} />
|
|
53
|
+
</CalendarGridRoot>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const CalendarDay = withClassName(
|
|
58
|
+
BaseCalendarDay,
|
|
59
|
+
'border border-solid border-transparent bg-white mr--1px mb--1px relative color-black',
|
|
60
|
+
'flex items-center justify-center transition cursor-pointer',
|
|
61
|
+
'[&[data-highlighted]]:(z-1 ring-2 ring-accent)',
|
|
62
|
+
'hover:(z-1 ring-2 ring-accent)',
|
|
63
|
+
'active:(bg-main-light rounded)',
|
|
64
|
+
'[&[data-selected]]:(bg-main z-2 rounded)',
|
|
65
|
+
'[&[data-in-range]]:(bg-main-light rounded-none z-1)',
|
|
66
|
+
'[&[data-range-start]]:(bg-main rounded-l rounded-r-none z-1)',
|
|
67
|
+
'[&[data-range-end]]:(bg-main rounded-r rounded-l-none z-1)',
|
|
68
|
+
'disabled:(opacity-50 cursor-default)',
|
|
69
|
+
// today dot
|
|
70
|
+
"[&[data-today]]:before:(content-[''] absolute left-[1px] top-[1px] w-[6px] h-[6px] rounded-lg bg-attention border-1 border-solid border-black)",
|
|
71
|
+
// calendar edges
|
|
72
|
+
'[&[data-top-edge]]:(border-t-gray)',
|
|
73
|
+
'[&[data-bottom-edge]]:(border-b-gray)',
|
|
74
|
+
'[&[data-first-column]]:(border-l-gray)',
|
|
75
|
+
'[&[data-last-column]]:(border-r-gray)',
|
|
76
|
+
'[&[data-day-first]]:(border-l-gray rounded-tl)',
|
|
77
|
+
'[&[data-day-last]]:(border-r-gray rounded-br)',
|
|
78
|
+
'[&[data-first-column][data-bottom-edge]]:rounded-bl',
|
|
79
|
+
'[&[data-last-column][data-bottom-edge]]:rounded-br',
|
|
80
|
+
'[&[data-first-column][data-top-edge]]:rounded-tl',
|
|
81
|
+
'[&[data-last-column][data-top-edge]]:rounded-tr',
|
|
82
|
+
'[&[data-different-month]]:[visibility:hidden]',
|
|
83
|
+
);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { CalendarDayValue } from 'calendar-blocks';
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Spinner } from '../spinner/Spinner.js';
|
|
5
|
+
import { DatePicker } from './DatePicker.js';
|
|
6
|
+
import { DateRangePicker } from './DateRangePicker.js';
|
|
4
7
|
|
|
5
8
|
const meta = {
|
|
6
9
|
title: 'Components/DatePicker',
|
|
@@ -31,3 +34,35 @@ export const Range: Story = {
|
|
|
31
34
|
return <DateRangePicker value={value} onChange={setValue} />;
|
|
32
35
|
},
|
|
33
36
|
};
|
|
37
|
+
|
|
38
|
+
export const CustomComposition: Story = {
|
|
39
|
+
render() {
|
|
40
|
+
const [value, setValue] = useState<Date | null>(null);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<DatePicker.Root value={value} onChange={setValue}>
|
|
44
|
+
<DatePicker.MonthControls />
|
|
45
|
+
<DatePicker.CalendarGrid>
|
|
46
|
+
{(value) => <FakeLoadingDay value={value} key={value.key} />}
|
|
47
|
+
</DatePicker.CalendarGrid>
|
|
48
|
+
</DatePicker.Root>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function FakeLoadingDay({ value }: { value: CalendarDayValue }) {
|
|
54
|
+
const [loading, setLoading] = useState(true);
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const timeout = setTimeout(
|
|
57
|
+
() => setLoading(false),
|
|
58
|
+
Math.random() * 2000 + 500,
|
|
59
|
+
);
|
|
60
|
+
return () => clearTimeout(timeout);
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<DatePicker.CalendarDay value={value}>
|
|
65
|
+
{loading ? <Spinner size={10} /> : value.date.getDate()}
|
|
66
|
+
</DatePicker.CalendarDay>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -1,72 +1,76 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
CalendarDays,
|
|
5
|
-
} from 'calendar-blocks';
|
|
6
|
-
import classNames from 'clsx';
|
|
7
|
-
import { useCallback, useState } from 'react';
|
|
8
|
-
import { withClassName } from '../../hooks.js';
|
|
1
|
+
import { Calendar, CalendarDays, useCalendarContext } from 'calendar-blocks';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { ReactNode, useState } from 'react';
|
|
9
4
|
import { PaletteName } from '../../uno/index.js';
|
|
10
|
-
import { Button } from '../button/index.js';
|
|
11
5
|
import { Icon } from '../icon/index.js';
|
|
6
|
+
import {
|
|
7
|
+
CalendarDay,
|
|
8
|
+
CalendarGrid,
|
|
9
|
+
DayLabels,
|
|
10
|
+
MonthButton,
|
|
11
|
+
MonthLabel,
|
|
12
|
+
MonthRow,
|
|
13
|
+
} from './Calendar.js';
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
function DatePickerMonthControls({}: {}) {
|
|
16
|
+
const { setDisplayInfo, month, year } = useCalendarContext();
|
|
17
|
+
const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
|
|
18
|
+
month: 'long',
|
|
19
|
+
year: 'numeric',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<MonthRow>
|
|
24
|
+
<MonthButton
|
|
25
|
+
emphasis="ghost"
|
|
26
|
+
onClick={() =>
|
|
27
|
+
setDisplayInfo({
|
|
28
|
+
month: month - 1,
|
|
29
|
+
year: year,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<Icon name="arrowLeft" />
|
|
34
|
+
</MonthButton>
|
|
35
|
+
<MonthLabel>{monthLabel}</MonthLabel>
|
|
36
|
+
<MonthButton
|
|
37
|
+
emphasis="ghost"
|
|
38
|
+
onClick={() =>
|
|
39
|
+
setDisplayInfo({
|
|
40
|
+
month: month + 1,
|
|
41
|
+
year: year,
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
>
|
|
45
|
+
<Icon name="arrowRight" />
|
|
46
|
+
</MonthButton>
|
|
47
|
+
</MonthRow>
|
|
48
|
+
);
|
|
18
49
|
}
|
|
19
50
|
|
|
20
|
-
|
|
21
|
-
value,
|
|
22
|
-
onChange,
|
|
51
|
+
function DatePickerRoot({
|
|
23
52
|
className,
|
|
24
53
|
color,
|
|
54
|
+
value,
|
|
55
|
+
onChange,
|
|
56
|
+
children,
|
|
25
57
|
...rest
|
|
26
|
-
}: DatePickerProps
|
|
58
|
+
}: DatePickerProps & {
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
}) {
|
|
27
61
|
const [{ month, year }, setDisplay] = useState(() => ({
|
|
28
62
|
month: new Date().getMonth(),
|
|
29
63
|
year: new Date().getFullYear(),
|
|
30
64
|
}));
|
|
31
|
-
const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
|
|
32
|
-
month: 'long',
|
|
33
|
-
year: 'numeric',
|
|
34
|
-
});
|
|
35
65
|
|
|
36
66
|
return (
|
|
37
67
|
<div
|
|
38
|
-
className={
|
|
68
|
+
className={clsx(
|
|
39
69
|
color && `palette-${color}`,
|
|
40
70
|
'layer-components:(flex flex-col items-center justify-center w-[calc(var(--day-size,32px)*7)])',
|
|
41
|
-
className,
|
|
42
71
|
)}
|
|
43
72
|
{...rest}
|
|
44
73
|
>
|
|
45
|
-
<MonthRow>
|
|
46
|
-
<MonthButton
|
|
47
|
-
emphasis="ghost"
|
|
48
|
-
onClick={() =>
|
|
49
|
-
setDisplay((cur) => ({
|
|
50
|
-
month: cur.month - 1,
|
|
51
|
-
year: cur.year,
|
|
52
|
-
}))
|
|
53
|
-
}
|
|
54
|
-
>
|
|
55
|
-
<Icon name="arrowLeft" />
|
|
56
|
-
</MonthButton>
|
|
57
|
-
<MonthLabel>{monthLabel}</MonthLabel>
|
|
58
|
-
<MonthButton
|
|
59
|
-
emphasis="ghost"
|
|
60
|
-
onClick={() =>
|
|
61
|
-
setDisplay((cur) => ({
|
|
62
|
-
month: cur.month + 1,
|
|
63
|
-
year: cur.year,
|
|
64
|
-
}))
|
|
65
|
-
}
|
|
66
|
-
>
|
|
67
|
-
<Icon name="arrowRight" />
|
|
68
|
-
</MonthButton>
|
|
69
|
-
</MonthRow>
|
|
70
74
|
<Calendar
|
|
71
75
|
displayMonth={month}
|
|
72
76
|
displayYear={year}
|
|
@@ -74,188 +78,39 @@ export function DatePicker({
|
|
|
74
78
|
onChange={onChange}
|
|
75
79
|
onDisplayChange={setDisplay}
|
|
76
80
|
>
|
|
77
|
-
|
|
78
|
-
<DayLabels />
|
|
79
|
-
<CalendarDays>
|
|
80
|
-
{(value) => <CalendarDay value={value} key={value.key} />}
|
|
81
|
-
</CalendarDays>
|
|
82
|
-
</CalendarGrid>
|
|
81
|
+
{children}
|
|
83
82
|
</Calendar>
|
|
84
83
|
</div>
|
|
85
84
|
);
|
|
86
85
|
}
|
|
87
86
|
|
|
88
|
-
export interface
|
|
89
|
-
value:
|
|
90
|
-
onChange: (
|
|
87
|
+
export interface DatePickerProps {
|
|
88
|
+
value: Date | null;
|
|
89
|
+
onChange: (date: Date | null) => void;
|
|
91
90
|
className?: string;
|
|
91
|
+
color?: PaletteName;
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
value,
|
|
96
|
-
onChange,
|
|
97
|
-
className,
|
|
98
|
-
}: DateRangePickerProps) {
|
|
99
|
-
const [{ month, year }, setDisplay] = useState(() => ({
|
|
100
|
-
month: new Date().getMonth(),
|
|
101
|
-
year: new Date().getFullYear(),
|
|
102
|
-
}));
|
|
103
|
-
const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
|
|
104
|
-
month: 'long',
|
|
105
|
-
year: 'numeric',
|
|
106
|
-
});
|
|
107
|
-
const nextMonth = new Date(year, month + 1);
|
|
108
|
-
const nextMonthLabel = nextMonth.toLocaleDateString('en-US', {
|
|
109
|
-
month: 'long',
|
|
110
|
-
year: 'numeric',
|
|
111
|
-
});
|
|
112
|
-
const onDisplayChange = useCallback(
|
|
113
|
-
({ month: newMonth, year: newYear }: { month: number; year: number }) => {
|
|
114
|
-
/**
|
|
115
|
-
* Important UX consideration:
|
|
116
|
-
*
|
|
117
|
-
* since we are displaying 2 months at once, we don't
|
|
118
|
-
* always want to change our view if the user's cursor
|
|
119
|
-
* date moves from one month to another. Specifically,
|
|
120
|
-
* if they move from the first visible month to the
|
|
121
|
-
* second visible month, we don't need to change the view,
|
|
122
|
-
* since they are still within the visible range.
|
|
123
|
-
* So, we write logic to ignore that case!
|
|
124
|
-
*/
|
|
125
|
-
if (newMonth === month + 1 && newYear === year) {
|
|
126
|
-
return; // ignore movement from the first to the second frame
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
setDisplay({
|
|
130
|
-
month: newMonth,
|
|
131
|
-
year: newYear,
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
[month, year],
|
|
135
|
-
);
|
|
136
|
-
|
|
94
|
+
function DatePickerDefault(props: DatePickerProps) {
|
|
137
95
|
return (
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
className={classNames('flex justify-center', className)}
|
|
145
|
-
>
|
|
146
|
-
<RangeLayout>
|
|
147
|
-
<MonthButton
|
|
148
|
-
emphasis="ghost"
|
|
149
|
-
className="[grid-area:prevMonth]"
|
|
150
|
-
onClick={() =>
|
|
151
|
-
setDisplay((cur) => ({
|
|
152
|
-
month: cur.month - 1,
|
|
153
|
-
year: cur.year,
|
|
154
|
-
}))
|
|
155
|
-
}
|
|
156
|
-
>
|
|
157
|
-
<Icon name="arrowLeft" />
|
|
158
|
-
</MonthButton>
|
|
159
|
-
<MonthLabel className="[grid-area:leftMonth]">{monthLabel}</MonthLabel>
|
|
160
|
-
<MonthLabel className="[grid-area:rightMonth] !hidden !sm:block">
|
|
161
|
-
{nextMonthLabel}
|
|
162
|
-
</MonthLabel>
|
|
163
|
-
<MonthButton
|
|
164
|
-
emphasis="ghost"
|
|
165
|
-
className="[grid-area:nextMonth]"
|
|
166
|
-
onClick={() =>
|
|
167
|
-
setDisplay((cur) => ({
|
|
168
|
-
month: cur.month + 1,
|
|
169
|
-
year: cur.year,
|
|
170
|
-
}))
|
|
171
|
-
}
|
|
172
|
-
>
|
|
173
|
-
<Icon name="arrowRight" />
|
|
174
|
-
</MonthButton>
|
|
175
|
-
<CalendarGrid className="[grid-area:leftGrid]">
|
|
176
|
-
<DayLabels />
|
|
177
|
-
<CalendarDays>
|
|
178
|
-
{(value) => <CalendarDay value={value} key={value.key} />}
|
|
179
|
-
</CalendarDays>
|
|
180
|
-
</CalendarGrid>
|
|
181
|
-
<CalendarGrid className="[grid-area:rightGrid] !hidden !sm:grid">
|
|
182
|
-
<DayLabels />
|
|
183
|
-
<CalendarDays monthOffset={1}>
|
|
184
|
-
{(value) => <CalendarDay value={value} key={value.key} />}
|
|
185
|
-
</CalendarDays>
|
|
186
|
-
</CalendarGrid>
|
|
187
|
-
</RangeLayout>
|
|
188
|
-
</Calendar>
|
|
96
|
+
<DatePickerRoot {...props}>
|
|
97
|
+
<DatePickerMonthControls />
|
|
98
|
+
<CalendarGrid>
|
|
99
|
+
{(value) => <CalendarDay value={value} key={value.key} />}
|
|
100
|
+
</CalendarGrid>
|
|
101
|
+
</DatePickerRoot>
|
|
189
102
|
);
|
|
190
103
|
}
|
|
191
104
|
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const CalendarGrid = withClassName(
|
|
206
|
-
'div',
|
|
207
|
-
'grid grid-cols-[repeat(7,var(--day-size,32px))] [grid-auto-rows:var(--day-size,32px)]',
|
|
208
|
-
'height-[calc(var(--day-size,32px)*7)] rounded overflow-hidden p-2',
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
const CalendarDay = withClassName(
|
|
212
|
-
BaseCalendarDay,
|
|
213
|
-
'border border-solid border-transparent bg-white mr--1px mb--1px relative color-black',
|
|
214
|
-
'flex items-center justify-center transition cursor-pointer',
|
|
215
|
-
'[&[data-highlighted]]:(z-1 ring-2 ring-accent)',
|
|
216
|
-
'hover:(z-1 ring-2 ring-accent)',
|
|
217
|
-
'active:(bg-main-light rounded)',
|
|
218
|
-
'[&[data-selected]]:(bg-main z-2 rounded)',
|
|
219
|
-
'[&[data-in-range]]:(bg-main-light rounded-none z-1)',
|
|
220
|
-
'[&[data-range-start]]:(bg-main rounded-l rounded-r-none z-1)',
|
|
221
|
-
'[&[data-range-end]]:(bg-main rounded-r rounded-l-none z-1)',
|
|
222
|
-
'disabled:(opacity-50 cursor-default)',
|
|
223
|
-
// today dot
|
|
224
|
-
"[&[data-today]]:before:(content-[''] absolute left-[1px] top-[1px] w-[6px] h-[6px] rounded-lg bg-attention border-1 border-solid border-black)",
|
|
225
|
-
// calendar edges
|
|
226
|
-
'[&[data-top-edge]]:(border-t-gray)',
|
|
227
|
-
'[&[data-bottom-edge]]:(border-b-gray)',
|
|
228
|
-
'[&[data-first-column]]:(border-l-gray)',
|
|
229
|
-
'[&[data-last-column]]:(border-r-gray)',
|
|
230
|
-
'[&[data-day-first]]:(border-l-gray rounded-tl)',
|
|
231
|
-
'[&[data-day-last]]:(border-r-gray rounded-br)',
|
|
232
|
-
'[&[data-first-column][data-bottom-edge]]:rounded-bl',
|
|
233
|
-
'[&[data-last-column][data-bottom-edge]]:rounded-br',
|
|
234
|
-
'[&[data-first-column][data-top-edge]]:rounded-tl',
|
|
235
|
-
'[&[data-last-column][data-top-edge]]:rounded-tr',
|
|
236
|
-
'[&[data-different-month]]:[visibility:hidden]',
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
const DayLabel = withClassName(
|
|
240
|
-
'div',
|
|
241
|
-
'flex items-center justify-center text-sm color-gray-dark',
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
const DayLabels = () => (
|
|
245
|
-
<>
|
|
246
|
-
<DayLabel>S</DayLabel>
|
|
247
|
-
<DayLabel>M</DayLabel>
|
|
248
|
-
<DayLabel>T</DayLabel>
|
|
249
|
-
<DayLabel>W</DayLabel>
|
|
250
|
-
<DayLabel>T</DayLabel>
|
|
251
|
-
<DayLabel>F</DayLabel>
|
|
252
|
-
<DayLabel>S</DayLabel>
|
|
253
|
-
</>
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
const RangeLayout = withClassName(
|
|
257
|
-
'div',
|
|
258
|
-
'grid [grid-template-areas:"prevMonth_leftMonth_nextMonth""leftGrid_leftGrid_leftGrid"] [grid-template-columns:auto_1fr_auto]',
|
|
259
|
-
'[grid-template-rows:auto_1fr] gap-2',
|
|
260
|
-
'sm:grid-areas-[prevMonth_leftMonth_rightMonth_nextMonth]-[leftGrid_leftGrid_rightGrid_rightGrid] sm:[grid-template-columns:auto_1fr_1fr_auto]',
|
|
261
|
-
);
|
|
105
|
+
export const DatePicker = Object.assign(DatePickerDefault, {
|
|
106
|
+
Root: DatePickerRoot,
|
|
107
|
+
Calendar,
|
|
108
|
+
CalendarDay,
|
|
109
|
+
CalendarDays,
|
|
110
|
+
CalendarGrid,
|
|
111
|
+
DayLabels,
|
|
112
|
+
MonthControls: DatePickerMonthControls,
|
|
113
|
+
MonthButton,
|
|
114
|
+
MonthLabel,
|
|
115
|
+
MonthRow,
|
|
116
|
+
});
|