@westpac/ui 0.49.0 → 0.50.3
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/CHANGELOG.md +28 -0
- package/dist/component-type.json +1 -1
- package/dist/components/accordion/components/accordion-item/accordion-item.component.js +44 -24
- package/dist/components/accordion/components/accordion-item/accordion-item.styles.d.ts +18 -6
- package/dist/components/accordion/components/accordion-item/accordion-item.styles.js +10 -6
- package/dist/components/autocomplete/autocomplete.component.d.ts +1 -1
- package/dist/components/autocomplete/autocomplete.component.js +3 -2
- package/dist/components/autocomplete/autocomplete.types.d.ts +6 -0
- package/dist/components/date-picker-beta/components/calendar/calendar.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/calendar.component.js +101 -0
- package/dist/components/date-picker-beta/components/calendar/calendar.types.d.ts +2 -0
- package/dist/components/date-picker-beta/components/calendar/calendar.types.js +1 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.component.js +28 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.styles.d.ts +103 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.styles.js +39 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.types.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.types.js +1 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.component.js +26 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.types.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.types.js +1 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.component.js +23 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.styles.d.ts +28 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.styles.js +14 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.types.d.ts +2 -0
- package/dist/components/date-picker-beta/components/calendar/components/select/select.types.js +1 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.component.js +20 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.d.ts +44 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.js +26 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.types.d.ts +7 -0
- package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.types.js +1 -0
- package/dist/components/date-picker-beta/components/date-field/date-field.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/date-field/date-field.component.js +25 -0
- package/dist/components/date-picker-beta/components/date-field/date-field.types.d.ts +4 -0
- package/dist/components/date-picker-beta/components/date-field/date-field.types.js +1 -0
- package/dist/components/date-picker-beta/components/dialog/dialog.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/dialog/dialog.component.js +16 -0
- package/dist/components/date-picker-beta/components/dialog/dialog.types.d.ts +3 -0
- package/dist/components/date-picker-beta/components/dialog/dialog.types.js +1 -0
- package/dist/components/date-picker-beta/components/popover/popover.component.d.ts +5 -0
- package/dist/components/date-picker-beta/components/popover/popover.component.js +38 -0
- package/dist/components/date-picker-beta/components/popover/popover.styles.d.ts +71 -0
- package/dist/components/date-picker-beta/components/popover/popover.styles.js +35 -0
- package/dist/components/date-picker-beta/components/popover/popover.types.d.ts +9 -0
- package/dist/components/date-picker-beta/components/popover/popover.types.js +1 -0
- package/dist/components/date-picker-beta/date-picker.component.d.ts +2 -0
- package/dist/components/date-picker-beta/date-picker.component.js +114 -0
- package/dist/components/date-picker-beta/date-picker.styles.d.ts +107 -0
- package/dist/components/date-picker-beta/date-picker.styles.js +47 -0
- package/dist/components/date-picker-beta/date-picker.types.d.ts +32 -0
- package/dist/components/date-picker-beta/date-picker.types.js +1 -0
- package/dist/components/date-picker-beta/index.d.ts +2 -0
- package/dist/components/date-picker-beta/index.js +1 -0
- package/dist/components/footer/footer.component.js +4 -11
- package/dist/components/footer/footer.styles.d.ts +3 -21
- package/dist/components/footer/footer.styles.js +3 -9
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/css/westpac-ui.css +1025 -35
- package/dist/css/westpac-ui.min.css +1025 -35
- package/dist/hook/breakpoints.hook.js +59 -10
- package/dist/hook/index.d.ts +1 -0
- package/dist/hook/index.js +1 -0
- package/dist/tailwind/constants/colors.d.ts +25 -25
- package/dist/tailwind/tailwind-plugin.js +20 -0
- package/dist/tailwind/themes/index.d.ts +27 -27
- package/package.json +10 -5
- package/src/components/accordion/components/accordion-item/accordion-item.component.tsx +49 -32
- package/src/components/accordion/components/accordion-item/accordion-item.styles.ts +10 -6
- package/src/components/autocomplete/autocomplete.component.tsx +3 -1
- package/src/components/autocomplete/autocomplete.types.ts +6 -0
- package/src/components/date-picker-beta/components/calendar/calendar.component.tsx +106 -0
- package/src/components/date-picker-beta/components/calendar/calendar.types.ts +3 -0
- package/src/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.component.tsx +42 -0
- package/src/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.styles.ts +40 -0
- package/src/components/date-picker-beta/components/calendar/components/calendar-cell/calendar-cell.types.ts +8 -0
- package/src/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.component.tsx +36 -0
- package/src/components/date-picker-beta/components/calendar/components/calendar-grid/calendar-grid.types.ts +4 -0
- package/src/components/date-picker-beta/components/calendar/components/select/select.component.tsx +21 -0
- package/src/components/date-picker-beta/components/calendar/components/select/select.styles.ts +13 -0
- package/src/components/date-picker-beta/components/calendar/components/select/select.types.ts +3 -0
- package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.component.tsx +26 -0
- package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.ts +22 -0
- package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.types.ts +8 -0
- package/src/components/date-picker-beta/components/date-field/date-field.component.tsx +32 -0
- package/src/components/date-picker-beta/components/date-field/date-field.types.ts +3 -0
- package/src/components/date-picker-beta/components/dialog/dialog.component.tsx +23 -0
- package/src/components/date-picker-beta/components/dialog/dialog.types.ts +4 -0
- package/src/components/date-picker-beta/components/popover/popover.component.tsx +34 -0
- package/src/components/date-picker-beta/components/popover/popover.styles.ts +34 -0
- package/src/components/date-picker-beta/components/popover/popover.types.ts +10 -0
- package/src/components/date-picker-beta/date-picker.component.tsx +114 -0
- package/src/components/date-picker-beta/date-picker.styles.ts +44 -0
- package/src/components/date-picker-beta/date-picker.types.ts +40 -0
- package/src/components/date-picker-beta/index.ts +2 -0
- package/src/components/footer/footer.component.tsx +8 -12
- package/src/components/footer/footer.styles.ts +2 -6
- package/src/components/index.ts +1 -0
- package/src/hook/breakpoints.hook.ts +71 -11
- package/src/hook/index.ts +1 -0
- package/src/tailwind/tailwind-plugin.ts +20 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* eslint-disable sonarjs/deprecation */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3
3
|
import { useAccordionItem } from '@react-aria/accordion';
|
|
4
|
-
import {
|
|
5
|
-
import React, { useRef } from 'react';
|
|
4
|
+
import { LazyMotion, m, useAnimate } from 'motion/react';
|
|
5
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
6
6
|
import { mergeProps, useFocusRing, useHover, useLocale } from 'react-aria';
|
|
7
7
|
|
|
8
8
|
import { ArrowLeftIcon, ArrowRightIcon } from '../../../icon/index.js';
|
|
@@ -23,11 +23,44 @@ export function AccordionItem<T = HTMLElement>({
|
|
|
23
23
|
const { state, item } = props;
|
|
24
24
|
const { buttonProps, regionProps } = useAccordionItem<T>(props, state, ref);
|
|
25
25
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
26
|
-
const
|
|
26
|
+
const isOpenState = state.expandedKeys.has(item.key);
|
|
27
27
|
const isDisabled = state.disabledKeys.has(item.key);
|
|
28
28
|
const { hoverProps } = useHover({ isDisabled });
|
|
29
29
|
const { direction } = useLocale();
|
|
30
|
-
|
|
30
|
+
// Open/close animation needs to be done with useAnimate as AnimatePresence will unmount component
|
|
31
|
+
const [scope, animate] = useAnimate();
|
|
32
|
+
const [enableOpenStyle, setEnableOpenStyle] = useState(false);
|
|
33
|
+
|
|
34
|
+
const styles = accordionItemStyles({
|
|
35
|
+
isOpen: enableOpenStyle,
|
|
36
|
+
isOpenState,
|
|
37
|
+
isDisabled,
|
|
38
|
+
look,
|
|
39
|
+
isFocusVisible,
|
|
40
|
+
rounded,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
// setEnableStyle here as opening animation isn't working correctly if done below
|
|
45
|
+
if (isOpenState) setEnableOpenStyle(true);
|
|
46
|
+
|
|
47
|
+
if (enableOpenStyle) {
|
|
48
|
+
animate(scope.current, { height: 'auto' }, { duration: 0.3, ease: [0.25, 0.1, 0.25, 1.0] });
|
|
49
|
+
}
|
|
50
|
+
if (!isOpenState) {
|
|
51
|
+
animate(
|
|
52
|
+
scope.current,
|
|
53
|
+
{ height: '0px' },
|
|
54
|
+
{
|
|
55
|
+
duration: 0.3,
|
|
56
|
+
ease: [0.25, 0.1, 0.25, 1.0],
|
|
57
|
+
// set some styles after animation completes so content doesn't disappear on close
|
|
58
|
+
onComplete: () => setEnableOpenStyle(false),
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
|
+
}, [isOpenState, enableOpenStyle]);
|
|
31
64
|
|
|
32
65
|
return (
|
|
33
66
|
<Tag className={styles.base({ className })}>
|
|
@@ -47,34 +80,18 @@ export function AccordionItem<T = HTMLElement>({
|
|
|
47
80
|
</h3>
|
|
48
81
|
<div {...regionProps}>
|
|
49
82
|
<LazyMotion features={loadAnimations}>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}}
|
|
63
|
-
transition={{ duration: 0.3, ease: [0.25, 0.1, 0.25, 1.0] }}
|
|
64
|
-
>
|
|
65
|
-
<div
|
|
66
|
-
className={styles.content()}
|
|
67
|
-
// TODO: Remove below with updated accordion that uses disclosure as the issue doesn't happen with that version
|
|
68
|
-
// Need to call stopPropagation here as some events from children are bubbling up and focusing the accordion i.e. inputs
|
|
69
|
-
onBlur={e => {
|
|
70
|
-
e.stopPropagation();
|
|
71
|
-
}}
|
|
72
|
-
>
|
|
73
|
-
{item.props.children}
|
|
74
|
-
</div>
|
|
75
|
-
</m.div>
|
|
76
|
-
)}
|
|
77
|
-
</AnimatePresence>
|
|
83
|
+
<m.div className="overflow-hidden" initial={{ height: isOpenState ? 'auto' : 0 }} ref={scope}>
|
|
84
|
+
<div
|
|
85
|
+
className={styles.content()}
|
|
86
|
+
// TODO: Remove below with updated accordion that uses disclosure as the issue doesn't happen with that version
|
|
87
|
+
// Need to call stopPropagation here as some events from children are bubbling up and focusing the accordion i.e. inputs
|
|
88
|
+
onBlur={e => {
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{item.props.children}
|
|
93
|
+
</div>
|
|
94
|
+
</m.div>
|
|
78
95
|
</LazyMotion>
|
|
79
96
|
</div>
|
|
80
97
|
</Tag>
|
|
@@ -7,7 +7,7 @@ export const styles = tv(
|
|
|
7
7
|
itemHeader: 'typography-body-9 flex w-full flex-1 items-center justify-between px-3 py-2 group-first:border-t-0',
|
|
8
8
|
headerTitleWrapper: 'flex-1 pr-2 text-left',
|
|
9
9
|
indicator: 'size-3 rotate-90',
|
|
10
|
-
content: '
|
|
10
|
+
content: '',
|
|
11
11
|
},
|
|
12
12
|
variants: {
|
|
13
13
|
look: {
|
|
@@ -19,13 +19,17 @@ export const styles = tv(
|
|
|
19
19
|
'mb-[-1px] border-l-[0.375rem] border-r border-border bg-light shadow-[inset_0px_1px_0_0_var(--tw-shadow-color),inset_0_-1px_0_0_var(--tw-shadow-color)] !shadow-border transition-colors',
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
|
+
isOpenState: {
|
|
23
|
+
false: {
|
|
24
|
+
itemHeader: 'background-transition hover:bg-background',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
22
27
|
isOpen: {
|
|
23
28
|
true: {
|
|
24
|
-
content: 'block border-border p-3',
|
|
29
|
+
content: 'visible block border-border p-3',
|
|
25
30
|
},
|
|
26
31
|
false: {
|
|
27
|
-
|
|
28
|
-
itemHeader: 'background-transition hover:bg-background',
|
|
32
|
+
content: 'hidden',
|
|
29
33
|
},
|
|
30
34
|
},
|
|
31
35
|
isDisabled: {
|
|
@@ -45,13 +49,13 @@ export const styles = tv(
|
|
|
45
49
|
compoundSlots: [
|
|
46
50
|
{
|
|
47
51
|
slots: ['indicator'],
|
|
48
|
-
|
|
52
|
+
isOpenState: true,
|
|
49
53
|
className: '-rotate-90',
|
|
50
54
|
},
|
|
51
55
|
{
|
|
52
56
|
slots: ['itemHeader'],
|
|
53
57
|
look: 'lego',
|
|
54
|
-
|
|
58
|
+
isOpenState: true,
|
|
55
59
|
className: 'border-l-hero',
|
|
56
60
|
},
|
|
57
61
|
{
|
|
@@ -41,13 +41,15 @@ function Autocomplete<T extends object>(
|
|
|
41
41
|
className,
|
|
42
42
|
width = 'full',
|
|
43
43
|
loadingState,
|
|
44
|
+
comboBoxState,
|
|
44
45
|
...props
|
|
45
46
|
}: AutocompleteProps<T>,
|
|
46
47
|
ref: ForwardedRef<HTMLInputElement>,
|
|
47
48
|
) {
|
|
48
49
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
49
50
|
const { contains } = useFilter({ sensitivity: 'base' });
|
|
50
|
-
const
|
|
51
|
+
const internalState = useComboBoxState({ isDisabled, ...props, defaultFilter: contains });
|
|
52
|
+
const state = comboBoxState ?? internalState;
|
|
51
53
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
52
54
|
const { isFocusVisible: isInputFocusVisible, focusProps: inputFocusProps } = useFocusRing();
|
|
53
55
|
const inputRef = React.useRef<HTMLInputElement>(null);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ComboBoxProps } from '@react-types/combobox';
|
|
2
2
|
import { type AriaLabelingProps } from '@react-types/shared';
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
|
+
import { ComboBoxState } from 'react-stately';
|
|
4
5
|
import { type VariantProps } from 'tailwind-variants';
|
|
5
6
|
|
|
6
7
|
import { HintProps, InputProps } from '../index.js';
|
|
@@ -63,5 +64,10 @@ export type AutocompleteProps<T extends object> = {
|
|
|
63
64
|
* Width of autocomplete
|
|
64
65
|
*/
|
|
65
66
|
width?: InputProps['width'];
|
|
67
|
+
/**
|
|
68
|
+
* Pass through comboBox state from consuming component. If not specified,
|
|
69
|
+
* will be handled internally.
|
|
70
|
+
*/
|
|
71
|
+
comboBoxState?: ComboBoxState<T>;
|
|
66
72
|
} & ComboBoxProps<T> &
|
|
67
73
|
AriaLabelingProps;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { CalendarDate, createCalendar } from '@internationalized/date';
|
|
4
|
+
import React, { ChangeEvent, useCallback, useMemo, useRef } from 'react';
|
|
5
|
+
import { useButton, useCalendar, useLocale } from 'react-aria';
|
|
6
|
+
import { useCalendarState } from 'react-stately';
|
|
7
|
+
|
|
8
|
+
import { Button } from '../../../button/index.js';
|
|
9
|
+
import { Circle } from '../../../circle/circle.component.js';
|
|
10
|
+
import { ArrowLeftIcon, ArrowRightIcon } from '../../../icon/index.js';
|
|
11
|
+
|
|
12
|
+
import { type CalendarProps } from './calendar.types.js';
|
|
13
|
+
import { CalendarGrid } from './components/calendar-grid/calendar-grid.component.js';
|
|
14
|
+
import { Select } from './components/select/select.component.js';
|
|
15
|
+
|
|
16
|
+
const MONTHS = Array.from({ length: 12 }, (_, i) => {
|
|
17
|
+
const date = new Date(2020, i, 1); // Year doesn't matter, use 2020 as a common year
|
|
18
|
+
const monthName = new Intl.DateTimeFormat('en', { month: 'short' }).format(date);
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
value: i + 1,
|
|
22
|
+
label: monthName,
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const YEAR_OFFSET = 10;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
31
|
+
export function Calendar({ value, ...props }: CalendarProps) {
|
|
32
|
+
const { locale } = useLocale();
|
|
33
|
+
const refPrevButton = useRef(null);
|
|
34
|
+
const refNextButton = useRef(null);
|
|
35
|
+
const state = useCalendarState({
|
|
36
|
+
createCalendar,
|
|
37
|
+
...props,
|
|
38
|
+
value,
|
|
39
|
+
locale,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const { calendarProps, prevButtonProps, nextButtonProps } = useCalendar({ value, ...props }, state);
|
|
43
|
+
const { buttonProps: newPrevButtonProps } = useButton(prevButtonProps, refPrevButton);
|
|
44
|
+
const { buttonProps: newNextButtonProps } = useButton(nextButtonProps, refNextButton);
|
|
45
|
+
|
|
46
|
+
const years = useMemo(() => {
|
|
47
|
+
const beginning = state.focusedDate.year - YEAR_OFFSET;
|
|
48
|
+
return Array.from({ length: 20 }, (_, i) => {
|
|
49
|
+
return {
|
|
50
|
+
value: beginning + i,
|
|
51
|
+
label: beginning + i,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}, [state.focusedDate.year]);
|
|
55
|
+
|
|
56
|
+
const handleMonthChange = useCallback(
|
|
57
|
+
(ev: ChangeEvent<HTMLSelectElement>) => {
|
|
58
|
+
state.setFocusedDate(new CalendarDate(state.focusedDate.year, +ev.target.value, state.focusedDate.day));
|
|
59
|
+
},
|
|
60
|
+
[state],
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const handleYearChange = useCallback(
|
|
64
|
+
(ev: ChangeEvent<HTMLSelectElement>) => {
|
|
65
|
+
state.setFocusedDate(new CalendarDate(+ev.target.value, state.focusedDate.month, state.focusedDate.day));
|
|
66
|
+
},
|
|
67
|
+
[state],
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<div {...calendarProps}>
|
|
72
|
+
<div className="flex items-center justify-between">
|
|
73
|
+
<div className="flex gap-3">
|
|
74
|
+
<Select onChange={handleMonthChange} value={state.visibleRange.start.month}>
|
|
75
|
+
{MONTHS.map(month => (
|
|
76
|
+
<option key={month.value} value={month.value}>
|
|
77
|
+
{month.label}
|
|
78
|
+
</option>
|
|
79
|
+
))}
|
|
80
|
+
</Select>
|
|
81
|
+
|
|
82
|
+
<Select onChange={handleYearChange} value={state.visibleRange.start.year}>
|
|
83
|
+
{years.map(year => (
|
|
84
|
+
<option key={year.value} value={year.value}>
|
|
85
|
+
{year.label}
|
|
86
|
+
</option>
|
|
87
|
+
))}
|
|
88
|
+
</Select>
|
|
89
|
+
</div>
|
|
90
|
+
<div className="flex gap-2">
|
|
91
|
+
<Button look="unstyled" {...newPrevButtonProps}>
|
|
92
|
+
<Circle className="bg-light">
|
|
93
|
+
<ArrowLeftIcon size="small" color="primary" />
|
|
94
|
+
</Circle>
|
|
95
|
+
</Button>
|
|
96
|
+
<Button look="unstyled" {...newNextButtonProps}>
|
|
97
|
+
<Circle className="bg-light">
|
|
98
|
+
<ArrowRightIcon size="small" color="primary" />
|
|
99
|
+
</Circle>
|
|
100
|
+
</Button>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<CalendarGrid state={state} firstDayOfWeek={props.firstDayOfWeek} />
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React, { useRef } from 'react';
|
|
3
|
+
import { useCalendarCell, useFocusVisible } from 'react-aria';
|
|
4
|
+
|
|
5
|
+
import { styles as calendarCellStyles } from './calendar-cell.styles.js';
|
|
6
|
+
import { CalendarCellProps } from './calendar-cell.types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
export function CalendarCell({ state, date }: CalendarCellProps) {
|
|
12
|
+
const ref = useRef(null);
|
|
13
|
+
const { isFocusVisible } = useFocusVisible();
|
|
14
|
+
const {
|
|
15
|
+
cellProps,
|
|
16
|
+
buttonProps,
|
|
17
|
+
isSelected,
|
|
18
|
+
isOutsideVisibleRange,
|
|
19
|
+
isDisabled,
|
|
20
|
+
isUnavailable,
|
|
21
|
+
formattedDate,
|
|
22
|
+
isFocused,
|
|
23
|
+
} = useCalendarCell({ date }, state, ref);
|
|
24
|
+
const isToday = buttonProps['aria-label']?.indexOf('Today') !== -1;
|
|
25
|
+
const styles = calendarCellStyles({
|
|
26
|
+
isSelected,
|
|
27
|
+
isFocused: isFocused && isFocusVisible,
|
|
28
|
+
isToday,
|
|
29
|
+
isDisabled,
|
|
30
|
+
isUnavailable,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<td {...cellProps}>
|
|
35
|
+
<div className={styles.base()}>
|
|
36
|
+
<div {...buttonProps} ref={ref} hidden={isOutsideVisibleRange} className={styles.text()}>
|
|
37
|
+
{formattedDate}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</td>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
export const styles = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: 'flex items-center justify-center',
|
|
6
|
+
text: 'size-6 rounded-full border border-white text-center leading-[2.125rem]',
|
|
7
|
+
},
|
|
8
|
+
variants: {
|
|
9
|
+
isDisabled: {
|
|
10
|
+
true: {
|
|
11
|
+
text: 'cursor-default line-through opacity-50',
|
|
12
|
+
},
|
|
13
|
+
false: {
|
|
14
|
+
text: 'hover:bg-primary/5',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
isUnavailable: {
|
|
18
|
+
true: {
|
|
19
|
+
text: 'cursor-default line-through opacity-50',
|
|
20
|
+
},
|
|
21
|
+
false: {},
|
|
22
|
+
},
|
|
23
|
+
isFocused: {
|
|
24
|
+
true: {
|
|
25
|
+
text: '!outline-offset-0 focus-outline',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
isToday: {
|
|
29
|
+
true: {
|
|
30
|
+
text: 'border-primary bg-primary/5',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
isSelected: {
|
|
34
|
+
true: {
|
|
35
|
+
text: 'bg-primary text-white hover:bg-primary',
|
|
36
|
+
},
|
|
37
|
+
false: 'bg-white',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AriaCalendarCellProps } from 'react-aria';
|
|
2
|
+
import { CalendarState, RangeCalendarState } from 'react-stately';
|
|
3
|
+
|
|
4
|
+
// import { styles } from './calendar-Cell.styles.js';
|
|
5
|
+
|
|
6
|
+
// type Variants = VariantProps<typeof styles>;
|
|
7
|
+
|
|
8
|
+
export type CalendarCellProps = AriaCalendarCellProps & { state: CalendarState | RangeCalendarState };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useCalendarGrid } from 'react-aria';
|
|
3
|
+
|
|
4
|
+
import { CalendarCell } from '../calendar-cell/calendar-cell.component.js';
|
|
5
|
+
|
|
6
|
+
import { CalendarGridProps } from './calendar-grid.types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
export function CalendarGrid({ state, weekdayStyle = 'short', ...props }: CalendarGridProps) {
|
|
12
|
+
const { gridProps, headerProps, weekDays, weeksInMonth } = useCalendarGrid({ weekdayStyle, ...props }, state);
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<table className="w-full" {...gridProps}>
|
|
16
|
+
<thead {...headerProps}>
|
|
17
|
+
<tr>
|
|
18
|
+
{weekDays.map((day, index) => (
|
|
19
|
+
<th key={index} className="text-text size-6 text-center text-[0.75rem] font-semibold leading-9">
|
|
20
|
+
{day.toUpperCase().slice(0, 2)}
|
|
21
|
+
</th>
|
|
22
|
+
))}
|
|
23
|
+
</tr>
|
|
24
|
+
</thead>
|
|
25
|
+
<tbody>
|
|
26
|
+
{[...new Array(weeksInMonth).keys()].map(weekIndex => (
|
|
27
|
+
<tr key={weekIndex}>
|
|
28
|
+
{state
|
|
29
|
+
.getDatesInWeek(weekIndex)
|
|
30
|
+
.map((date, i) => (date ? <CalendarCell key={i} state={state} date={date} /> : <td key={i} />))}
|
|
31
|
+
</tr>
|
|
32
|
+
))}
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
);
|
|
36
|
+
}
|
package/src/components/date-picker-beta/components/calendar/components/select/select.component.tsx
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useFocusRing } from 'react-aria';
|
|
3
|
+
|
|
4
|
+
import { ExpandMoreIcon } from '../../../../../icon/index.js';
|
|
5
|
+
|
|
6
|
+
import { styles as selectStyles } from './select.styles.js';
|
|
7
|
+
import { SelectProps } from './select.types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function Select({ ...props }: SelectProps) {
|
|
13
|
+
const { isFocusVisible, focusProps } = useFocusRing();
|
|
14
|
+
const styles = selectStyles({ isFocusVisible });
|
|
15
|
+
return (
|
|
16
|
+
<div className="relative">
|
|
17
|
+
<select {...focusProps} className={styles.base({ className: props.className })} {...props} />
|
|
18
|
+
<ExpandMoreIcon color="primary" size="small" className={styles.caret()} />
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
package/src/components/date-picker-beta/components/calendar/components/select/select.styles.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
export const styles = tv({
|
|
4
|
+
slots: {
|
|
5
|
+
base: '!typography-body-8 appearance-none border-none !bg-none pl-0 pr-4 font-semibold',
|
|
6
|
+
caret: 'pointer-events-none absolute right-0 top-1/2 -translate-y-1/2 touch-none',
|
|
7
|
+
},
|
|
8
|
+
variants: {
|
|
9
|
+
isFocusVisible: {
|
|
10
|
+
true: { base: 'focus-outline' },
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { useRef } from 'react';
|
|
4
|
+
import { mergeProps, useDateSegment, useFocusRing } from 'react-aria';
|
|
5
|
+
|
|
6
|
+
import { styles as dateSegmentStyles } from './date-segment.styles.js';
|
|
7
|
+
import { DateSegmentProps } from './date-segment.types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function DateSegment({ segment, state, separator, ...props }: DateSegmentProps) {
|
|
13
|
+
const ref = useRef(null);
|
|
14
|
+
const { focusProps, isFocusVisible } = useFocusRing();
|
|
15
|
+
const { segmentProps } = useDateSegment(segment, state, ref);
|
|
16
|
+
const styles = dateSegmentStyles({
|
|
17
|
+
isFocusVisible,
|
|
18
|
+
isPlaceholder: segment.isPlaceholder,
|
|
19
|
+
isSeparator: segmentProps.role !== 'spinbutton',
|
|
20
|
+
});
|
|
21
|
+
return (
|
|
22
|
+
<span {...props} {...mergeProps(focusProps, segmentProps)} ref={ref} className={styles}>
|
|
23
|
+
{segment.type === 'literal' ? separator || segment.text : segment.text}
|
|
24
|
+
</span>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
export const styles = tv(
|
|
4
|
+
{
|
|
5
|
+
base: 'font-light disabled:form-control-disabled',
|
|
6
|
+
variants: {
|
|
7
|
+
isPlaceholder: {
|
|
8
|
+
true: 'text-text-50 opacity-100',
|
|
9
|
+
false: '',
|
|
10
|
+
},
|
|
11
|
+
isFocusVisible: {
|
|
12
|
+
true: 'focus-outline',
|
|
13
|
+
false: '',
|
|
14
|
+
},
|
|
15
|
+
isSeparator: {
|
|
16
|
+
true: 'px-0.5 text-text-50',
|
|
17
|
+
false: '',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{ responsiveVariants: ['xsl', 'sm', 'md', 'lg', 'xl'] },
|
|
22
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createCalendar } from '@internationalized/date';
|
|
4
|
+
import React, { useRef } from 'react';
|
|
5
|
+
import { useDateField, useLocale } from 'react-aria';
|
|
6
|
+
import { useDateFieldState } from 'react-stately';
|
|
7
|
+
|
|
8
|
+
import { DateSegment } from './components/date-segment/date-segment.component.js';
|
|
9
|
+
import { type DateFieldProps } from './date-field.types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
export function DateField({ separator, ...props }: DateFieldProps) {
|
|
15
|
+
const { locale } = useLocale();
|
|
16
|
+
const state = useDateFieldState({
|
|
17
|
+
...props,
|
|
18
|
+
locale,
|
|
19
|
+
createCalendar,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const ref = useRef(null);
|
|
23
|
+
const { fieldProps } = useDateField(props, state, ref);
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div {...fieldProps} ref={ref}>
|
|
27
|
+
{state.segments.map((segment, i) => (
|
|
28
|
+
<DateSegment separator={separator} key={i} segment={segment} state={state} />
|
|
29
|
+
))}
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { useDialog } from 'react-aria';
|
|
3
|
+
|
|
4
|
+
import { DialogProps } from './dialog.types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
export function Dialog({ title, children, ...props }: DialogProps) {
|
|
10
|
+
const ref = useRef(null);
|
|
11
|
+
const { dialogProps, titleProps } = useDialog(props, ref);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div {...dialogProps} ref={ref} className="p-3">
|
|
15
|
+
{title && (
|
|
16
|
+
<h3 {...titleProps} style={{ marginTop: 0 }}>
|
|
17
|
+
{title}
|
|
18
|
+
</h3>
|
|
19
|
+
)}
|
|
20
|
+
{children}
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { Overlay, usePopover } from 'react-aria';
|
|
3
|
+
|
|
4
|
+
import { CloseIcon } from '../../../icon/index.js';
|
|
5
|
+
|
|
6
|
+
import { styles as popoverStyles } from './popover.styles.js';
|
|
7
|
+
import { PopoverProps } from './popover.types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export function Popover({ state, portalContainer, children, showAsBottomSheet, ...props }: PopoverProps) {
|
|
13
|
+
const ref = useRef(null);
|
|
14
|
+
const { popoverProps, underlayProps } = usePopover(
|
|
15
|
+
{ ...props, popoverRef: ref, containerPadding: 0, offset: 0 },
|
|
16
|
+
state,
|
|
17
|
+
);
|
|
18
|
+
const styles = popoverStyles({ showAsBottomSheet });
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Overlay portalContainer={portalContainer}>
|
|
22
|
+
<div {...underlayProps} className={styles.underlay()} />
|
|
23
|
+
<div {...popoverProps} ref={ref} className={styles.popover()}>
|
|
24
|
+
<div className={styles.header()}>
|
|
25
|
+
<p className={styles.headerLabel()}>Choose a date</p>
|
|
26
|
+
<button className={styles.closeButton()} onClick={() => state.close()} aria-label="Close window">
|
|
27
|
+
<CloseIcon color="primary" className="block" size="small" />
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
</Overlay>
|
|
33
|
+
);
|
|
34
|
+
}
|