@aurora-ds/components 0.22.5 → 0.23.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 (30) hide show
  1. package/dist/cjs/components/actions/button-toggle/ButtonToggle/ButtonToggle.d.ts +15 -0
  2. package/dist/cjs/components/actions/button-toggle/ButtonToggle/ButtonToggle.props.d.ts +48 -0
  3. package/dist/cjs/components/actions/button-toggle/ButtonToggle/ButtonToggle.styles.d.ts +4 -0
  4. package/dist/cjs/components/actions/button-toggle/ButtonToggle/index.d.ts +2 -0
  5. package/dist/cjs/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.d.ts +14 -0
  6. package/dist/cjs/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.props.d.ts +29 -0
  7. package/dist/cjs/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.styles.d.ts +3 -0
  8. package/dist/cjs/components/actions/button-toggle/ButtonToggleGroup/index.d.ts +2 -0
  9. package/dist/cjs/components/actions/button-toggle/index.d.ts +2 -0
  10. package/dist/cjs/components/forms/select/Select.props.d.ts +1 -0
  11. package/dist/cjs/components/forms/select/Select.styles.d.ts +1 -1
  12. package/dist/cjs/components/index.d.ts +1 -0
  13. package/dist/cjs/index.js +168 -4
  14. package/dist/cjs/index.js.map +1 -1
  15. package/dist/esm/components/actions/button-toggle/ButtonToggle/ButtonToggle.d.ts +15 -0
  16. package/dist/esm/components/actions/button-toggle/ButtonToggle/ButtonToggle.props.d.ts +48 -0
  17. package/dist/esm/components/actions/button-toggle/ButtonToggle/ButtonToggle.styles.d.ts +4 -0
  18. package/dist/esm/components/actions/button-toggle/ButtonToggle/index.d.ts +2 -0
  19. package/dist/esm/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.d.ts +14 -0
  20. package/dist/esm/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.props.d.ts +29 -0
  21. package/dist/esm/components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.styles.d.ts +3 -0
  22. package/dist/esm/components/actions/button-toggle/ButtonToggleGroup/index.d.ts +2 -0
  23. package/dist/esm/components/actions/button-toggle/index.d.ts +2 -0
  24. package/dist/esm/components/forms/select/Select.props.d.ts +1 -0
  25. package/dist/esm/components/forms/select/Select.styles.d.ts +1 -1
  26. package/dist/esm/components/index.d.ts +1 -0
  27. package/dist/esm/index.js +167 -5
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/index.d.ts +87 -2
  30. package/package.json +1 -1
@@ -0,0 +1,15 @@
1
+ import { FC } from 'react';
2
+ import { ButtonToggleProps } from '@components/actions/button-toggle/ButtonToggle/ButtonToggle.props';
3
+ /**
4
+ * ButtonToggle component
5
+ *
6
+ * A toggle button similar to IconButton but with active state.
7
+ * Uses only the 'text' variant style.
8
+ * Designed to be used within ButtonToggleGroup.
9
+ *
10
+ * **Colors:**
11
+ * - Active: primary (default) - customizable via activeTextColor
12
+ * - Inactive: textSecondary (default) - customizable via inactiveTextColor
13
+ */
14
+ declare const ButtonToggle: FC<ButtonToggleProps>;
15
+ export default ButtonToggle;
@@ -0,0 +1,48 @@
1
+ import { MouseEvent, ReactNode } from 'react';
2
+ import { IconButtonSizes, ThemeContract } from '@/interfaces';
3
+ export type ButtonToggleProps = {
4
+ /** Value to identify this toggle button */
5
+ value: string;
6
+ /** Button content (icon or text) */
7
+ children: ReactNode;
8
+ /** Click handler */
9
+ onClick?: (e: MouseEvent<HTMLButtonElement>, value: string) => void;
10
+ /** Active/pressed state */
11
+ active?: boolean;
12
+ /** Disabled state */
13
+ disabled?: boolean;
14
+ /** Custom text/icon color when active (default: primary) */
15
+ activeTextColor?: keyof ThemeContract['colors'];
16
+ /** Custom text/icon color when inactive (default: textSecondary) */
17
+ inactiveTextColor?: keyof ThemeContract['colors'];
18
+ /** Custom text/icon color (overrides activeTextColor and inactiveTextColor) */
19
+ textColor?: keyof ThemeContract['colors'];
20
+ /** Custom backgroundColor (overrides variant backgroundColor) */
21
+ backgroundColor?: keyof ThemeContract['colors'];
22
+ /** Custom hover backgroundColor (overrides variant hover backgroundColor) */
23
+ hoverBackgroundColor?: keyof ThemeContract['colors'];
24
+ /** Custom active backgroundColor (overrides variant active backgroundColor) */
25
+ activeBackgroundColor?: keyof ThemeContract['colors'];
26
+ /** Size of the button */
27
+ size?: IconButtonSizes;
28
+ /** Accessibility label for screen readers */
29
+ ariaLabel?: string;
30
+ /** ID of element that labels this button */
31
+ ariaLabelledBy?: string;
32
+ /** ID of element that describes this button */
33
+ ariaDescribedBy?: string;
34
+ /** ARIA role */
35
+ role?: string;
36
+ /** Tab index for keyboard navigation */
37
+ tabIndex?: number;
38
+ };
39
+ export type ButtonToggleStyleParams = {
40
+ active?: boolean;
41
+ size?: IconButtonSizes;
42
+ activeTextColor?: keyof ThemeContract['colors'];
43
+ inactiveTextColor?: keyof ThemeContract['colors'];
44
+ textColor?: keyof ThemeContract['colors'];
45
+ backgroundColor?: keyof ThemeContract['colors'];
46
+ hoverBackgroundColor?: keyof ThemeContract['colors'];
47
+ activeBackgroundColor?: keyof ThemeContract['colors'];
48
+ };
@@ -0,0 +1,4 @@
1
+ import { ButtonToggleStyleParams } from '@components/actions/button-toggle/ButtonToggle/ButtonToggle.props';
2
+ export declare const BUTTON_TOGGLE_STYLES: {
3
+ root: (args_0: ButtonToggleStyleParams) => string;
4
+ };
@@ -0,0 +1,2 @@
1
+ export { default as ButtonToggle } from './ButtonToggle';
2
+ export type { ButtonToggleProps } from './ButtonToggle.props';
@@ -0,0 +1,14 @@
1
+ import { FC } from 'react';
2
+ import { ButtonToggleGroupProps } from '@components/actions/button-toggle/ButtonToggleGroup/ButtonToggleGroup.props';
3
+ /**
4
+ * ButtonToggleGroup component
5
+ *
6
+ * Groups multiple ButtonToggle components together in a row without gaps.
7
+ * Manages exclusive selection (only one button can be active at a time).
8
+ *
9
+ * **Default Colors:**
10
+ * - Active buttons: primary
11
+ * - Inactive buttons: textSecondary
12
+ */
13
+ declare const ButtonToggleGroup: FC<ButtonToggleGroupProps>;
14
+ export default ButtonToggleGroup;
@@ -0,0 +1,29 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { IconButtonSizes, ThemeContract } from '@/interfaces';
3
+ import { ButtonToggleProps } from '@components/actions/button-toggle/ButtonToggle/ButtonToggle.props';
4
+ export type ButtonToggleGroupProps = {
5
+ /** Current selected value */
6
+ value?: string | null;
7
+ /** Change handler for value selection */
8
+ onChange?: (value: string | null) => void;
9
+ /** Children ButtonToggle components */
10
+ children: ReactNode;
11
+ /** If true, only one button can be active at a time */
12
+ exclusive?: boolean;
13
+ /** If true, at least one button must always be active (clicking the active button won't deselect it) */
14
+ required?: boolean;
15
+ /** Size of all buttons in the group */
16
+ size?: IconButtonSizes;
17
+ /** Custom text/icon color when active (default: primary) - applied to all children */
18
+ activeTextColor?: keyof ThemeContract['colors'];
19
+ /** Custom text/icon color when inactive (default: textSecondary) - applied to all children */
20
+ inactiveTextColor?: keyof ThemeContract['colors'];
21
+ /** Accessibility label for the group */
22
+ ariaLabel?: string;
23
+ /** ARIA role for the group */
24
+ role?: string;
25
+ };
26
+ export type ButtonToggleGroupStyleParams = {
27
+ size?: IconButtonSizes;
28
+ };
29
+ export type ButtonToggleChild = ReactElement<ButtonToggleProps>;
@@ -0,0 +1,3 @@
1
+ export declare const BUTTON_TOGGLE_GROUP_STYLES: {
2
+ root: () => string;
3
+ };
@@ -0,0 +1,2 @@
1
+ export { default as ButtonToggleGroup } from './ButtonToggleGroup';
2
+ export type { ButtonToggleGroupProps } from './ButtonToggleGroup.props';
@@ -0,0 +1,2 @@
1
+ export * from './ButtonToggle';
2
+ export * from './ButtonToggleGroup';
@@ -36,4 +36,5 @@ export type SelectProps = {
36
36
  export type SelectStyleParams = {
37
37
  disabled?: boolean;
38
38
  width?: string | number;
39
+ isOpen?: boolean;
39
40
  };
@@ -1,4 +1,4 @@
1
- import { SelectStyleParams } from '@components/forms/select/Select.props.ts';
1
+ import { SelectStyleParams } from '@components/forms/select/Select.props';
2
2
  /**
3
3
  * Select styles using createStyles from @aurora-ds/theme
4
4
  */
@@ -5,6 +5,7 @@ export * from '@components/data-display/avatar';
5
5
  export * from '@components/data-display/skeleton';
6
6
  export * from '@components/actions/button';
7
7
  export * from '@components/actions/icon-button';
8
+ export * from '@components/actions/button-toggle';
8
9
  export * from '@components/forms/form';
9
10
  export * from '@components/forms/input';
10
11
  export * from '@components/forms/textarea';
package/dist/cjs/index.js CHANGED
@@ -886,6 +886,167 @@ const IconButton = ({ icon, variant = 'contained', active = false, type = 'butto
886
886
  };
887
887
  IconButton.displayName = 'IconButton';
888
888
 
889
+ const BUTTON_TOGGLE_STYLES = theme.createStyles((theme) => {
890
+ const variantStyles = getButtonVariantStyles(theme);
891
+ const sizeStyles = getIconButtonSizeStyles();
892
+ const textVariant = variantStyles.text;
893
+ return {
894
+ root: ({ active = false, size = 'medium', activeTextColor = 'primary', inactiveTextColor = 'textSecondary', textColor, backgroundColor, hoverBackgroundColor, activeBackgroundColor }) => {
895
+ const sizeConfig = sizeStyles[size];
896
+ // Determine the text color based on active state
897
+ const finalTextColor = textColor
898
+ ? theme.colors[textColor]
899
+ : active
900
+ ? theme.colors[activeTextColor]
901
+ : theme.colors[inactiveTextColor];
902
+ const overrides = {
903
+ color: finalTextColor,
904
+ };
905
+ const backgroundOverride = backgroundColor ? { backgroundColor: theme.colors[backgroundColor] } : {};
906
+ const hoverBackgroundOverride = hoverBackgroundColor ? { backgroundColor: theme.colors[hoverBackgroundColor] } : {};
907
+ const activeBackgroundOverride = activeBackgroundColor ? { backgroundColor: theme.colors[activeBackgroundColor] } : {};
908
+ return {
909
+ display: 'inline-flex',
910
+ alignItems: 'center',
911
+ justifyContent: 'center',
912
+ boxSizing: 'border-box',
913
+ gap: theme.spacing.sm,
914
+ padding: theme.spacing[sizeConfig.padding],
915
+ borderRadius: 0, // No border radius for grouped buttons
916
+ cursor: 'pointer',
917
+ transition: `background-color ${theme.transition.fast}, color ${theme.transition.fast}`,
918
+ minHeight: sizeConfig.size,
919
+ maxHeight: sizeConfig.size,
920
+ minWidth: sizeConfig.size,
921
+ fontFamily: 'inherit',
922
+ ...textVariant.default,
923
+ ...(active && textVariant.pressed),
924
+ ':hover': {
925
+ ...textVariant.hover,
926
+ ...hoverBackgroundOverride,
927
+ },
928
+ ':active': {
929
+ ...textVariant.pressed,
930
+ ...activeBackgroundOverride,
931
+ },
932
+ ':disabled': textVariant.disabled,
933
+ ...overrides,
934
+ ...backgroundOverride,
935
+ };
936
+ },
937
+ };
938
+ });
939
+
940
+ /**
941
+ * ButtonToggle component
942
+ *
943
+ * A toggle button similar to IconButton but with active state.
944
+ * Uses only the 'text' variant style.
945
+ * Designed to be used within ButtonToggleGroup.
946
+ *
947
+ * **Colors:**
948
+ * - Active: primary (default) - customizable via activeTextColor
949
+ * - Inactive: textSecondary (default) - customizable via inactiveTextColor
950
+ */
951
+ const ButtonToggle = ({ value, children, active = false, onClick, disabled, activeTextColor, inactiveTextColor, textColor, backgroundColor, hoverBackgroundColor, activeBackgroundColor, size = 'medium', ariaLabel, ariaLabelledBy, ariaDescribedBy, role, tabIndex, }) => {
952
+ const handleClick = (e) => {
953
+ if (onClick) {
954
+ onClick(e, value);
955
+ }
956
+ };
957
+ return (jsxRuntime.jsx("button", { onClick: handleClick, disabled: disabled, type: 'button', className: BUTTON_TOGGLE_STYLES.root({
958
+ active,
959
+ size,
960
+ activeTextColor,
961
+ inactiveTextColor,
962
+ textColor,
963
+ backgroundColor,
964
+ hoverBackgroundColor,
965
+ activeBackgroundColor
966
+ }), "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-pressed": active, role: role, tabIndex: tabIndex, children: children }));
967
+ };
968
+ ButtonToggle.displayName = 'ButtonToggle';
969
+
970
+ const BUTTON_TOGGLE_GROUP_STYLES = theme.createStyles((theme) => {
971
+ return {
972
+ root: () => ({
973
+ display: 'inline-flex',
974
+ flexDirection: 'row',
975
+ gap: 0,
976
+ flexGrow: 0,
977
+ width: 'fit-content',
978
+ border: `1px solid ${theme.colors.border}`,
979
+ borderRadius: theme.radius.md,
980
+ overflow: 'hidden',
981
+ // First child - rounded left corners
982
+ '& > button:first-of-type': {
983
+ borderTopLeftRadius: theme.radius.md,
984
+ borderBottomLeftRadius: theme.radius.md,
985
+ },
986
+ // Last child - rounded right corners
987
+ '& > button:last-of-type': {
988
+ borderTopRightRadius: theme.radius.md,
989
+ borderBottomRightRadius: theme.radius.md,
990
+ },
991
+ // All children except last - border right
992
+ '& > button:not(:last-of-type)': {
993
+ borderRight: `1px solid ${theme.colors.border}`,
994
+ },
995
+ }),
996
+ };
997
+ });
998
+
999
+ /**
1000
+ * ButtonToggleGroup component
1001
+ *
1002
+ * Groups multiple ButtonToggle components together in a row without gaps.
1003
+ * Manages exclusive selection (only one button can be active at a time).
1004
+ *
1005
+ * **Default Colors:**
1006
+ * - Active buttons: primary
1007
+ * - Inactive buttons: textSecondary
1008
+ */
1009
+ const ButtonToggleGroup = ({ value, onChange, children, exclusive = true, required = false, size = 'medium', activeTextColor, inactiveTextColor, ariaLabel, role = 'group', }) => {
1010
+ const handleToggleClick = (_e, toggleValue) => {
1011
+ if (!onChange) {
1012
+ return;
1013
+ }
1014
+ if (exclusive) {
1015
+ // If required is true and clicking the currently active button, don't deselect
1016
+ if (required && value === toggleValue) {
1017
+ return;
1018
+ }
1019
+ // Toggle off if clicking the active button, otherwise set new value
1020
+ onChange(value === toggleValue ? null : toggleValue);
1021
+ }
1022
+ else {
1023
+ // Non-exclusive mode would need array value support
1024
+ onChange(toggleValue);
1025
+ }
1026
+ };
1027
+ return (jsxRuntime.jsx("div", { className: BUTTON_TOGGLE_GROUP_STYLES.root(), role: role, "aria-label": ariaLabel, children: React.Children.map(children, (child) => {
1028
+ if (!React.isValidElement(child)) {
1029
+ return child;
1030
+ }
1031
+ const toggleChild = child;
1032
+ return React.cloneElement(toggleChild, {
1033
+ ...toggleChild.props,
1034
+ active: exclusive ? value === toggleChild.props.value : toggleChild.props.active,
1035
+ size,
1036
+ activeTextColor: toggleChild.props.activeTextColor || activeTextColor,
1037
+ inactiveTextColor: toggleChild.props.inactiveTextColor || inactiveTextColor,
1038
+ onClick: (e, toggleValue) => {
1039
+ handleToggleClick(e, toggleValue);
1040
+ // Also call original onClick if provided
1041
+ if (toggleChild.props.onClick) {
1042
+ toggleChild.props.onClick(e, toggleValue);
1043
+ }
1044
+ },
1045
+ });
1046
+ }) }));
1047
+ };
1048
+ ButtonToggleGroup.displayName = 'ButtonToggleGroup';
1049
+
889
1050
  const FORM_STYLES = theme.createStyles(() => ({
890
1051
  root: {
891
1052
  display: 'contents',
@@ -1163,7 +1324,7 @@ var TextArea_default = React.memo(TextArea);
1163
1324
  * Select styles using createStyles from @aurora-ds/theme
1164
1325
  */
1165
1326
  const SELECT_STYLES = theme.createStyles((theme) => ({
1166
- root: ({ disabled = false, width }) => ({
1327
+ root: ({ disabled = false, width, isOpen = false }) => ({
1167
1328
  position: 'relative',
1168
1329
  display: 'inline-flex',
1169
1330
  alignItems: 'center',
@@ -1171,7 +1332,7 @@ const SELECT_STYLES = theme.createStyles((theme) => ({
1171
1332
  boxSizing: 'border-box',
1172
1333
  width: width ?? '100%',
1173
1334
  padding: `${theme.spacing.sm} ${theme.spacing.md}`,
1174
- border: `1px solid ${theme.colors.border}`,
1335
+ border: `1px solid ${isOpen ? theme.colors.primary : theme.colors.border}`,
1175
1336
  borderRadius: theme.radius.md,
1176
1337
  fontSize: theme.fontSize.md,
1177
1338
  fontFamily: 'inherit',
@@ -1192,7 +1353,7 @@ const SELECT_STYLES = theme.createStyles((theme) => ({
1192
1353
  cursor: 'not-allowed',
1193
1354
  opacity: theme.opacity.high
1194
1355
  }),
1195
- ...(!disabled && {
1356
+ ...(!disabled && !isOpen && {
1196
1357
  ':hover': {
1197
1358
  borderColor: theme.colors.primaryHover,
1198
1359
  },
@@ -1493,7 +1654,7 @@ const Select = ({ options, value, onChange, label, mandatory = false, placeholde
1493
1654
  onChange(selectedValue);
1494
1655
  setIsOpen(false);
1495
1656
  };
1496
- return (jsxRuntime.jsxs(Stack, { direction: 'column', gap: 'xs', align: 'stretch', width: width ?? '100%', children: [label && (jsxRuntime.jsxs(Stack, { direction: 'row', gap: 'xs', align: 'center', children: [jsxRuntime.jsx(Text, { variant: 'label', fontSize: 'sm', children: label }), mandatory && (jsxRuntime.jsx(Text, { variant: 'label', fontSize: 'sm', color: 'error', children: "*" }))] })), jsxRuntime.jsxs("div", { ref: triggerRef, className: SELECT_STYLES.root({ disabled, width }), onClick: handleTriggerClick, role: 'button', tabIndex: disabled ? -1 : 0, "aria-expanded": isOpen, "aria-haspopup": 'listbox', children: [jsxRuntime.jsx("div", { className: SELECT_STYLES.trigger, children: jsxRuntime.jsx(Text, { variant: 'p', maxLines: 1, color: selectedOption ? 'text' : 'textSecondary', children: selectedOption ? selectedOption.label : placeholder }) }), jsxRuntime.jsx(Icon, { children: jsxRuntime.jsx(ChevronDownIcon, {}) })] }), jsxRuntime.jsx(Menu, { anchor: isOpen ? triggerRef.current : null, onClose: handleClose, width: menuWidth, children: jsxRuntime.jsx(MenuGroup, { children: options.map(option => (jsxRuntime.jsx(SelectItem, { option: option, isSelected: option.value === value, onSelect: handleSelect }, option.value))) }) })] }));
1657
+ return (jsxRuntime.jsxs(Stack, { direction: 'column', gap: 'xs', align: 'stretch', width: width ?? '100%', children: [label && (jsxRuntime.jsxs(Stack, { direction: 'row', gap: 'xs', align: 'center', children: [jsxRuntime.jsx(Text, { variant: 'label', fontSize: 'sm', children: label }), mandatory && (jsxRuntime.jsx(Text, { variant: 'label', fontSize: 'sm', color: 'error', children: "*" }))] })), jsxRuntime.jsxs("div", { ref: triggerRef, className: SELECT_STYLES.root({ disabled, width, isOpen }), onClick: handleTriggerClick, role: 'button', tabIndex: disabled ? -1 : 0, "aria-expanded": isOpen, "aria-haspopup": 'listbox', children: [jsxRuntime.jsx("div", { className: SELECT_STYLES.trigger, children: jsxRuntime.jsx(Text, { variant: 'p', maxLines: 1, color: selectedOption ? 'text' : 'textSecondary', children: selectedOption ? selectedOption.label : placeholder }) }), jsxRuntime.jsx(Icon, { children: jsxRuntime.jsx(ChevronDownIcon, {}) })] }), jsxRuntime.jsx(Menu, { anchor: isOpen ? triggerRef.current : null, onClose: handleClose, width: menuWidth, children: jsxRuntime.jsx(MenuGroup, { children: options.map(option => (jsxRuntime.jsx(SelectItem, { option: option, isSelected: option.value === value, onSelect: handleSelect }, option.value))) }) })] }));
1497
1658
  };
1498
1659
  Select.displayName = 'Select';
1499
1660
 
@@ -2057,6 +2218,7 @@ const CARD_STYLES = theme.createStyles((theme) => ({
2057
2218
  width,
2058
2219
  height,
2059
2220
  maxHeight,
2221
+ overflowY: maxHeight ? 'auto' : undefined,
2060
2222
  gap: gap ? theme.spacing[gap] : undefined,
2061
2223
  borderRadius: theme.radius[radius],
2062
2224
  boxShadow: theme.shadows[shadow],
@@ -3405,6 +3567,8 @@ exports.BreadcrumbLink = BreadcrumbLink;
3405
3567
  exports.BreadcrumbPage = BreadcrumbPage;
3406
3568
  exports.BreadcrumbSeparator = BreadcrumbSeparator;
3407
3569
  exports.Button = Button;
3570
+ exports.ButtonToggle = ButtonToggle;
3571
+ exports.ButtonToggleGroup = ButtonToggleGroup;
3408
3572
  exports.Card = Card;
3409
3573
  exports.DatePicker = DatePicker_default;
3410
3574
  exports.DrawerItem = DrawerItem;