components-test-pb 0.0.6 → 0.0.7

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.
@@ -7,8 +7,9 @@ export type ButtonSize = 'small' | 'medium' | 'large';
7
7
  export type ButtonProps = ComponentProps<ButtonSlots> & {
8
8
  appearance?: 'secondary' | 'primary' | 'tertiary';
9
9
  disabled?: boolean;
10
+ disabledFocusable?: boolean;
10
11
  shape?: 'rounded' | 'circular' | 'square';
11
12
  size?: ButtonSize;
12
13
  };
13
14
  export type ButtonBaseProps = DistributiveOmit<ButtonProps, 'appearance' | 'size' | 'shape'>;
14
- export type ButtonState = ComponentState<ButtonSlots> & Required<Pick<ButtonProps, 'appearance' | 'disabled' | 'shape' | 'size'>>;
15
+ export type ButtonState = ComponentState<ButtonSlots> & Required<Pick<ButtonProps, 'appearance' | 'disabled' | 'disabledFocusable' | 'shape' | 'size'>>;
@@ -1,11 +1,19 @@
1
+ import { useARIAButtonProps } from '../../utilities/useARIAButtonProps.js';
1
2
  export const useButton = (props) => {
2
- const { appearance, shape, size, disabled, ...buttonProps } = props;
3
+ const { appearance, shape, size, disabled, disabledFocusable, ...buttonProps } = props;
4
+ const tag = (buttonProps.as ?? 'button');
5
+ const ariaButtonProps = useARIAButtonProps(tag, {
6
+ ...buttonProps,
7
+ disabled,
8
+ disabledFocusable,
9
+ });
3
10
  return {
4
11
  appearance: appearance ?? 'secondary',
5
12
  shape: shape ?? 'rounded',
6
13
  size: size ?? 'medium',
7
14
  disabled: disabled ?? false,
8
- components: { root: buttonProps.as ?? 'button' },
9
- root: { as: buttonProps.as ?? 'button', disabled: disabled ?? false, ...buttonProps },
15
+ disabledFocusable: disabledFocusable ?? false,
16
+ components: { root: tag },
17
+ root: { as: tag, ...ariaButtonProps },
10
18
  };
11
19
  };
@@ -102,7 +102,8 @@ export const useButtonStyles = (state) => {
102
102
  const rootBaseClassName = useRootBaseClassName();
103
103
  const rootStyles = useRootStyles();
104
104
  const rootDisabledStyles = useRootDisabledstyles();
105
- const { appearance, disabled, shape, size } = state;
106
- state.root.className = mergeClasses(buttonClassNames.root, rootBaseClassName, appearance && rootStyles[appearance], rootStyles[size], rootStyles[shape], disabled && rootDisabledStyles.base, appearance && disabled && rootDisabledStyles[appearance], state.root.className);
105
+ const { appearance, disabled, disabledFocusable, shape, size } = state;
106
+ const isDisabled = disabled || disabledFocusable;
107
+ state.root.className = mergeClasses(buttonClassNames.root, rootBaseClassName, appearance && rootStyles[appearance], rootStyles[size], rootStyles[shape], isDisabled && rootDisabledStyles.base, appearance && isDisabled && rootDisabledStyles[appearance], state.root.className);
107
108
  return state;
108
109
  };
package/dist/index.d.ts CHANGED
@@ -4,3 +4,5 @@ export { Button, useButton, renderButton, useButtonStyles } from './Components/B
4
4
  export type { ButtonSlots, ButtonProps, ButtonBaseProps, ButtonState } from './Components/Button/index.js';
5
5
  export * from './Types/compose/index.js';
6
6
  export * from './Types/utils/index.js';
7
+ export { useARIAButtonProps } from './utilities/index.js';
8
+ export type { ARIAButtonType, ARIAButtonProps, ARIAButtonResultProps } from './utilities/index.js';
package/dist/index.js CHANGED
@@ -2,3 +2,4 @@ export { Text, useText, renderText, useTextStyles } from './Components/Text/inde
2
2
  export { Button, useButton, renderButton, useButtonStyles } from './Components/Button/index.js';
3
3
  export * from './Types/compose/index.js';
4
4
  export * from './Types/utils/index.js';
5
+ export { useARIAButtonProps } from './utilities/index.js';
@@ -0,0 +1,2 @@
1
+ export { useARIAButtonProps } from './useARIAButtonProps.js';
2
+ export type { ARIAButtonType, ARIAButtonProps, ARIAButtonResultProps } from './useARIAButtonProps.js';
@@ -0,0 +1 @@
1
+ export { useARIAButtonProps } from './useARIAButtonProps.js';
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes } from '../Types/utils/types.js';
2
+ export type ARIAButtonType = 'button' | 'a' | 'div';
3
+ export type ARIAButtonProps<Tag extends ARIAButtonType = 'button'> = HTMLAttributes<HTMLElement> & {
4
+ disabled?: boolean;
5
+ disabledFocusable?: boolean;
6
+ } & (Tag extends 'a' ? {
7
+ href?: string;
8
+ } : {});
9
+ export type ARIAButtonResultProps<Tag extends ARIAButtonType = 'button'> = HTMLAttributes<HTMLElement> & {
10
+ disabled?: Tag extends 'button' ? '' | undefined : never;
11
+ 'aria-disabled'?: 'true';
12
+ role?: string;
13
+ tabIndex?: number;
14
+ href?: string;
15
+ };
16
+ export declare const useARIAButtonProps: <Tag extends ARIAButtonType>(tag: Tag, props?: ARIAButtonProps<Tag>) => ARIAButtonResultProps<Tag>;
@@ -0,0 +1,75 @@
1
+ const noop = () => { };
2
+ export const useARIAButtonProps = (tag, props = {}) => {
3
+ const { disabled, disabledFocusable, onClick, onKeyDown, onKeyUp, ...rest } = props;
4
+ const isDisabled = disabled || disabledFocusable;
5
+ const handleClick = (e) => {
6
+ if (isDisabled) {
7
+ e.preventDefault();
8
+ e.stopPropagation();
9
+ return;
10
+ }
11
+ onClick?.(e);
12
+ };
13
+ if (tag === 'button') {
14
+ const result = {
15
+ ...rest,
16
+ onClick: handleClick,
17
+ onKeyDown: isDisabled ? (e) => {
18
+ e.preventDefault();
19
+ e.stopPropagation();
20
+ } : onKeyDown,
21
+ onKeyUp: isDisabled ? (e) => {
22
+ e.preventDefault();
23
+ e.stopPropagation();
24
+ } : onKeyUp,
25
+ };
26
+ if (disabled && !disabledFocusable) {
27
+ result.disabled = '';
28
+ }
29
+ else if (disabledFocusable) {
30
+ result['aria-disabled'] = 'true';
31
+ }
32
+ return result;
33
+ }
34
+ const handleKeyDown = (e) => {
35
+ if (isDisabled) {
36
+ e.preventDefault();
37
+ e.stopPropagation();
38
+ return;
39
+ }
40
+ if (e.key === 'Enter') {
41
+ e.preventDefault();
42
+ e.target?.click();
43
+ }
44
+ onKeyDown?.(e);
45
+ };
46
+ const handleKeyUp = (e) => {
47
+ if (isDisabled) {
48
+ e.preventDefault();
49
+ e.stopPropagation();
50
+ return;
51
+ }
52
+ if (e.key === ' ') {
53
+ e.preventDefault();
54
+ e.target?.click();
55
+ }
56
+ onKeyUp?.(e);
57
+ };
58
+ const result = {
59
+ ...rest,
60
+ role: 'button',
61
+ onClick: handleClick,
62
+ onKeyDown: handleKeyDown,
63
+ onKeyUp: handleKeyUp,
64
+ };
65
+ if (isDisabled) {
66
+ result['aria-disabled'] = 'true';
67
+ if (tag === 'a') {
68
+ delete result.href;
69
+ }
70
+ }
71
+ if (!disabled || disabledFocusable) {
72
+ result.tabIndex = rest.tabIndex ?? 0;
73
+ }
74
+ return result;
75
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "components-test-pb",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -10,6 +10,7 @@ export type ButtonSize = 'small' | 'medium' | 'large';
10
10
  export type ButtonProps = ComponentProps<ButtonSlots> & {
11
11
  appearance?: 'secondary' | 'primary' | 'tertiary';
12
12
  disabled?: boolean;
13
+ disabledFocusable?: boolean;
13
14
  shape?: 'rounded' | 'circular' | 'square';
14
15
  size?: ButtonSize;
15
16
  };
@@ -20,6 +21,6 @@ export type ButtonState = ComponentState<ButtonSlots> &
20
21
  Required<
21
22
  Pick<
22
23
  ButtonProps,
23
- 'appearance' | 'disabled' | 'shape' | 'size'
24
+ 'appearance' | 'disabled' | 'disabledFocusable' | 'shape' | 'size'
24
25
  >
25
26
  >;
@@ -1,16 +1,27 @@
1
1
  import type { ButtonProps, ButtonState } from './Button.types.js';
2
+ import { useARIAButtonProps } from '../../utilities/useARIAButtonProps.js';
3
+ import type { ARIAButtonType } from '../../utilities/useARIAButtonProps.js';
2
4
 
3
5
  export const useButton = (props: ButtonProps): ButtonState => {
4
- const { appearance, shape, size, disabled, ...buttonProps } = props;
6
+ const { appearance, shape, size, disabled, disabledFocusable, ...buttonProps } = props;
7
+
8
+ const tag = (buttonProps.as ?? 'button') as ARIAButtonType;
9
+
10
+ const ariaButtonProps = useARIAButtonProps(tag, {
11
+ ...buttonProps,
12
+ disabled,
13
+ disabledFocusable,
14
+ });
5
15
 
6
16
  return {
7
17
  appearance: appearance ?? 'secondary',
8
18
  shape: shape ?? 'rounded',
9
19
  size: size ?? 'medium',
10
20
  disabled: disabled ?? false,
21
+ disabledFocusable: disabledFocusable ?? false,
11
22
 
12
- components: { root: buttonProps.as ?? 'button' },
23
+ components: { root: tag },
13
24
 
14
- root: { as: buttonProps.as ?? 'button', disabled: disabled ?? false, ...buttonProps } as ButtonState['root'],
25
+ root: { as: tag, ...ariaButtonProps } as ButtonState['root'],
15
26
  };
16
- };
27
+ };
@@ -130,7 +130,9 @@ export const useButtonStyles = (state: ButtonState): ButtonState => {
130
130
  const rootStyles = useRootStyles();
131
131
  const rootDisabledStyles = useRootDisabledstyles();
132
132
 
133
- const { appearance, disabled, shape, size } = state;
133
+ const { appearance, disabled, disabledFocusable, shape, size } = state;
134
+
135
+ const isDisabled = disabled || disabledFocusable;
134
136
 
135
137
  state.root.className = mergeClasses(
136
138
  buttonClassNames.root,
@@ -141,8 +143,8 @@ export const useButtonStyles = (state: ButtonState): ButtonState => {
141
143
  rootStyles[size],
142
144
  rootStyles[shape],
143
145
 
144
- disabled && rootDisabledStyles.base,
145
- appearance && disabled && rootDisabledStyles[appearance],
146
+ isDisabled && rootDisabledStyles.base,
147
+ appearance && isDisabled && rootDisabledStyles[appearance],
146
148
 
147
149
  state.root.className,
148
150
  );
package/src/index.ts CHANGED
@@ -26,4 +26,7 @@ export type {
26
26
  } from './Components/Button/index.js';
27
27
 
28
28
  export * from './Types/compose/index.js';
29
- export * from './Types/utils/index.js';
29
+ export * from './Types/utils/index.js';
30
+
31
+ export { useARIAButtonProps } from './utilities/index.js';
32
+ export type { ARIAButtonType, ARIAButtonProps, ARIAButtonResultProps } from './utilities/index.js';
@@ -0,0 +1,2 @@
1
+ export { useARIAButtonProps } from './useARIAButtonProps.js';
2
+ export type { ARIAButtonType, ARIAButtonProps, ARIAButtonResultProps } from './useARIAButtonProps.js';
@@ -0,0 +1,106 @@
1
+ import type { HTMLAttributes, IntrinsicElementKeys } from '../Types/utils/types.js';
2
+
3
+ export type ARIAButtonType = 'button' | 'a' | 'div';
4
+
5
+ export type ARIAButtonProps<Tag extends ARIAButtonType = 'button'> = HTMLAttributes<HTMLElement> & {
6
+ disabled?: boolean;
7
+ disabledFocusable?: boolean;
8
+ } & (Tag extends 'a' ? { href?: string } : {});
9
+
10
+ export type ARIAButtonResultProps<Tag extends ARIAButtonType = 'button'> = HTMLAttributes<HTMLElement> & {
11
+ disabled?: Tag extends 'button' ? '' | undefined : never;
12
+ 'aria-disabled'?: 'true';
13
+ role?: string;
14
+ tabIndex?: number;
15
+ href?: string;
16
+ };
17
+
18
+ const noop = () => { };
19
+
20
+ export const useARIAButtonProps = <Tag extends ARIAButtonType>(
21
+ tag: Tag,
22
+ props: ARIAButtonProps<Tag> = {} as ARIAButtonProps<Tag>,
23
+ ): ARIAButtonResultProps<Tag> => {
24
+ const { disabled, disabledFocusable, onClick, onKeyDown, onKeyUp, ...rest } = props as ARIAButtonProps & { href?: string };
25
+
26
+ const isDisabled = disabled || disabledFocusable;
27
+
28
+ const handleClick = (e: MouseEvent) => {
29
+ if (isDisabled) {
30
+ e.preventDefault();
31
+ e.stopPropagation();
32
+ return;
33
+ }
34
+ onClick?.(e);
35
+ };
36
+
37
+ if (tag === 'button') {
38
+ const result = {
39
+ ...rest,
40
+ onClick: handleClick,
41
+ onKeyDown: isDisabled ? (e: KeyboardEvent) => {
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+ } : onKeyDown,
45
+ onKeyUp: isDisabled ? (e: KeyboardEvent) => {
46
+ e.preventDefault();
47
+ e.stopPropagation();
48
+ } : onKeyUp,
49
+ } as ARIAButtonResultProps<Tag>;
50
+
51
+ if (disabled && !disabledFocusable) {
52
+ (result as any).disabled = '';
53
+ } else if (disabledFocusable) {
54
+ result['aria-disabled'] = 'true';
55
+ }
56
+
57
+ return result;
58
+ }
59
+
60
+ const handleKeyDown = (e: KeyboardEvent) => {
61
+ if (isDisabled) {
62
+ e.preventDefault();
63
+ e.stopPropagation();
64
+ return;
65
+ }
66
+ if (e.key === 'Enter') {
67
+ e.preventDefault();
68
+ (e.target as HTMLElement)?.click();
69
+ }
70
+ onKeyDown?.(e);
71
+ };
72
+
73
+ const handleKeyUp = (e: KeyboardEvent) => {
74
+ if (isDisabled) {
75
+ e.preventDefault();
76
+ e.stopPropagation();
77
+ return;
78
+ }
79
+ if (e.key === ' ') {
80
+ e.preventDefault();
81
+ (e.target as HTMLElement)?.click();
82
+ }
83
+ onKeyUp?.(e);
84
+ };
85
+
86
+ const result: ARIAButtonResultProps<Tag> = {
87
+ ...rest,
88
+ role: 'button',
89
+ onClick: handleClick,
90
+ onKeyDown: handleKeyDown,
91
+ onKeyUp: handleKeyUp,
92
+ } as ARIAButtonResultProps<Tag>;
93
+
94
+ if (isDisabled) {
95
+ result['aria-disabled'] = 'true';
96
+ if (tag === 'a') {
97
+ delete (result as any).href;
98
+ }
99
+ }
100
+
101
+ if (!disabled || disabledFocusable) {
102
+ result.tabIndex = rest.tabIndex ?? 0;
103
+ }
104
+
105
+ return result;
106
+ };