@westpac/ui 0.56.0 → 0.57.0

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 (27) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/component-type.json +1 -1
  3. package/dist/components/button/button.styles.js +1 -1
  4. package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.component.js +0 -1
  5. package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.d.ts +2 -14
  6. package/dist/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.js +2 -6
  7. package/dist/components/date-picker-beta/components/date-field/date-field.component.d.ts +1 -1
  8. package/dist/components/date-picker-beta/components/date-field/date-field.component.js +3 -2
  9. package/dist/components/date-picker-beta/components/date-field/date-field.types.d.ts +1 -0
  10. package/dist/components/date-picker-beta/date-picker.component.js +11 -1
  11. package/dist/components/date-picker-beta/date-picker.styles.d.ts +45 -18
  12. package/dist/components/date-picker-beta/date-picker.styles.js +22 -13
  13. package/dist/components/date-picker-beta/date-picker.types.d.ts +6 -2
  14. package/dist/components/popover/components/panel/panel.hook.d.ts +2 -0
  15. package/dist/components/popover/components/panel/panel.hook.js +35 -13
  16. package/dist/css/westpac-ui.css +115 -352
  17. package/dist/css/westpac-ui.min.css +115 -352
  18. package/package.json +1 -1
  19. package/src/components/button/button.styles.ts +1 -1
  20. package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.component.tsx +0 -1
  21. package/src/components/date-picker-beta/components/date-field/components/date-segment/date-segment.styles.ts +2 -6
  22. package/src/components/date-picker-beta/components/date-field/date-field.component.tsx +2 -2
  23. package/src/components/date-picker-beta/components/date-field/date-field.types.ts +4 -1
  24. package/src/components/date-picker-beta/date-picker.component.tsx +14 -2
  25. package/src/components/date-picker-beta/date-picker.styles.ts +22 -14
  26. package/src/components/date-picker-beta/date-picker.types.ts +7 -3
  27. package/src/components/popover/components/panel/panel.hook.tsx +40 -23
@@ -33,7 +33,7 @@ export const styles = tv({
33
33
  base: 'border border-borderDark bg-light text-muted hover:bg-white active:bg-white'
34
34
  },
35
35
  link: {
36
- base: 'text-link underline'
36
+ base: 'text-link underline hover:no-underline'
37
37
  },
38
38
  unstyled: {
39
39
  base: 'p-0 text-left'
@@ -8,7 +8,6 @@ export function DateSegment({ segment, state, separator, ...props }) {
8
8
  const { segmentProps } = useDateSegment(segment, state, ref);
9
9
  const styles = dateSegmentStyles({
10
10
  isFocusVisible,
11
- isPlaceholder: segment.isPlaceholder,
12
11
  isSeparator: segmentProps.role !== 'spinbutton'
13
12
  });
14
13
  return React.createElement("span", {
@@ -1,8 +1,4 @@
1
1
  export declare const styles: import("tailwind-variants").TVReturnType<{
2
- isPlaceholder: {
3
- true: string;
4
- false: string;
5
- };
6
2
  isFocusVisible: {
7
3
  true: string;
8
4
  false: string;
@@ -11,13 +7,9 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
11
7
  true: string;
12
8
  false: string;
13
9
  };
14
- }, undefined, "font-light disabled:form-control-disabled focus:focus-outline", {
10
+ }, undefined, "uppercase disabled:form-control-disabled focus:focus-outline", {
15
11
  responsiveVariants: string[];
16
12
  }, {
17
- isPlaceholder: {
18
- true: string;
19
- false: string;
20
- };
21
13
  isFocusVisible: {
22
14
  true: string;
23
15
  false: string;
@@ -27,10 +19,6 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
27
19
  false: string;
28
20
  };
29
21
  }, undefined, import("tailwind-variants").TVReturnType<{
30
- isPlaceholder: {
31
- true: string;
32
- false: string;
33
- };
34
22
  isFocusVisible: {
35
23
  true: string;
36
24
  false: string;
@@ -39,6 +27,6 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
39
27
  true: string;
40
28
  false: string;
41
29
  };
42
- }, undefined, "font-light disabled:form-control-disabled focus:focus-outline", {
30
+ }, undefined, "uppercase disabled:form-control-disabled focus:focus-outline", {
43
31
  responsiveVariants: string[];
44
32
  }, unknown, unknown, undefined>>;
@@ -1,17 +1,13 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  export const styles = tv({
3
- base: 'font-light disabled:form-control-disabled focus:focus-outline',
3
+ base: 'uppercase disabled:form-control-disabled focus:focus-outline',
4
4
  variants: {
5
- isPlaceholder: {
6
- true: 'text-text-50 opacity-100',
7
- false: ''
8
- },
9
5
  isFocusVisible: {
10
6
  true: 'focus-outline',
11
7
  false: ''
12
8
  },
13
9
  isSeparator: {
14
- true: 'px-0.5 text-text-50',
10
+ true: 'px-0.5 text-text',
15
11
  false: ''
16
12
  }
17
13
  }
@@ -2,4 +2,4 @@ import { type DateFieldProps } from './date-field.types.js';
2
2
  /**
3
3
  * @private
4
4
  */
5
- export declare function DateField({ separator, ...props }: DateFieldProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function DateField({ separator, className, ...props }: DateFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,7 @@ import React, { useRef } from 'react';
4
4
  import { useDateField, useLocale } from 'react-aria';
5
5
  import { useDateFieldState } from 'react-stately';
6
6
  import { DateSegment } from './components/date-segment/date-segment.component.js';
7
- export function DateField({ separator, ...props }) {
7
+ export function DateField({ separator, className, ...props }) {
8
8
  const { locale } = useLocale();
9
9
  const state = useDateFieldState({
10
10
  ...props,
@@ -15,7 +15,8 @@ export function DateField({ separator, ...props }) {
15
15
  const { fieldProps } = useDateField(props, state, ref);
16
16
  return React.createElement("div", {
17
17
  ...fieldProps,
18
- ref: ref
18
+ ref: ref,
19
+ className: className
19
20
  }, state.segments.map((segment, i)=>React.createElement(DateSegment, {
20
21
  separator: separator,
21
22
  key: i,
@@ -1,4 +1,5 @@
1
1
  import { AriaDateFieldProps, DateValue } from 'react-aria';
2
2
  export type DateFieldProps<T extends DateValue = DateValue> = AriaDateFieldProps<T> & {
3
3
  separator?: string;
4
+ className?: string;
4
5
  };
@@ -57,6 +57,7 @@ export function DatePickerBeta({ size = 'medium', className, bottomSheetView = {
57
57
  size,
58
58
  isInvalid: state.isInvalid,
59
59
  isDisabled: props.isDisabled,
60
+ isReadOnly: props.isReadOnly,
60
61
  block
61
62
  });
62
63
  const breakpoint = useBreakpoint();
@@ -88,12 +89,21 @@ export function DatePickerBeta({ size = 'medium', className, bottomSheetView = {
88
89
  ...props,
89
90
  ...groupProps,
90
91
  ref: ref,
92
+ onBlur: (e)=>{
93
+ var _props_onBlur;
94
+ if (state.value) {
95
+ var _props_onBlur1;
96
+ return (_props_onBlur1 = props.onBlur) === null || _props_onBlur1 === void 0 ? void 0 : _props_onBlur1.call(props, e, state.value);
97
+ }
98
+ return (_props_onBlur = props.onBlur) === null || _props_onBlur === void 0 ? void 0 : _props_onBlur.call(props, e);
99
+ },
91
100
  className: styles.input({
92
101
  className
93
102
  })
94
103
  }, React.createElement(DateField, {
95
104
  separator: separator,
96
- ...fieldProps
105
+ ...fieldProps,
106
+ className: styles.dateField()
97
107
  }), React.createElement(Button, {
98
108
  look: "faint",
99
109
  className: styles.button(),
@@ -2,40 +2,49 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
2
2
  size: {
3
3
  small: {
4
4
  input: string;
5
- button: string;
5
+ dateField: string;
6
6
  };
7
7
  medium: {
8
8
  input: string;
9
- button: string;
9
+ dateField: string;
10
10
  };
11
11
  large: {
12
12
  input: string;
13
- button: string;
13
+ dateField: string;
14
14
  };
15
15
  xlarge: {
16
16
  input: string;
17
- button: string;
17
+ dateField: string;
18
18
  };
19
19
  };
20
20
  block: {
21
21
  true: {
22
22
  input: string;
23
+ dateField: string;
23
24
  };
24
25
  };
25
26
  isInvalid: {
26
27
  true: {
27
- input: string;
28
+ dateField: string;
29
+ button: string;
28
30
  };
29
31
  false: {};
30
32
  };
31
33
  isDisabled: {
32
34
  true: {
33
- input: string;
35
+ dateField: string;
36
+ };
37
+ false: {};
38
+ };
39
+ isReadOnly: {
40
+ true: {
41
+ dateField: string;
34
42
  };
35
43
  false: {};
36
44
  };
37
45
  }, {
38
46
  input: string;
47
+ dateField: string;
39
48
  button: string;
40
49
  }, undefined, {
41
50
  responsiveVariants: string[];
@@ -43,79 +52,97 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
43
52
  size: {
44
53
  small: {
45
54
  input: string;
46
- button: string;
55
+ dateField: string;
47
56
  };
48
57
  medium: {
49
58
  input: string;
50
- button: string;
59
+ dateField: string;
51
60
  };
52
61
  large: {
53
62
  input: string;
54
- button: string;
63
+ dateField: string;
55
64
  };
56
65
  xlarge: {
57
66
  input: string;
58
- button: string;
67
+ dateField: string;
59
68
  };
60
69
  };
61
70
  block: {
62
71
  true: {
63
72
  input: string;
73
+ dateField: string;
64
74
  };
65
75
  };
66
76
  isInvalid: {
67
77
  true: {
68
- input: string;
78
+ dateField: string;
79
+ button: string;
69
80
  };
70
81
  false: {};
71
82
  };
72
83
  isDisabled: {
73
84
  true: {
74
- input: string;
85
+ dateField: string;
86
+ };
87
+ false: {};
88
+ };
89
+ isReadOnly: {
90
+ true: {
91
+ dateField: string;
75
92
  };
76
93
  false: {};
77
94
  };
78
95
  }, {
79
96
  input: string;
97
+ dateField: string;
80
98
  button: string;
81
99
  }, import("tailwind-variants").TVReturnType<{
82
100
  size: {
83
101
  small: {
84
102
  input: string;
85
- button: string;
103
+ dateField: string;
86
104
  };
87
105
  medium: {
88
106
  input: string;
89
- button: string;
107
+ dateField: string;
90
108
  };
91
109
  large: {
92
110
  input: string;
93
- button: string;
111
+ dateField: string;
94
112
  };
95
113
  xlarge: {
96
114
  input: string;
97
- button: string;
115
+ dateField: string;
98
116
  };
99
117
  };
100
118
  block: {
101
119
  true: {
102
120
  input: string;
121
+ dateField: string;
103
122
  };
104
123
  };
105
124
  isInvalid: {
106
125
  true: {
107
- input: string;
126
+ dateField: string;
127
+ button: string;
108
128
  };
109
129
  false: {};
110
130
  };
111
131
  isDisabled: {
112
132
  true: {
113
- input: string;
133
+ dateField: string;
134
+ };
135
+ false: {};
136
+ };
137
+ isReadOnly: {
138
+ true: {
139
+ dateField: string;
114
140
  };
115
141
  false: {};
116
142
  };
117
143
  }, {
118
144
  input: string;
145
+ dateField: string;
119
146
  button: string;
120
147
  }, undefined, {
121
148
  responsiveVariants: string[];
@@ -1,42 +1,51 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  export const styles = tv({
3
3
  slots: {
4
- input: 'form-control flex items-center border-borderDark disabled:form-control-disabled',
5
- button: 'flex h-auto items-center justify-center rounded-l-none border-y-0 border-l border-r-0 border-l-borderDark bg-light'
4
+ input: 'form-control flex items-center border-0',
5
+ dateField: 'rounded rounded-r-none border border-r-0 border-borderDark',
6
+ button: 'flex items-center justify-center rounded-l-none border-borderDark bg-light'
6
7
  },
7
8
  variants: {
8
9
  size: {
9
10
  small: {
10
- input: 'form-control-small gap-1.5',
11
- button: '-my-0.5 -mr-1.5 mb-[-0.25rem] min-h-5 py-[0.25rem]'
11
+ input: 'max-h-5',
12
+ dateField: 'form-control-small h-5'
12
13
  },
13
14
  medium: {
14
- input: 'form-control-medium gap-2',
15
- button: 'my-[-0.3125rem] -mr-2 min-h-6 py-[0.3125rem]'
15
+ input: 'max-h-6',
16
+ dateField: 'form-control-medium h-6'
16
17
  },
17
18
  large: {
18
- input: 'form-control-large gap-2.5',
19
- button: 'my-[-0.5rem] -mr-2.5 min-h-7 py-[0.5rem]'
19
+ input: 'max-h-7',
20
+ dateField: 'form-control-large h-7'
20
21
  },
21
22
  xlarge: {
22
- input: 'form-control-xlarge gap-3',
23
- button: '-my-1.5 -mr-3 mb-[-0.625rem] min-h-8 py-1.5'
23
+ input: 'max-h-8',
24
+ dateField: 'form-control-xlarge h-8'
24
25
  }
25
26
  },
26
27
  block: {
27
28
  true: {
28
- input: 'w-full justify-between gap-0'
29
+ input: 'w-full gap-0',
30
+ dateField: 'w-full'
29
31
  }
30
32
  },
31
33
  isInvalid: {
32
34
  true: {
33
- input: 'border-danger'
35
+ dateField: 'border-danger',
36
+ button: 'border-danger border-l-borderDark'
34
37
  },
35
38
  false: {}
36
39
  },
37
40
  isDisabled: {
38
41
  true: {
39
- input: 'form-control-disabled'
42
+ dateField: 'form-control-disabled'
43
+ },
44
+ false: {}
45
+ },
46
+ isReadOnly: {
47
+ true: {
48
+ dateField: 'form-control-disabled'
40
49
  },
41
50
  false: {}
42
51
  }
@@ -1,11 +1,11 @@
1
- import { HTMLAttributes } from 'react';
1
+ import { HTMLAttributes, FocusEvent } from 'react';
2
2
  import { DateValue } from 'react-aria';
3
3
  import { DatePickerStateOptions } from 'react-stately';
4
4
  import { VariantProps } from 'tailwind-variants';
5
5
  import { Breakpoint } from '../../tailwind/constants/index.js';
6
6
  import { styles } from './date-picker.styles.js';
7
7
  type Variants = VariantProps<typeof styles>;
8
- export type DatePickerBetaProps<T extends DateValue = DateValue> = DatePickerStateOptions<T> & Omit<Variants, 'block'> & Omit<HTMLAttributes<HTMLDivElement>, 'invalid'> & {
8
+ export type DatePickerBetaProps<T extends DateValue = DateValue> = Omit<DatePickerStateOptions<T>, 'onBlur'> & Omit<Variants, 'block'> & Omit<HTMLAttributes<HTMLDivElement>, 'invalid' | 'onBlur'> & {
9
9
  /**
10
10
  * Allows the input to take the full width of its container.
11
11
  * @default false
@@ -29,6 +29,10 @@ export type DatePickerBetaProps<T extends DateValue = DateValue> = DatePickerSta
29
29
  * Separator character used in the date field. Defaults to "/".
30
30
  */
31
31
  separator?: string;
32
+ /**
33
+ * Custom onBlur that provides the regular event as the first parameter and the date value in the same format as onChange as the second.
34
+ */
35
+ onBlur?: (event: FocusEvent<Element, Element>, date?: T) => void;
32
36
  /**
33
37
  * Placement for the datepicker popover.
34
38
  * @default "bottom left"
@@ -1,9 +1,11 @@
1
+ import { RefObject } from 'react';
1
2
  import { PanelProps } from './panel.types.js';
2
3
  export type PanelHookProps = {
3
4
  placement: PanelProps['placement'];
4
5
  portal: PanelProps['portal'];
5
6
  state: PanelProps['state'];
6
7
  triggerRef: PanelProps['triggerRef'];
8
+ popoverRef?: RefObject<HTMLDivElement>;
7
9
  };
8
10
  /**
9
11
  * Custom hook to calculate the position of a popover panel relative to its trigger element.
@@ -1,34 +1,54 @@
1
- import { useMemo } from 'react';
2
- const PANEL_WIDTH_SIZE = 282;
3
- const getVerticalPositionPopover = (element)=>{
1
+ import { useEffect, useMemo, useState } from 'react';
2
+ const PANEL_WIDTH_SIZE = 300;
3
+ const getHorizontalPositionPopover = (element, screenWidth)=>{
4
4
  const triggerDOMRect = element.getBoundingClientRect();
5
- const offsetLeftToCenter = (PANEL_WIDTH_SIZE - ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.width) || 0) / 2) * -1;
5
+ const offsetLeftToCenter = (PANEL_WIDTH_SIZE - ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.width) || 0)) / 2 * -1;
6
6
  if (triggerDOMRect.left + offsetLeftToCenter <= 0) {
7
7
  return 'left';
8
8
  }
9
- if (triggerDOMRect.left + offsetLeftToCenter >= 0 && triggerDOMRect.right + offsetLeftToCenter * -1 <= window.innerWidth) {
9
+ if (triggerDOMRect.left + offsetLeftToCenter >= 0 && triggerDOMRect.right + offsetLeftToCenter * -1 <= screenWidth) {
10
10
  return 'center';
11
11
  }
12
- if (PANEL_WIDTH_SIZE + ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.left) || 0) >= window.innerWidth) {
12
+ if (PANEL_WIDTH_SIZE + ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.left) || 0) >= screenWidth) {
13
13
  return 'right';
14
14
  }
15
15
  };
16
- const getLeftOffsetPerVerticalPosition = (element)=>{
16
+ const getLeftOffsetPerHorizontalPosition = (element, screenWidth)=>{
17
17
  const triggerDOMRect = element.getBoundingClientRect();
18
- switch(getVerticalPositionPopover(element)){
18
+ const rightOffset = (PANEL_WIDTH_SIZE + ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.left) || 0) - screenWidth + (screenWidth - ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.right) || 0))) * -1;
19
+ switch(getHorizontalPositionPopover(element, screenWidth)){
19
20
  case 'center':
20
21
  return (PANEL_WIDTH_SIZE - ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.width) || 0)) / 2 * -1;
21
22
  case 'right':
22
- return (PANEL_WIDTH_SIZE + ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.left) || 0) - window.innerWidth + (window.innerWidth - ((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.right) || 0))) * -1;
23
+ if (triggerDOMRect.left + rightOffset <= 0) {
24
+ return rightOffset - (triggerDOMRect.left + rightOffset) + 16;
25
+ }
26
+ return rightOffset;
23
27
  default:
24
28
  return 0;
25
29
  }
26
30
  };
27
31
  export function usePanel({ state, placement = 'bottom', triggerRef, portal }) {
32
+ const [screenWidth, setScreenWidth] = useState(document.documentElement.clientWidth);
33
+ useEffect(()=>{
34
+ const handleResize = ()=>{
35
+ if (portal instanceof Element) {
36
+ setScreenWidth(portal.clientWidth);
37
+ } else {
38
+ setScreenWidth(document.documentElement.clientWidth);
39
+ }
40
+ };
41
+ window.addEventListener('resize', handleResize);
42
+ return ()=>{
43
+ window.removeEventListener('resize', handleResize);
44
+ };
45
+ }, [
46
+ portal
47
+ ]);
28
48
  const popoverPosition = useMemo(()=>{
29
49
  var _triggerRef_current;
30
50
  const triggerDOMRect = (_triggerRef_current = triggerRef.current) === null || _triggerRef_current === void 0 ? void 0 : _triggerRef_current.getBoundingClientRect();
31
- const leftOffset = triggerRef.current ? getLeftOffsetPerVerticalPosition(triggerRef.current) : 0;
51
+ const leftOffset = triggerRef.current ? getLeftOffsetPerHorizontalPosition(triggerRef.current, screenWidth) : 0;
32
52
  if (!portal) {
33
53
  switch(placement){
34
54
  case 'top':
@@ -63,18 +83,20 @@ export function usePanel({ state, placement = 'bottom', triggerRef, portal }) {
63
83
  placement,
64
84
  portal,
65
85
  triggerRef,
66
- state.isOpen
86
+ state.isOpen,
87
+ screenWidth
67
88
  ]);
68
89
  const arrowPosition = useMemo(()=>{
69
90
  var _triggerRef_current;
70
91
  const triggerDOMRect = (_triggerRef_current = triggerRef.current) === null || _triggerRef_current === void 0 ? void 0 : _triggerRef_current.getBoundingClientRect();
71
- const leftOffset = triggerRef.current ? getLeftOffsetPerVerticalPosition(triggerRef.current) * -1 : 0;
92
+ const leftOffset = triggerRef.current ? getLeftOffsetPerHorizontalPosition(triggerRef.current, screenWidth) * -1 : 0;
72
93
  return {
73
94
  left: `${((triggerDOMRect === null || triggerDOMRect === void 0 ? void 0 : triggerDOMRect.width) || 0) / 2 + leftOffset}px`
74
95
  };
75
96
  }, [
76
97
  triggerRef,
77
- state.isOpen
98
+ state.isOpen,
99
+ screenWidth
78
100
  ]);
79
101
  return {
80
102
  popoverPosition,