@a-type/ui 0.3.3 → 0.4.1

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.
Files changed (29) hide show
  1. package/dist/cjs/components/datePIcker.d.ts +1 -0
  2. package/dist/cjs/components/datePIcker.js +18 -0
  3. package/dist/cjs/components/datePIcker.js.map +1 -0
  4. package/dist/cjs/components/datePicker/DatePicker.d.ts +19 -0
  5. package/dist/cjs/components/datePicker/DatePicker.js +97 -0
  6. package/dist/cjs/components/datePicker/DatePicker.js.map +1 -0
  7. package/dist/cjs/components/datePicker/DatePicker.stories.d.ts +16 -0
  8. package/dist/cjs/components/datePicker/DatePicker.stories.js +28 -0
  9. package/dist/cjs/components/datePicker/DatePicker.stories.js.map +1 -0
  10. package/dist/cjs/components/datePicker/index.d.ts +1 -0
  11. package/dist/cjs/components/datePicker/index.js +18 -0
  12. package/dist/cjs/components/datePicker/index.js.map +1 -0
  13. package/dist/esm/components/datePIcker.d.ts +1 -0
  14. package/dist/esm/components/datePIcker.js +2 -0
  15. package/dist/esm/components/datePIcker.js.map +1 -0
  16. package/dist/esm/components/datePicker/DatePicker.d.ts +19 -0
  17. package/dist/esm/components/datePicker/DatePicker.js +89 -0
  18. package/dist/esm/components/datePicker/DatePicker.js.map +1 -0
  19. package/dist/esm/components/datePicker/DatePicker.stories.d.ts +16 -0
  20. package/dist/esm/components/datePicker/DatePicker.stories.js +25 -0
  21. package/dist/esm/components/datePicker/DatePicker.stories.js.map +1 -0
  22. package/dist/esm/components/datePicker/index.d.ts +1 -0
  23. package/dist/esm/components/datePicker/index.js +2 -0
  24. package/dist/esm/components/datePicker/index.js.map +1 -0
  25. package/package.json +2 -1
  26. package/src/components/datePIcker.ts +1 -0
  27. package/src/components/datePicker/DatePicker.stories.tsx +33 -0
  28. package/src/components/datePicker/DatePicker.tsx +258 -0
  29. package/src/components/datePicker/index.ts +1 -0
@@ -0,0 +1 @@
1
+ export * from './datePicker/index.js';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./datePicker/index.js"), exports);
18
+ //# sourceMappingURL=datePIcker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datePIcker.js","sourceRoot":"","sources":["../../../src/components/datePIcker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC"}
@@ -0,0 +1,19 @@
1
+ /// <reference types="react" resolution-mode="require"/>
2
+ export interface DatePickerProps {
3
+ value: Date | null;
4
+ onChange: (date: Date | null) => void;
5
+ className?: string;
6
+ }
7
+ export declare function DatePicker({ value, onChange, className, ...rest }: DatePickerProps): JSX.Element;
8
+ export interface DateRangePickerProps {
9
+ value: {
10
+ start: Date | null;
11
+ end: Date | null;
12
+ };
13
+ onChange: (value: {
14
+ start: Date | null;
15
+ end: Date | null;
16
+ }) => void;
17
+ className?: string;
18
+ }
19
+ export declare function DateRangePicker({ value, onChange, className, }: DateRangePickerProps): JSX.Element;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.DateRangePicker = exports.DatePicker = void 0;
18
+ const jsx_runtime_1 = require("react/jsx-runtime");
19
+ const calendar_blocks_1 = require("calendar-blocks");
20
+ const button_js_1 = require("../button.js");
21
+ const react_icons_1 = require("@radix-ui/react-icons");
22
+ const react_1 = require("react");
23
+ const hooks_js_1 = require("../../hooks.js");
24
+ const classnames_1 = __importDefault(require("classnames"));
25
+ function DatePicker(_a) {
26
+ var { value, onChange, className } = _a, rest = __rest(_a, ["value", "onChange", "className"]);
27
+ const [{ month, year }, setDisplay] = (0, react_1.useState)(() => ({
28
+ month: new Date().getMonth(),
29
+ year: new Date().getFullYear(),
30
+ }));
31
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
32
+ month: 'long',
33
+ year: 'numeric',
34
+ });
35
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, classnames_1.default)('flex flex-col items-center justify-center w-[calc(var(--day-size,32px)*7)]', className) }, rest, { children: [(0, jsx_runtime_1.jsxs)(MonthRow, { children: [(0, jsx_runtime_1.jsx)(MonthButton, Object.assign({ size: "icon", color: "ghost", onClick: () => setDisplay((cur) => ({
36
+ month: cur.month - 1,
37
+ year: cur.year,
38
+ })) }, { children: (0, jsx_runtime_1.jsx)(react_icons_1.ArrowLeftIcon, {}) })), (0, jsx_runtime_1.jsx)(MonthLabel, { children: monthLabel }), (0, jsx_runtime_1.jsx)(MonthButton, Object.assign({ size: "icon", color: "ghost", onClick: () => setDisplay((cur) => ({
39
+ month: cur.month + 1,
40
+ year: cur.year,
41
+ })) }, { children: (0, jsx_runtime_1.jsx)(react_icons_1.ArrowRightIcon, {}) }))] }), (0, jsx_runtime_1.jsx)(calendar_blocks_1.Calendar, Object.assign({ displayMonth: month, displayYear: year, value: value, onChange: onChange, onDisplayChange: setDisplay }, { children: (0, jsx_runtime_1.jsxs)(CalendarGrid, { children: [(0, jsx_runtime_1.jsx)(DayLabels, {}), (0, jsx_runtime_1.jsx)(calendar_blocks_1.CalendarDays, { children: (value) => (0, jsx_runtime_1.jsx)(CalendarDay, { value: value }, value.key) })] }) }))] })));
42
+ }
43
+ exports.DatePicker = DatePicker;
44
+ function DateRangePicker({ value, onChange, className, }) {
45
+ const [{ month, year }, setDisplay] = (0, react_1.useState)(() => ({
46
+ month: new Date().getMonth(),
47
+ year: new Date().getFullYear(),
48
+ }));
49
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
50
+ month: 'long',
51
+ year: 'numeric',
52
+ });
53
+ const nextMonth = new Date(year, month + 1);
54
+ const nextMonthLabel = nextMonth.toLocaleDateString('en-US', {
55
+ month: 'long',
56
+ year: 'numeric',
57
+ });
58
+ const onDisplayChange = (0, react_1.useCallback)(({ month: newMonth, year: newYear }) => {
59
+ /**
60
+ * Important UX consideration:
61
+ *
62
+ * since we are displaying 2 months at once, we don't
63
+ * always want to change our view if the user's cursor
64
+ * date moves from one month to another. Specifically,
65
+ * if they move from the first visible month to the
66
+ * second visible month, we don't need to change the view,
67
+ * since they are still within the visible range.
68
+ * So, we write logic to ignore that case!
69
+ */
70
+ if (newMonth === month + 1 && newYear === year) {
71
+ return; // ignore movement from the first to the second frame
72
+ }
73
+ setDisplay({
74
+ month: newMonth,
75
+ year: newYear,
76
+ });
77
+ }, [month, year]);
78
+ return ((0, jsx_runtime_1.jsx)(calendar_blocks_1.Calendar, Object.assign({ displayMonth: month, displayYear: year, rangeValue: value, onRangeChange: (range) => onChange(range), onDisplayChange: onDisplayChange, className: (0, classnames_1.default)('flex justify-center', className) }, { children: (0, jsx_runtime_1.jsxs)(RangeLayout, { children: [(0, jsx_runtime_1.jsx)(MonthButton, Object.assign({ size: "icon", color: "ghost", className: "[grid-area:prevMonth]", onClick: () => setDisplay((cur) => ({
79
+ month: cur.month - 1,
80
+ year: cur.year,
81
+ })) }, { children: (0, jsx_runtime_1.jsx)(react_icons_1.ArrowLeftIcon, {}) })), (0, jsx_runtime_1.jsx)(MonthLabel, Object.assign({ className: "[grid-area:leftMonth]" }, { children: monthLabel })), (0, jsx_runtime_1.jsx)(MonthLabel, Object.assign({ className: "[grid-area:rightMonth]" }, { children: nextMonthLabel })), (0, jsx_runtime_1.jsx)(MonthButton, Object.assign({ size: "icon", color: "ghost", className: "[grid-area:nextMonth]", onClick: () => setDisplay((cur) => ({
82
+ month: cur.month + 1,
83
+ year: cur.year,
84
+ })) }, { children: (0, jsx_runtime_1.jsx)(react_icons_1.ArrowRightIcon, {}) })), (0, jsx_runtime_1.jsxs)(CalendarGrid, Object.assign({ className: "[grid-area:leftGrid]" }, { children: [(0, jsx_runtime_1.jsx)(DayLabels, {}), (0, jsx_runtime_1.jsx)(calendar_blocks_1.CalendarDays, { children: (value) => (0, jsx_runtime_1.jsx)(CalendarDay, { value: value }, value.key) })] })), (0, jsx_runtime_1.jsxs)(CalendarGrid, Object.assign({ className: "[grid-area:rightGrid]" }, { children: [(0, jsx_runtime_1.jsx)(DayLabels, {}), (0, jsx_runtime_1.jsx)(calendar_blocks_1.CalendarDays, Object.assign({ monthOffset: 1 }, { children: (value) => (0, jsx_runtime_1.jsx)(CalendarDay, { value: value }, value.key) }))] }))] }) })));
85
+ }
86
+ exports.DateRangePicker = DateRangePicker;
87
+ const MonthRow = (0, hooks_js_1.withClassName)('div', 'flex flex-row justify-between items-center w-full');
88
+ const MonthLabel = (0, hooks_js_1.withClassName)('span', 'text-sm font-bold min-w-0 overflow-hidden text-center text-ellipsis', 'self-center');
89
+ const MonthButton = (0, hooks_js_1.withClassName)(button_js_1.Button, 'self-center');
90
+ const CalendarGrid = (0, hooks_js_1.withClassName)('div', 'grid grid-cols-[repeat(7,var(--day-size,32px))] [grid-auto-rows:var(--day-size,32px)]', 'height-[calc(var(--day-size,32px)*7)] rounded overflow-hidden p-2 bg-gray-1');
91
+ const CalendarDay = (0, hooks_js_1.withClassName)(calendar_blocks_1.CalendarDay, 'border border-solid border-transparent bg-white mr--1px mb--1px relative rounded', 'flex items-center justify-center transition-colors cursor-pointer', '[&[data-highlighted]]:(z-1 outline-accent)', '[&[data-selected]]:(bg-accent-light z-2)', '[&[data-in-range]]:(bg-accent-wash rounded-none z-1)', '[&[data-range-start]]:(bg-accent-light rounded-l rounded-r-none z-1)', '[&[data-range-end]]:(bg-accent-light rounded-r rounded-l-none z-1)', 'disabled:(opacity-50 cursor-default)',
92
+ // today dot
93
+ '[&[data-today]]:before:(content-[""] absolute left-[2px] top-[2px] w-[6px] h-[6px] rounded-full bg-primary)', '[&[data-top-edge]]:(border-top-gray-2)', '[&[data-bottom-edge]]:(border-bottom-gray-2)', '[&[data-first-column]]:(border-left-gray-2)', '[&[data-last-column]]:(border-right-gray-2)', '[&[data-day-first]]:(border-left-gray-2 rounded-tl)', '[&[data-day-last]]:(border-right-gray-2 rounded-br)', '[&[data-first-column][data-bottom-edge]]:rounded-bl', '[&[data-last-column][data-bottom-edge]]:rounded-br', '[&[data-first-column][data-top-edge]]:rounded-tl', '[&[data-last-column][data-top-edge]]:rounded-tr', '[&[data-different-month]]:[visibility:hidden]');
94
+ const DayLabel = (0, hooks_js_1.withClassName)('div', 'flex items-center justify-center text-sm text-gray-6');
95
+ const DayLabels = () => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(DayLabel, { children: "S" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "M" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "T" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "W" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "T" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "F" }), (0, jsx_runtime_1.jsx)(DayLabel, { children: "S" })] }));
96
+ const RangeLayout = (0, hooks_js_1.withClassName)('div', 'grid [grid-template-areas:"prevMonth_leftMonth_rightMonth_nextMonth""leftGrid_leftGrid_rightGrid_rightGrid"]', '[grid-template-columns:auto_1fr_1fr_auto] [grid-template-rows:auto_1fr] gap-2');
97
+ //# sourceMappingURL=DatePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.js","sourceRoot":"","sources":["../../../../src/components/datePicker/DatePicker.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { DatePicker } from './DatePicker.js';
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof DatePicker;
6
+ argTypes: {};
7
+ parameters: {
8
+ controls: {
9
+ expanded: boolean;
10
+ };
11
+ };
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof DatePicker>;
15
+ export declare const Default: Story;
16
+ export declare const Range: Story;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Range = exports.Default = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const DatePicker_js_1 = require("./DatePicker.js");
6
+ const react_1 = require("react");
7
+ const meta = {
8
+ title: 'DatePicker',
9
+ component: DatePicker_js_1.DatePicker,
10
+ argTypes: {},
11
+ parameters: {
12
+ controls: { expanded: true },
13
+ },
14
+ };
15
+ exports.default = meta;
16
+ exports.Default = {
17
+ render() {
18
+ const [value, setValue] = (0, react_1.useState)(null);
19
+ return (0, jsx_runtime_1.jsx)(DatePicker_js_1.DatePicker, { value: value, onChange: setValue });
20
+ },
21
+ };
22
+ exports.Range = {
23
+ render() {
24
+ const [value, setValue] = (0, react_1.useState)({ start: null, end: null });
25
+ return (0, jsx_runtime_1.jsx)(DatePicker_js_1.DateRangePicker, { value: value, onChange: setValue });
26
+ },
27
+ };
28
+ //# sourceMappingURL=DatePicker.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.stories.js","sourceRoot":"","sources":["../../../../src/components/datePicker/DatePicker.stories.tsx"],"names":[],"mappings":";;;;AACA,mDAA8D;AAC9D,iCAAiC;AAEjC,MAAM,IAAI,GAAG;IACZ,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,0BAAU;IACrB,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE;QACX,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;KAC5B;CACiC,CAAC;AAEpC,kBAAe,IAAI,CAAC;AAIP,QAAA,OAAO,GAAU;IAC7B,MAAM;QACL,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAc,IAAI,CAAC,CAAC;QACtD,OAAO,uBAAC,0BAAU,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAAC;IACzD,CAAC;CACD,CAAC;AAEW,QAAA,KAAK,GAAU;IAC3B,MAAM;QACL,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAG/B,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,OAAO,uBAAC,+BAAe,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAAC;IAC9D,CAAC;CACD,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './DatePicker.js';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./DatePicker.js"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/datePicker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC"}
@@ -0,0 +1 @@
1
+ export * from './datePicker/index.js';
@@ -0,0 +1,2 @@
1
+ export * from './datePicker/index.js';
2
+ //# sourceMappingURL=datePIcker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datePIcker.js","sourceRoot":"","sources":["../../../src/components/datePIcker.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /// <reference types="react" resolution-mode="require"/>
2
+ export interface DatePickerProps {
3
+ value: Date | null;
4
+ onChange: (date: Date | null) => void;
5
+ className?: string;
6
+ }
7
+ export declare function DatePicker({ value, onChange, className, ...rest }: DatePickerProps): JSX.Element;
8
+ export interface DateRangePickerProps {
9
+ value: {
10
+ start: Date | null;
11
+ end: Date | null;
12
+ };
13
+ onChange: (value: {
14
+ start: Date | null;
15
+ end: Date | null;
16
+ }) => void;
17
+ className?: string;
18
+ }
19
+ export declare function DateRangePicker({ value, onChange, className, }: DateRangePickerProps): JSX.Element;
@@ -0,0 +1,89 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
+ import { Calendar, CalendarDay as BaseCalendarDay, CalendarDays, } from 'calendar-blocks';
14
+ import { Button } from '../button.js';
15
+ import { ArrowLeftIcon, ArrowRightIcon } from '@radix-ui/react-icons';
16
+ import { useCallback, useState } from 'react';
17
+ import { withClassName } from '../../hooks.js';
18
+ import classNames from 'classnames';
19
+ export function DatePicker(_a) {
20
+ var { value, onChange, className } = _a, rest = __rest(_a, ["value", "onChange", "className"]);
21
+ const [{ month, year }, setDisplay] = useState(() => ({
22
+ month: new Date().getMonth(),
23
+ year: new Date().getFullYear(),
24
+ }));
25
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
26
+ month: 'long',
27
+ year: 'numeric',
28
+ });
29
+ return (_jsxs("div", Object.assign({ className: classNames('flex flex-col items-center justify-center w-[calc(var(--day-size,32px)*7)]', className) }, rest, { children: [_jsxs(MonthRow, { children: [_jsx(MonthButton, Object.assign({ size: "icon", color: "ghost", onClick: () => setDisplay((cur) => ({
30
+ month: cur.month - 1,
31
+ year: cur.year,
32
+ })) }, { children: _jsx(ArrowLeftIcon, {}) })), _jsx(MonthLabel, { children: monthLabel }), _jsx(MonthButton, Object.assign({ size: "icon", color: "ghost", onClick: () => setDisplay((cur) => ({
33
+ month: cur.month + 1,
34
+ year: cur.year,
35
+ })) }, { children: _jsx(ArrowRightIcon, {}) }))] }), _jsx(Calendar, Object.assign({ displayMonth: month, displayYear: year, value: value, onChange: onChange, onDisplayChange: setDisplay }, { children: _jsxs(CalendarGrid, { children: [_jsx(DayLabels, {}), _jsx(CalendarDays, { children: (value) => _jsx(CalendarDay, { value: value }, value.key) })] }) }))] })));
36
+ }
37
+ export function DateRangePicker({ value, onChange, className, }) {
38
+ const [{ month, year }, setDisplay] = useState(() => ({
39
+ month: new Date().getMonth(),
40
+ year: new Date().getFullYear(),
41
+ }));
42
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
43
+ month: 'long',
44
+ year: 'numeric',
45
+ });
46
+ const nextMonth = new Date(year, month + 1);
47
+ const nextMonthLabel = nextMonth.toLocaleDateString('en-US', {
48
+ month: 'long',
49
+ year: 'numeric',
50
+ });
51
+ const onDisplayChange = useCallback(({ month: newMonth, year: newYear }) => {
52
+ /**
53
+ * Important UX consideration:
54
+ *
55
+ * since we are displaying 2 months at once, we don't
56
+ * always want to change our view if the user's cursor
57
+ * date moves from one month to another. Specifically,
58
+ * if they move from the first visible month to the
59
+ * second visible month, we don't need to change the view,
60
+ * since they are still within the visible range.
61
+ * So, we write logic to ignore that case!
62
+ */
63
+ if (newMonth === month + 1 && newYear === year) {
64
+ return; // ignore movement from the first to the second frame
65
+ }
66
+ setDisplay({
67
+ month: newMonth,
68
+ year: newYear,
69
+ });
70
+ }, [month, year]);
71
+ return (_jsx(Calendar, Object.assign({ displayMonth: month, displayYear: year, rangeValue: value, onRangeChange: (range) => onChange(range), onDisplayChange: onDisplayChange, className: classNames('flex justify-center', className) }, { children: _jsxs(RangeLayout, { children: [_jsx(MonthButton, Object.assign({ size: "icon", color: "ghost", className: "[grid-area:prevMonth]", onClick: () => setDisplay((cur) => ({
72
+ month: cur.month - 1,
73
+ year: cur.year,
74
+ })) }, { children: _jsx(ArrowLeftIcon, {}) })), _jsx(MonthLabel, Object.assign({ className: "[grid-area:leftMonth]" }, { children: monthLabel })), _jsx(MonthLabel, Object.assign({ className: "[grid-area:rightMonth]" }, { children: nextMonthLabel })), _jsx(MonthButton, Object.assign({ size: "icon", color: "ghost", className: "[grid-area:nextMonth]", onClick: () => setDisplay((cur) => ({
75
+ month: cur.month + 1,
76
+ year: cur.year,
77
+ })) }, { children: _jsx(ArrowRightIcon, {}) })), _jsxs(CalendarGrid, Object.assign({ className: "[grid-area:leftGrid]" }, { children: [_jsx(DayLabels, {}), _jsx(CalendarDays, { children: (value) => _jsx(CalendarDay, { value: value }, value.key) })] })), _jsxs(CalendarGrid, Object.assign({ className: "[grid-area:rightGrid]" }, { children: [_jsx(DayLabels, {}), _jsx(CalendarDays, Object.assign({ monthOffset: 1 }, { children: (value) => _jsx(CalendarDay, { value: value }, value.key) }))] }))] }) })));
78
+ }
79
+ const MonthRow = withClassName('div', 'flex flex-row justify-between items-center w-full');
80
+ const MonthLabel = withClassName('span', 'text-sm font-bold min-w-0 overflow-hidden text-center text-ellipsis', 'self-center');
81
+ const MonthButton = withClassName(Button, 'self-center');
82
+ const CalendarGrid = withClassName('div', 'grid grid-cols-[repeat(7,var(--day-size,32px))] [grid-auto-rows:var(--day-size,32px)]', 'height-[calc(var(--day-size,32px)*7)] rounded overflow-hidden p-2 bg-gray-1');
83
+ const CalendarDay = withClassName(BaseCalendarDay, 'border border-solid border-transparent bg-white mr--1px mb--1px relative rounded', 'flex items-center justify-center transition-colors cursor-pointer', '[&[data-highlighted]]:(z-1 outline-accent)', '[&[data-selected]]:(bg-accent-light z-2)', '[&[data-in-range]]:(bg-accent-wash rounded-none z-1)', '[&[data-range-start]]:(bg-accent-light rounded-l rounded-r-none z-1)', '[&[data-range-end]]:(bg-accent-light rounded-r rounded-l-none z-1)', 'disabled:(opacity-50 cursor-default)',
84
+ // today dot
85
+ '[&[data-today]]:before:(content-[""] absolute left-[2px] top-[2px] w-[6px] h-[6px] rounded-full bg-primary)', '[&[data-top-edge]]:(border-top-gray-2)', '[&[data-bottom-edge]]:(border-bottom-gray-2)', '[&[data-first-column]]:(border-left-gray-2)', '[&[data-last-column]]:(border-right-gray-2)', '[&[data-day-first]]:(border-left-gray-2 rounded-tl)', '[&[data-day-last]]:(border-right-gray-2 rounded-br)', '[&[data-first-column][data-bottom-edge]]:rounded-bl', '[&[data-last-column][data-bottom-edge]]:rounded-br', '[&[data-first-column][data-top-edge]]:rounded-tl', '[&[data-last-column][data-top-edge]]:rounded-tr', '[&[data-different-month]]:[visibility:hidden]');
86
+ const DayLabel = withClassName('div', 'flex items-center justify-center text-sm text-gray-6');
87
+ const DayLabels = () => (_jsxs(_Fragment, { children: [_jsx(DayLabel, { children: "S" }), _jsx(DayLabel, { children: "M" }), _jsx(DayLabel, { children: "T" }), _jsx(DayLabel, { children: "W" }), _jsx(DayLabel, { children: "T" }), _jsx(DayLabel, { children: "F" }), _jsx(DayLabel, { children: "S" })] }));
88
+ const RangeLayout = withClassName('div', 'grid [grid-template-areas:"prevMonth_leftMonth_rightMonth_nextMonth""leftGrid_leftGrid_rightGrid_rightGrid"]', '[grid-template-columns:auto_1fr_1fr_auto] [grid-template-rows:auto_1fr] gap-2');
89
+ //# sourceMappingURL=DatePicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.js","sourceRoot":"","sources":["../../../../src/components/datePicker/DatePicker.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EACN,QAAQ,EACR,WAAW,IAAI,eAAe,EAC9B,YAAY,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,UAAU,MAAM,YAAY,CAAC;AAQpC,MAAM,UAAU,UAAU,CAAC,EAKT;QALS,EAC1B,KAAK,EACL,QAAQ,EACR,SAAS,OAEQ,EADd,IAAI,cAJmB,kCAK1B,CADO;IAEP,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,QAAQ,EAAE;QAC5B,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC9B,CAAC,CAAC,CAAC;IACJ,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;QACpE,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,SAAS;KACf,CAAC,CAAC;IAEH,OAAO,CACN,6BACC,SAAS,EAAE,UAAU,CACpB,4EAA4E,EAC5E,SAAS,CACT,IACG,IAAI,eAER,MAAC,QAAQ,eACR,KAAC,WAAW,kBACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,OAAO,EACb,OAAO,EAAE,GAAG,EAAE,CACb,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;4BACpB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;4BACpB,IAAI,EAAE,GAAG,CAAC,IAAI;yBACd,CAAC,CAAC,gBAGJ,KAAC,aAAa,KAAG,IACJ,EACd,KAAC,UAAU,cAAE,UAAU,GAAc,EACrC,KAAC,WAAW,kBACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,OAAO,EACb,OAAO,EAAE,GAAG,EAAE,CACb,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;4BACpB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;4BACpB,IAAI,EAAE,GAAG,CAAC,IAAI;yBACd,CAAC,CAAC,gBAGJ,KAAC,cAAc,KAAG,IACL,IACJ,EACX,KAAC,QAAQ,kBACR,YAAY,EAAE,KAAK,EACnB,WAAW,EAAE,IAAI,EACjB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,UAAU,gBAE3B,MAAC,YAAY,eACZ,KAAC,SAAS,KAAG,EACb,KAAC,YAAY,cACX,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,IAAO,KAAK,CAAC,GAAG,CAAI,GAC3C,IACD,IACL,KACN,CACN,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,eAAe,CAAC,EAC/B,KAAK,EACL,QAAQ,EACR,SAAS,GACa;IACtB,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACrD,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,QAAQ,EAAE;QAC5B,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC9B,CAAC,CAAC,CAAC;IACJ,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE;QACpE,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,SAAS;KACf,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE;QAC5D,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,SAAS;KACf,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,WAAW,CAClC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAmC,EAAE,EAAE;QACvE;;;;;;;;;;WAUG;QACH,IAAI,QAAQ,KAAK,KAAK,GAAG,CAAC,IAAI,OAAO,KAAK,IAAI,EAAE;YAC/C,OAAO,CAAC,qDAAqD;SAC7D;QAED,UAAU,CAAC;YACV,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,OAAO;SACb,CAAC,CAAC;IACJ,CAAC,EACD,CAAC,KAAK,EAAE,IAAI,CAAC,CACb,CAAC;IAEF,OAAO,CACN,KAAC,QAAQ,kBACR,YAAY,EAAE,KAAK,EACnB,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,KAAK,EACjB,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EACzC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,UAAU,CAAC,qBAAqB,EAAE,SAAS,CAAC,gBAEvD,MAAC,WAAW,eACX,KAAC,WAAW,kBACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,OAAO,EACb,SAAS,EAAC,uBAAuB,EACjC,OAAO,EAAE,GAAG,EAAE,CACb,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBACpB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;wBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;qBACd,CAAC,CAAC,gBAGJ,KAAC,aAAa,KAAG,IACJ,EACd,KAAC,UAAU,kBAAC,SAAS,EAAC,uBAAuB,gBAAE,UAAU,IAAc,EACvE,KAAC,UAAU,kBAAC,SAAS,EAAC,wBAAwB,gBAC5C,cAAc,IACH,EACb,KAAC,WAAW,kBACX,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,OAAO,EACb,SAAS,EAAC,uBAAuB,EACjC,OAAO,EAAE,GAAG,EAAE,CACb,UAAU,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBACpB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC;wBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;qBACd,CAAC,CAAC,gBAGJ,KAAC,cAAc,KAAG,IACL,EACd,MAAC,YAAY,kBAAC,SAAS,EAAC,sBAAsB,iBAC7C,KAAC,SAAS,KAAG,EACb,KAAC,YAAY,cACX,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,IAAO,KAAK,CAAC,GAAG,CAAI,GAC3C,KACD,EACf,MAAC,YAAY,kBAAC,SAAS,EAAC,uBAAuB,iBAC9C,KAAC,SAAS,KAAG,EACb,KAAC,YAAY,kBAAC,WAAW,EAAE,CAAC,gBAC1B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,IAAO,KAAK,CAAC,GAAG,CAAI,IAC3C,KACD,IACF,IACJ,CACX,CAAC;AACH,CAAC;AAED,MAAM,QAAQ,GAAG,aAAa,CAC7B,KAAK,EACL,mDAAmD,CACnD,CAAC;AAEF,MAAM,UAAU,GAAG,aAAa,CAC/B,MAAM,EACN,qEAAqE,EACrE,aAAa,CACb,CAAC;AAEF,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,YAAY,GAAG,aAAa,CACjC,KAAK,EACL,uFAAuF,EACvF,6EAA6E,CAC7E,CAAC;AAEF,MAAM,WAAW,GAAG,aAAa,CAChC,eAAe,EACf,kFAAkF,EAClF,mEAAmE,EACnE,4CAA4C,EAC5C,0CAA0C,EAC1C,sDAAsD,EACtD,sEAAsE,EACtE,oEAAoE,EACpE,sCAAsC;AACtC,YAAY;AACZ,6GAA6G,EAC7G,wCAAwC,EACxC,8CAA8C,EAC9C,6CAA6C,EAC7C,6CAA6C,EAC7C,qDAAqD,EACrD,qDAAqD,EACrD,qDAAqD,EACrD,oDAAoD,EACpD,kDAAkD,EAClD,iDAAiD,EACjD,+CAA+C,CAC/C,CAAC;AAEF,MAAM,QAAQ,GAAG,aAAa,CAC7B,KAAK,EACL,sDAAsD,CACtD,CAAC;AAEF,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,CACvB,8BACC,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,EACtB,KAAC,QAAQ,oBAAa,IACpB,CACH,CAAC;AAEF,MAAM,WAAW,GAAG,aAAa,CAChC,KAAK,EACL,8GAA8G,EAC9G,+EAA+E,CAC/E,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { DatePicker } from './DatePicker.js';
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof DatePicker;
6
+ argTypes: {};
7
+ parameters: {
8
+ controls: {
9
+ expanded: boolean;
10
+ };
11
+ };
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof DatePicker>;
15
+ export declare const Default: Story;
16
+ export declare const Range: Story;
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DatePicker, DateRangePicker } from './DatePicker.js';
3
+ import { useState } from 'react';
4
+ const meta = {
5
+ title: 'DatePicker',
6
+ component: DatePicker,
7
+ argTypes: {},
8
+ parameters: {
9
+ controls: { expanded: true },
10
+ },
11
+ };
12
+ export default meta;
13
+ export const Default = {
14
+ render() {
15
+ const [value, setValue] = useState(null);
16
+ return _jsx(DatePicker, { value: value, onChange: setValue });
17
+ },
18
+ };
19
+ export const Range = {
20
+ render() {
21
+ const [value, setValue] = useState({ start: null, end: null });
22
+ return _jsx(DateRangePicker, { value: value, onChange: setValue });
23
+ },
24
+ };
25
+ //# sourceMappingURL=DatePicker.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatePicker.stories.js","sourceRoot":"","sources":["../../../../src/components/datePicker/DatePicker.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,IAAI,GAAG;IACZ,KAAK,EAAE,YAAY;IACnB,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE;QACX,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;KAC5B;CACiC,CAAC;AAEpC,eAAe,IAAI,CAAC;AAIpB,MAAM,CAAC,MAAM,OAAO,GAAU;IAC7B,MAAM;QACL,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAc,IAAI,CAAC,CAAC;QACtD,OAAO,KAAC,UAAU,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAAC;IACzD,CAAC;CACD,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAU;IAC3B,MAAM;QACL,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAG/B,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,OAAO,KAAC,eAAe,IAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAAC;IAC9D,CAAC;CACD,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './DatePicker.js';
@@ -0,0 +1,2 @@
1
+ export * from './DatePicker.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/datePicker/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-type/ui",
3
- "version": "0.3.3",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "/dist",
@@ -57,6 +57,7 @@
57
57
  "@tiptap/starter-kit": "^2.0.3",
58
58
  "@use-gesture/react": "^10.2.27",
59
59
  "browser-image-resizer": "^2.4.1",
60
+ "calendar-blocks": "^0.3.0",
60
61
  "classnames": "^2.3.2",
61
62
  "color-interpolate": "^1.0.5",
62
63
  "color-parse": "^2.0.0",
@@ -0,0 +1 @@
1
+ export * from './datePicker/index.js';
@@ -0,0 +1,33 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { DatePicker, DateRangePicker } from './DatePicker.js';
3
+ import { useState } from 'react';
4
+
5
+ const meta = {
6
+ title: 'DatePicker',
7
+ component: DatePicker,
8
+ argTypes: {},
9
+ parameters: {
10
+ controls: { expanded: true },
11
+ },
12
+ } satisfies Meta<typeof DatePicker>;
13
+
14
+ export default meta;
15
+
16
+ type Story = StoryObj<typeof DatePicker>;
17
+
18
+ export const Default: Story = {
19
+ render() {
20
+ const [value, setValue] = useState<Date | null>(null);
21
+ return <DatePicker value={value} onChange={setValue} />;
22
+ },
23
+ };
24
+
25
+ export const Range: Story = {
26
+ render() {
27
+ const [value, setValue] = useState<{
28
+ start: Date | null;
29
+ end: Date | null;
30
+ }>({ start: null, end: null });
31
+ return <DateRangePicker value={value} onChange={setValue} />;
32
+ },
33
+ };
@@ -0,0 +1,258 @@
1
+ import {
2
+ Calendar,
3
+ CalendarDay as BaseCalendarDay,
4
+ CalendarDays,
5
+ } from 'calendar-blocks';
6
+ import { Button } from '../button.js';
7
+ import { Icon } from '../icon.js';
8
+ import { ArrowLeftIcon, ArrowRightIcon } from '@radix-ui/react-icons';
9
+ import { useCallback, useState } from 'react';
10
+ import { withClassName } from '../../hooks.js';
11
+ import classNames from 'classnames';
12
+
13
+ export interface DatePickerProps {
14
+ value: Date | null;
15
+ onChange: (date: Date | null) => void;
16
+ className?: string;
17
+ }
18
+
19
+ export function DatePicker({
20
+ value,
21
+ onChange,
22
+ className,
23
+ ...rest
24
+ }: DatePickerProps) {
25
+ const [{ month, year }, setDisplay] = useState(() => ({
26
+ month: new Date().getMonth(),
27
+ year: new Date().getFullYear(),
28
+ }));
29
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
30
+ month: 'long',
31
+ year: 'numeric',
32
+ });
33
+
34
+ return (
35
+ <div
36
+ className={classNames(
37
+ 'flex flex-col items-center justify-center w-[calc(var(--day-size,32px)*7)]',
38
+ className,
39
+ )}
40
+ {...rest}
41
+ >
42
+ <MonthRow>
43
+ <MonthButton
44
+ size="icon"
45
+ color="ghost"
46
+ onClick={() =>
47
+ setDisplay((cur) => ({
48
+ month: cur.month - 1,
49
+ year: cur.year,
50
+ }))
51
+ }
52
+ >
53
+ <ArrowLeftIcon />
54
+ </MonthButton>
55
+ <MonthLabel>{monthLabel}</MonthLabel>
56
+ <MonthButton
57
+ size="icon"
58
+ color="ghost"
59
+ onClick={() =>
60
+ setDisplay((cur) => ({
61
+ month: cur.month + 1,
62
+ year: cur.year,
63
+ }))
64
+ }
65
+ >
66
+ <ArrowRightIcon />
67
+ </MonthButton>
68
+ </MonthRow>
69
+ <Calendar
70
+ displayMonth={month}
71
+ displayYear={year}
72
+ value={value}
73
+ onChange={onChange}
74
+ onDisplayChange={setDisplay}
75
+ >
76
+ <CalendarGrid>
77
+ <DayLabels />
78
+ <CalendarDays>
79
+ {(value) => <CalendarDay value={value} key={value.key} />}
80
+ </CalendarDays>
81
+ </CalendarGrid>
82
+ </Calendar>
83
+ </div>
84
+ );
85
+ }
86
+
87
+ export interface DateRangePickerProps {
88
+ value: { start: Date | null; end: Date | null };
89
+ onChange: (value: { start: Date | null; end: Date | null }) => void;
90
+ className?: string;
91
+ }
92
+
93
+ export function DateRangePicker({
94
+ value,
95
+ onChange,
96
+ className,
97
+ }: DateRangePickerProps) {
98
+ const [{ month, year }, setDisplay] = useState(() => ({
99
+ month: new Date().getMonth(),
100
+ year: new Date().getFullYear(),
101
+ }));
102
+ const monthLabel = new Date(year, month).toLocaleDateString('en-US', {
103
+ month: 'long',
104
+ year: 'numeric',
105
+ });
106
+ const nextMonth = new Date(year, month + 1);
107
+ const nextMonthLabel = nextMonth.toLocaleDateString('en-US', {
108
+ month: 'long',
109
+ year: 'numeric',
110
+ });
111
+ const onDisplayChange = useCallback(
112
+ ({ month: newMonth, year: newYear }: { month: number; year: number }) => {
113
+ /**
114
+ * Important UX consideration:
115
+ *
116
+ * since we are displaying 2 months at once, we don't
117
+ * always want to change our view if the user's cursor
118
+ * date moves from one month to another. Specifically,
119
+ * if they move from the first visible month to the
120
+ * second visible month, we don't need to change the view,
121
+ * since they are still within the visible range.
122
+ * So, we write logic to ignore that case!
123
+ */
124
+ if (newMonth === month + 1 && newYear === year) {
125
+ return; // ignore movement from the first to the second frame
126
+ }
127
+
128
+ setDisplay({
129
+ month: newMonth,
130
+ year: newYear,
131
+ });
132
+ },
133
+ [month, year],
134
+ );
135
+
136
+ return (
137
+ <Calendar
138
+ displayMonth={month}
139
+ displayYear={year}
140
+ rangeValue={value}
141
+ onRangeChange={(range) => onChange(range)}
142
+ onDisplayChange={onDisplayChange}
143
+ className={classNames('flex justify-center', className)}
144
+ >
145
+ <RangeLayout>
146
+ <MonthButton
147
+ size="icon"
148
+ color="ghost"
149
+ className="[grid-area:prevMonth]"
150
+ onClick={() =>
151
+ setDisplay((cur) => ({
152
+ month: cur.month - 1,
153
+ year: cur.year,
154
+ }))
155
+ }
156
+ >
157
+ <ArrowLeftIcon />
158
+ </MonthButton>
159
+ <MonthLabel className="[grid-area:leftMonth]">{monthLabel}</MonthLabel>
160
+ <MonthLabel className="[grid-area:rightMonth]">
161
+ {nextMonthLabel}
162
+ </MonthLabel>
163
+ <MonthButton
164
+ size="icon"
165
+ color="ghost"
166
+ className="[grid-area:nextMonth]"
167
+ onClick={() =>
168
+ setDisplay((cur) => ({
169
+ month: cur.month + 1,
170
+ year: cur.year,
171
+ }))
172
+ }
173
+ >
174
+ <ArrowRightIcon />
175
+ </MonthButton>
176
+ <CalendarGrid className="[grid-area:leftGrid]">
177
+ <DayLabels />
178
+ <CalendarDays>
179
+ {(value) => <CalendarDay value={value} key={value.key} />}
180
+ </CalendarDays>
181
+ </CalendarGrid>
182
+ <CalendarGrid className="[grid-area:rightGrid]">
183
+ <DayLabels />
184
+ <CalendarDays monthOffset={1}>
185
+ {(value) => <CalendarDay value={value} key={value.key} />}
186
+ </CalendarDays>
187
+ </CalendarGrid>
188
+ </RangeLayout>
189
+ </Calendar>
190
+ );
191
+ }
192
+
193
+ const MonthRow = withClassName(
194
+ 'div',
195
+ 'flex flex-row justify-between items-center w-full',
196
+ );
197
+
198
+ const MonthLabel = withClassName(
199
+ 'span',
200
+ 'text-sm font-bold min-w-0 overflow-hidden text-center text-ellipsis',
201
+ 'self-center',
202
+ );
203
+
204
+ const MonthButton = withClassName(Button, 'self-center');
205
+
206
+ const CalendarGrid = withClassName(
207
+ 'div',
208
+ 'grid grid-cols-[repeat(7,var(--day-size,32px))] [grid-auto-rows:var(--day-size,32px)]',
209
+ 'height-[calc(var(--day-size,32px)*7)] rounded overflow-hidden p-2 bg-gray-1',
210
+ );
211
+
212
+ const CalendarDay = withClassName(
213
+ BaseCalendarDay,
214
+ 'border border-solid border-transparent bg-white mr--1px mb--1px relative rounded',
215
+ 'flex items-center justify-center transition-colors cursor-pointer',
216
+ '[&[data-highlighted]]:(z-1 outline-accent)',
217
+ '[&[data-selected]]:(bg-accent-light z-2)',
218
+ '[&[data-in-range]]:(bg-accent-wash rounded-none z-1)',
219
+ '[&[data-range-start]]:(bg-accent-light rounded-l rounded-r-none z-1)',
220
+ '[&[data-range-end]]:(bg-accent-light rounded-r rounded-l-none z-1)',
221
+ 'disabled:(opacity-50 cursor-default)',
222
+ // today dot
223
+ '[&[data-today]]:before:(content-[""] absolute left-[2px] top-[2px] w-[6px] h-[6px] rounded-full bg-primary)',
224
+ '[&[data-top-edge]]:(border-top-gray-2)',
225
+ '[&[data-bottom-edge]]:(border-bottom-gray-2)',
226
+ '[&[data-first-column]]:(border-left-gray-2)',
227
+ '[&[data-last-column]]:(border-right-gray-2)',
228
+ '[&[data-day-first]]:(border-left-gray-2 rounded-tl)',
229
+ '[&[data-day-last]]:(border-right-gray-2 rounded-br)',
230
+ '[&[data-first-column][data-bottom-edge]]:rounded-bl',
231
+ '[&[data-last-column][data-bottom-edge]]:rounded-br',
232
+ '[&[data-first-column][data-top-edge]]:rounded-tl',
233
+ '[&[data-last-column][data-top-edge]]:rounded-tr',
234
+ '[&[data-different-month]]:[visibility:hidden]',
235
+ );
236
+
237
+ const DayLabel = withClassName(
238
+ 'div',
239
+ 'flex items-center justify-center text-sm text-gray-6',
240
+ );
241
+
242
+ const DayLabels = () => (
243
+ <>
244
+ <DayLabel>S</DayLabel>
245
+ <DayLabel>M</DayLabel>
246
+ <DayLabel>T</DayLabel>
247
+ <DayLabel>W</DayLabel>
248
+ <DayLabel>T</DayLabel>
249
+ <DayLabel>F</DayLabel>
250
+ <DayLabel>S</DayLabel>
251
+ </>
252
+ );
253
+
254
+ const RangeLayout = withClassName(
255
+ 'div',
256
+ 'grid [grid-template-areas:"prevMonth_leftMonth_rightMonth_nextMonth""leftGrid_leftGrid_rightGrid_rightGrid"]',
257
+ '[grid-template-columns:auto_1fr_1fr_auto] [grid-template-rows:auto_1fr] gap-2',
258
+ );
@@ -0,0 +1 @@
1
+ export * from './DatePicker.js';