@mackin.com/styleguide 10.2.2 → 10.2.4
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/index.d.ts +1 -1
- package/index.esm.js +52 -7
- package/index.js +52 -7
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -863,7 +863,7 @@ interface SliderProps<T extends SliderValue> {
|
|
|
863
863
|
innerTrackClassName?: string;
|
|
864
864
|
/** Styles applied to the floating handle text with using 'showValue'. */
|
|
865
865
|
sliderTextClassName?: string;
|
|
866
|
-
/**
|
|
866
|
+
/** Sets the aria-label value. */
|
|
867
867
|
ariaLabel?: (T extends number ? string : readonly string[] | undefined) | undefined;
|
|
868
868
|
}
|
|
869
869
|
declare const Slider: <T extends SliderValue>(p: SliderProps<T>) => React__default.JSX.Element;
|
package/index.esm.js
CHANGED
|
@@ -497,6 +497,45 @@ const Button = React.forwardRef((props, ref) => {
|
|
|
497
497
|
return content;
|
|
498
498
|
});
|
|
499
499
|
|
|
500
|
+
/* Type is not always determinable due to the nature of custom components in typescript. For example OmniLink will not have a type of "a" but rather "OmniLink" so we have to determine
|
|
501
|
+
if the child component is focusable based on certain properties on the control that are found on focusable components */
|
|
502
|
+
const isChildFocusable = (props, type) => {
|
|
503
|
+
if (props.tabIndex !== undefined && props.tabIndex !== null) {
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
if (props.onClick !== undefined || props.onValueChange !== undefined) { //button or select
|
|
507
|
+
return true;
|
|
508
|
+
}
|
|
509
|
+
if (props.href || props.cols || props.rows || props.maxLength) {
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
if ((type === 'button' || type === 'input' || type === 'select' || type === 'textarea') && !props.disabled) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
return false;
|
|
516
|
+
};
|
|
517
|
+
const TabIndexContainer = (props) => {
|
|
518
|
+
const processElement = (node) => {
|
|
519
|
+
if (!React__default.isValidElement(node)) {
|
|
520
|
+
return node;
|
|
521
|
+
}
|
|
522
|
+
let updatedNode = node;
|
|
523
|
+
// Use the props-based logic to check focusability
|
|
524
|
+
if (isChildFocusable(node.props, node.type)) {
|
|
525
|
+
updatedNode = React__default.cloneElement(node, { tabIndex: props.tabIndexValue });
|
|
526
|
+
}
|
|
527
|
+
// Recursively process children
|
|
528
|
+
if (updatedNode.props.children) {
|
|
529
|
+
const clonedChildren = React__default.Children.map(updatedNode.props.children, processElement);
|
|
530
|
+
updatedNode = React__default.cloneElement(updatedNode, {
|
|
531
|
+
children: clonedChildren,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
return updatedNode;
|
|
535
|
+
};
|
|
536
|
+
return (React__default.createElement(React__default.Fragment, null, React__default.Children.map(props.children, processElement)));
|
|
537
|
+
};
|
|
538
|
+
|
|
500
539
|
const accordianExpandTimeMs = 250;
|
|
501
540
|
const accordianMaxHeight = 1020;
|
|
502
541
|
const accordianTimingFunction = 'ease-in-out';
|
|
@@ -544,7 +583,7 @@ const Accordian = (props) => {
|
|
|
544
583
|
}
|
|
545
584
|
setOpen((_a = props.open) !== null && _a !== void 0 ? _a : false);
|
|
546
585
|
}, [props.open]);
|
|
547
|
-
return (React.createElement("div", { className: "accordian" },
|
|
586
|
+
return (React.createElement("div", { className: "accordian", "aria-expanded": open },
|
|
548
587
|
React.createElement(Button, { readOnly: props.disabled, variant: props.variant, className: cx(css({
|
|
549
588
|
display: 'flex',
|
|
550
589
|
alignItems: 'center',
|
|
@@ -563,7 +602,8 @@ const Accordian = (props) => {
|
|
|
563
602
|
}, rightIcon: !props.disabled ? React.createElement(Icon, { id: open ? 'collapse' : 'expand' }) : undefined },
|
|
564
603
|
React.createElement("span", null, props.header)),
|
|
565
604
|
React.createElement("div", { ref: content, className: cx('accordian__body', contentStyles) },
|
|
566
|
-
React.createElement("div", { className: expandedContentWrapperStyles },
|
|
605
|
+
React.createElement("div", { className: expandedContentWrapperStyles },
|
|
606
|
+
React.createElement(TabIndexContainer, { tabIndexValue: open ? 0 : -1 }, props.children)))));
|
|
567
607
|
};
|
|
568
608
|
const useAccordianState = (count, openIndex) => {
|
|
569
609
|
const [panels, setShowPanel] = React.useState(new Array(count).fill(false).map((b, i) => {
|
|
@@ -969,13 +1009,14 @@ const defaultMaxShownValues = 7;
|
|
|
969
1009
|
const buttonMarkerClass = 'ListItem__button';
|
|
970
1010
|
const defaultOnPickFocusMs = 100;
|
|
971
1011
|
const Autocomplete = (p) => {
|
|
972
|
-
var _a;
|
|
1012
|
+
var _a, _b;
|
|
973
1013
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
974
1014
|
const inputProps = __rest(p, ["value", "className", "inputWrapperClassName", "inputClassName", "listClassName", "listItemClassName", "listItemButtonClassName", "maxShownValues", "allowScroll", "options", "onPick", "onPickFocusWaitMs"]);
|
|
975
1015
|
const theme = useThemeSafely();
|
|
976
1016
|
const element = React.useRef(null);
|
|
977
1017
|
const input = React.useRef(null);
|
|
978
1018
|
const list = React.useRef(null);
|
|
1019
|
+
const [selectedResultIndex, setSelectedResultIndex] = React.useState();
|
|
979
1020
|
const maxShowValues = (_a = p.maxShownValues) !== null && _a !== void 0 ? _a : defaultMaxShownValues;
|
|
980
1021
|
const displayOptions = React.useMemo(() => {
|
|
981
1022
|
if (!p.allowScroll) {
|
|
@@ -994,10 +1035,12 @@ const Autocomplete = (p) => {
|
|
|
994
1035
|
if (direction === -1) {
|
|
995
1036
|
buttonIndex = displayOptions.length - 1;
|
|
996
1037
|
}
|
|
1038
|
+
setSelectedResultIndex(buttonIndex);
|
|
997
1039
|
return (_a = list.current) === null || _a === void 0 ? void 0 : _a.querySelector(`.${buttonMarkerClass}${buttonIndex}`);
|
|
998
1040
|
}
|
|
999
1041
|
else {
|
|
1000
1042
|
const nextIndex = fromIndex + direction;
|
|
1043
|
+
setSelectedResultIndex(nextIndex);
|
|
1001
1044
|
if (nextIndex >= displayOptions.length || nextIndex < 0) {
|
|
1002
1045
|
return (_b = input.current) !== null && _b !== void 0 ? _b : undefined;
|
|
1003
1046
|
}
|
|
@@ -1021,6 +1064,7 @@ const Autocomplete = (p) => {
|
|
|
1021
1064
|
if (p.round || theme.controls.borderRadius) {
|
|
1022
1065
|
listBorderRadius = theme.controls.borderRadius || '0.5rem';
|
|
1023
1066
|
}
|
|
1067
|
+
const id = (_b = p.id) !== null && _b !== void 0 ? _b : `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1024
1068
|
const onPickValue = (v) => {
|
|
1025
1069
|
var _a;
|
|
1026
1070
|
// the TextInput will not respond to outer value changes if it has focus.
|
|
@@ -1068,8 +1112,9 @@ const Autocomplete = (p) => {
|
|
|
1068
1112
|
}
|
|
1069
1113
|
}
|
|
1070
1114
|
(_c = p.onKeyDown) === null || _c === void 0 ? void 0 : _c.call(p, e);
|
|
1071
|
-
} })),
|
|
1072
|
-
|
|
1115
|
+
}, "aria-owns": id, "aria-expanded": !!displayOptions.length, "aria-autocomplete": "both", "aria-describedby": `${id}-aria-description` })),
|
|
1116
|
+
React.createElement("span", { id: `${id}-aria-description`, className: css({ display: "none" }) }, "When autocomplete results are available use up and down arrows to review and enter to select."),
|
|
1117
|
+
!!displayOptions.length && (React.createElement(List, { id: id, ref: list, role: "listbox", className: cx(css({
|
|
1073
1118
|
position: 'absolute',
|
|
1074
1119
|
width: '100%',
|
|
1075
1120
|
border: theme.controls.border,
|
|
@@ -1092,7 +1137,7 @@ const Autocomplete = (p) => {
|
|
|
1092
1137
|
}), p.listClassName) },
|
|
1093
1138
|
displayOptions.map((v, listItemIndex) => {
|
|
1094
1139
|
var _a;
|
|
1095
|
-
return (React.createElement(ListItem, { key: v, variant: "full", className: p.listItemClassName },
|
|
1140
|
+
return (React.createElement(ListItem, { key: v, variant: "full", className: p.listItemClassName, role: "option", "aria-selected": selectedResultIndex === listItemIndex },
|
|
1096
1141
|
React.createElement(Button, { title: ((_a = p.showOptionTextAsTitle) !== null && _a !== void 0 ? _a : true) ? v : undefined, onKeyDown: e => {
|
|
1097
1142
|
var _a, _b;
|
|
1098
1143
|
if (e.key === 'ArrowDown') {
|
|
@@ -4044,7 +4089,7 @@ const TabHeader = (p) => {
|
|
|
4044
4089
|
buttonContent = tab.name;
|
|
4045
4090
|
}
|
|
4046
4091
|
return (React.createElement("li", { key: index, className: cx(tabStyles, p.tabClassName) },
|
|
4047
|
-
React.createElement(Button, { disabled: tabsChanging, className: buttonStyles, variant: buttonVariant, title: title, readOnly: active, onClick: () => {
|
|
4092
|
+
React.createElement(Button, { "aria-role": "tab", "aria-selected": active, disabled: tabsChanging, className: buttonStyles, variant: buttonVariant, title: title, readOnly: active, onClick: () => {
|
|
4048
4093
|
const onChange = () => {
|
|
4049
4094
|
var _a;
|
|
4050
4095
|
setTabIndex(index);
|
package/index.js
CHANGED
|
@@ -515,6 +515,45 @@ const Button = React__namespace.forwardRef((props, ref) => {
|
|
|
515
515
|
return content;
|
|
516
516
|
});
|
|
517
517
|
|
|
518
|
+
/* Type is not always determinable due to the nature of custom components in typescript. For example OmniLink will not have a type of "a" but rather "OmniLink" so we have to determine
|
|
519
|
+
if the child component is focusable based on certain properties on the control that are found on focusable components */
|
|
520
|
+
const isChildFocusable = (props, type) => {
|
|
521
|
+
if (props.tabIndex !== undefined && props.tabIndex !== null) {
|
|
522
|
+
return true;
|
|
523
|
+
}
|
|
524
|
+
if (props.onClick !== undefined || props.onValueChange !== undefined) { //button or select
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
if (props.href || props.cols || props.rows || props.maxLength) {
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
if ((type === 'button' || type === 'input' || type === 'select' || type === 'textarea') && !props.disabled) {
|
|
531
|
+
return true;
|
|
532
|
+
}
|
|
533
|
+
return false;
|
|
534
|
+
};
|
|
535
|
+
const TabIndexContainer = (props) => {
|
|
536
|
+
const processElement = (node) => {
|
|
537
|
+
if (!React.isValidElement(node)) {
|
|
538
|
+
return node;
|
|
539
|
+
}
|
|
540
|
+
let updatedNode = node;
|
|
541
|
+
// Use the props-based logic to check focusability
|
|
542
|
+
if (isChildFocusable(node.props, node.type)) {
|
|
543
|
+
updatedNode = React.cloneElement(node, { tabIndex: props.tabIndexValue });
|
|
544
|
+
}
|
|
545
|
+
// Recursively process children
|
|
546
|
+
if (updatedNode.props.children) {
|
|
547
|
+
const clonedChildren = React.Children.map(updatedNode.props.children, processElement);
|
|
548
|
+
updatedNode = React.cloneElement(updatedNode, {
|
|
549
|
+
children: clonedChildren,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
return updatedNode;
|
|
553
|
+
};
|
|
554
|
+
return (React.createElement(React.Fragment, null, React.Children.map(props.children, processElement)));
|
|
555
|
+
};
|
|
556
|
+
|
|
518
557
|
const accordianExpandTimeMs = 250;
|
|
519
558
|
const accordianMaxHeight = 1020;
|
|
520
559
|
const accordianTimingFunction = 'ease-in-out';
|
|
@@ -562,7 +601,7 @@ const Accordian = (props) => {
|
|
|
562
601
|
}
|
|
563
602
|
setOpen((_a = props.open) !== null && _a !== void 0 ? _a : false);
|
|
564
603
|
}, [props.open]);
|
|
565
|
-
return (React__namespace.createElement("div", { className: "accordian" },
|
|
604
|
+
return (React__namespace.createElement("div", { className: "accordian", "aria-expanded": open },
|
|
566
605
|
React__namespace.createElement(Button, { readOnly: props.disabled, variant: props.variant, className: css.cx(css.css({
|
|
567
606
|
display: 'flex',
|
|
568
607
|
alignItems: 'center',
|
|
@@ -581,7 +620,8 @@ const Accordian = (props) => {
|
|
|
581
620
|
}, rightIcon: !props.disabled ? React__namespace.createElement(Icon, { id: open ? 'collapse' : 'expand' }) : undefined },
|
|
582
621
|
React__namespace.createElement("span", null, props.header)),
|
|
583
622
|
React__namespace.createElement("div", { ref: content, className: css.cx('accordian__body', contentStyles) },
|
|
584
|
-
React__namespace.createElement("div", { className: expandedContentWrapperStyles },
|
|
623
|
+
React__namespace.createElement("div", { className: expandedContentWrapperStyles },
|
|
624
|
+
React__namespace.createElement(TabIndexContainer, { tabIndexValue: open ? 0 : -1 }, props.children)))));
|
|
585
625
|
};
|
|
586
626
|
const useAccordianState = (count, openIndex) => {
|
|
587
627
|
const [panels, setShowPanel] = React__namespace.useState(new Array(count).fill(false).map((b, i) => {
|
|
@@ -987,13 +1027,14 @@ const defaultMaxShownValues = 7;
|
|
|
987
1027
|
const buttonMarkerClass = 'ListItem__button';
|
|
988
1028
|
const defaultOnPickFocusMs = 100;
|
|
989
1029
|
const Autocomplete = (p) => {
|
|
990
|
-
var _a;
|
|
1030
|
+
var _a, _b;
|
|
991
1031
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
992
1032
|
const inputProps = __rest(p, ["value", "className", "inputWrapperClassName", "inputClassName", "listClassName", "listItemClassName", "listItemButtonClassName", "maxShownValues", "allowScroll", "options", "onPick", "onPickFocusWaitMs"]);
|
|
993
1033
|
const theme = useThemeSafely();
|
|
994
1034
|
const element = React__namespace.useRef(null);
|
|
995
1035
|
const input = React__namespace.useRef(null);
|
|
996
1036
|
const list = React__namespace.useRef(null);
|
|
1037
|
+
const [selectedResultIndex, setSelectedResultIndex] = React__namespace.useState();
|
|
997
1038
|
const maxShowValues = (_a = p.maxShownValues) !== null && _a !== void 0 ? _a : defaultMaxShownValues;
|
|
998
1039
|
const displayOptions = React__namespace.useMemo(() => {
|
|
999
1040
|
if (!p.allowScroll) {
|
|
@@ -1012,10 +1053,12 @@ const Autocomplete = (p) => {
|
|
|
1012
1053
|
if (direction === -1) {
|
|
1013
1054
|
buttonIndex = displayOptions.length - 1;
|
|
1014
1055
|
}
|
|
1056
|
+
setSelectedResultIndex(buttonIndex);
|
|
1015
1057
|
return (_a = list.current) === null || _a === void 0 ? void 0 : _a.querySelector(`.${buttonMarkerClass}${buttonIndex}`);
|
|
1016
1058
|
}
|
|
1017
1059
|
else {
|
|
1018
1060
|
const nextIndex = fromIndex + direction;
|
|
1061
|
+
setSelectedResultIndex(nextIndex);
|
|
1019
1062
|
if (nextIndex >= displayOptions.length || nextIndex < 0) {
|
|
1020
1063
|
return (_b = input.current) !== null && _b !== void 0 ? _b : undefined;
|
|
1021
1064
|
}
|
|
@@ -1039,6 +1082,7 @@ const Autocomplete = (p) => {
|
|
|
1039
1082
|
if (p.round || theme.controls.borderRadius) {
|
|
1040
1083
|
listBorderRadius = theme.controls.borderRadius || '0.5rem';
|
|
1041
1084
|
}
|
|
1085
|
+
const id = (_b = p.id) !== null && _b !== void 0 ? _b : `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1042
1086
|
const onPickValue = (v) => {
|
|
1043
1087
|
var _a;
|
|
1044
1088
|
// the TextInput will not respond to outer value changes if it has focus.
|
|
@@ -1086,8 +1130,9 @@ const Autocomplete = (p) => {
|
|
|
1086
1130
|
}
|
|
1087
1131
|
}
|
|
1088
1132
|
(_c = p.onKeyDown) === null || _c === void 0 ? void 0 : _c.call(p, e);
|
|
1089
|
-
} })),
|
|
1090
|
-
|
|
1133
|
+
}, "aria-owns": id, "aria-expanded": !!displayOptions.length, "aria-autocomplete": "both", "aria-describedby": `${id}-aria-description` })),
|
|
1134
|
+
React__namespace.createElement("span", { id: `${id}-aria-description`, className: css.css({ display: "none" }) }, "When autocomplete results are available use up and down arrows to review and enter to select."),
|
|
1135
|
+
!!displayOptions.length && (React__namespace.createElement(List, { id: id, ref: list, role: "listbox", className: css.cx(css.css({
|
|
1091
1136
|
position: 'absolute',
|
|
1092
1137
|
width: '100%',
|
|
1093
1138
|
border: theme.controls.border,
|
|
@@ -1110,7 +1155,7 @@ const Autocomplete = (p) => {
|
|
|
1110
1155
|
}), p.listClassName) },
|
|
1111
1156
|
displayOptions.map((v, listItemIndex) => {
|
|
1112
1157
|
var _a;
|
|
1113
|
-
return (React__namespace.createElement(ListItem, { key: v, variant: "full", className: p.listItemClassName },
|
|
1158
|
+
return (React__namespace.createElement(ListItem, { key: v, variant: "full", className: p.listItemClassName, role: "option", "aria-selected": selectedResultIndex === listItemIndex },
|
|
1114
1159
|
React__namespace.createElement(Button, { title: ((_a = p.showOptionTextAsTitle) !== null && _a !== void 0 ? _a : true) ? v : undefined, onKeyDown: e => {
|
|
1115
1160
|
var _a, _b;
|
|
1116
1161
|
if (e.key === 'ArrowDown') {
|
|
@@ -4062,7 +4107,7 @@ const TabHeader = (p) => {
|
|
|
4062
4107
|
buttonContent = tab.name;
|
|
4063
4108
|
}
|
|
4064
4109
|
return (React__namespace.createElement("li", { key: index, className: css.cx(tabStyles, p.tabClassName) },
|
|
4065
|
-
React__namespace.createElement(Button, { disabled: tabsChanging, className: buttonStyles, variant: buttonVariant, title: title, readOnly: active, onClick: () => {
|
|
4110
|
+
React__namespace.createElement(Button, { "aria-role": "tab", "aria-selected": active, disabled: tabsChanging, className: buttonStyles, variant: buttonVariant, title: title, readOnly: active, onClick: () => {
|
|
4066
4111
|
const onChange = () => {
|
|
4067
4112
|
var _a;
|
|
4068
4113
|
setTabIndex(index);
|