@aurora-ds/components 1.6.0 → 1.7.1

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/dist/esm/index.js CHANGED
@@ -952,13 +952,13 @@ const LINK_STYLES = createStyles((theme) => ({
952
952
  * In that case the component stays accessible: it gets `role="link"`,
953
953
  * `tabIndex={0}` and keyboard Enter support automatically.
954
954
  *
955
- * @example <Link href='/about'>About</Link>
956
- * @example <Link href='https://example.com' external>External site</Link>
957
- * @example <Link href='/profile' underline='always' startIcon={UserIcon}>Profile</Link>
958
- * @example <Link href='/terms' underline='none'>Terms</Link>
959
- * @example <Link onClick={() => navigate('/about')}>About (SPA)</Link>
955
+ * @example <Link href='/about' label='About' />
956
+ * @example <Link href='https://example.com' label='External site' external />
957
+ * @example <Link href='/profile' underline='always' startIcon={UserIcon} label='Profile' />
958
+ * @example <Link href='/terms' underline='none' label='Terms' />
959
+ * @example <Link onClick={() => navigate('/about')} label='About (SPA)' />
960
960
  */
961
- const Link = ({ ref, underline = 'hover', color = 'default', external = false, disabled = false, startIcon: StartIcon, endIcon: EndIcon, children, className, href, onClick, onKeyDown, ...rest }) => {
961
+ const Link = ({ ref, label, fontSize = 'sm', underline = 'hover', color = 'default', external = false, disabled = false, startIcon: StartIcon, endIcon: EndIcon, className, href, onClick, onKeyDown, ...rest }) => {
962
962
  // An <a> without href has no implicit ARIA role and is not focusable.
963
963
  // When used for SPA navigation (onClick only), we restore both behaviours.
964
964
  const hasHref = !!href;
@@ -984,7 +984,7 @@ const Link = ({ ref, underline = 'hover', color = 'default', external = false, d
984
984
  // With href: the browser handles focusability natively (no tabIndex needed).
985
985
  tabIndex: disabled ? -1 : (!hasHref ? 0 : undefined),
986
986
  // Without href: <a> has no implicit ARIA role — add role="link" explicitly.
987
- role: !hasHref ? 'link' : undefined, target: external ? '_blank' : undefined, rel: external ? 'noopener noreferrer' : undefined, onClick: handleClick, onKeyDown: handleKeyDown, ...rest, children: [StartIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(StartIcon, { width: '1em', height: '1em' }) })), children, EndIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(EndIcon, { width: '1em', height: '1em' }) }))] }));
987
+ role: !hasHref ? 'link' : undefined, target: external ? '_blank' : undefined, rel: external ? 'noopener noreferrer' : undefined, onClick: handleClick, onKeyDown: handleKeyDown, ...rest, children: [StartIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(StartIcon, { width: '1em', height: '1em' }) })), jsx(Text, { as: 'span', fontSize: fontSize, children: label }), EndIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(EndIcon, { width: '1em', height: '1em' }) }))] }));
988
988
  };
989
989
  Link.displayName = 'Link';
990
990
 
@@ -5652,7 +5652,13 @@ const DRAWER_STYLES = createStyles((theme) => ({
5652
5652
  * Keep in sync with themeBreakpoints.
5653
5653
  */
5654
5654
  const BREAKPOINTS = {
5655
- sm: 640};
5655
+ xs: 480,
5656
+ sm: 640,
5657
+ md: 768,
5658
+ lg: 1024,
5659
+ xl: 1280,
5660
+ '2xl': 1536,
5661
+ };
5656
5662
  /** Max-width media query strings (max = breakpoint - 1px). */
5657
5663
  const MEDIA_MAX = {
5658
5664
  sm: `max-width: ${BREAKPOINTS.sm - 1}px`};
@@ -6551,6 +6557,13 @@ const AlertContext = createContext({
6551
6557
  });
6552
6558
  const useAlertContext = () => useContext(AlertContext);
6553
6559
 
6560
+ const VARIANT_DISMISS_COLOR = {
6561
+ default: 'neutral',
6562
+ success: 'success',
6563
+ error: 'error',
6564
+ warning: 'warning',
6565
+ info: 'info',
6566
+ };
6554
6567
  const VARIANT_ICONS = {
6555
6568
  success: AlertSuccessIcon,
6556
6569
  error: AlertErrorIcon,
@@ -6563,7 +6576,7 @@ const isSvgComponent = (value) => typeof value === 'function';
6563
6576
  * Alert title row: renders the variant icon alongside the title text.
6564
6577
  * Must be used inside an `<Alert>` component.
6565
6578
  */
6566
- const AlertTitle = ({ children, icon }) => {
6579
+ const AlertTitle = ({ children, icon, onDismiss }) => {
6567
6580
  const { variant, accentColor } = useAlertContext();
6568
6581
  // Resolve which icon to render:
6569
6582
  // - custom icon prop always takes precedence over the built-in variant icon
@@ -6573,7 +6586,7 @@ const AlertTitle = ({ children, icon }) => {
6573
6586
  const ResolvedIcon = icon && isSvgComponent(icon) ? icon : (icon === undefined ? (builtInIcon ?? null) : null);
6574
6587
  const customNode = icon && !isSvgComponent(icon) ? icon : null;
6575
6588
  const hasIcon = ResolvedIcon !== null || customNode !== null;
6576
- return (jsxs(Stack, { flexDirection: 'row', alignItems: 'center', gap: 'sm', children: [hasIcon && (jsx(Stack, { flexShrink: 0, alignItems: 'center', color: accentColor, width: '1.25rem', height: '1.25rem', "aria-hidden": true, children: ResolvedIcon ? (jsx(ResolvedIcon, { width: 20, height: 20 })) : (customNode) })), jsx(Text, { fontWeight: 'semibold', fontSize: 'sm', color: accentColor, children: children })] }));
6589
+ return (jsxs(Stack, { flexDirection: 'row', alignItems: 'center', gap: 'sm', justifyContent: onDismiss ? 'space-between' : undefined, children: [jsxs(Stack, { flexDirection: 'row', alignItems: 'center', gap: 'sm', children: [hasIcon && (jsx(Stack, { flexShrink: 0, alignItems: 'center', color: accentColor, width: '1.25rem', height: '1.25rem', "aria-hidden": true, children: ResolvedIcon ? (jsx(ResolvedIcon, { width: 20, height: 20 })) : (customNode) })), jsx(Text, { fontWeight: 'semibold', fontSize: 'sm', color: accentColor, children: children })] }), onDismiss && (jsx(IconButton, { icon: CloseIcon, ariaLabel: 'Dismiss', variant: 'text', color: VARIANT_DISMISS_COLOR[variant], size: 'sm', onClick: onDismiss }))] }));
6577
6590
  };
6578
6591
  AlertTitle.displayName = 'Alert.Title';
6579
6592
 
@@ -6583,6 +6596,22 @@ AlertTitle.displayName = 'Alert.Title';
6583
6596
  const AlertBody = ({ children }) => (jsx(Text, { as: 'p', fontSize: 'sm', color: 'textSecondary', children: children }));
6584
6597
  AlertBody.displayName = 'Alert.Body';
6585
6598
 
6599
+ /**
6600
+ * Alert actions row: renders action elements (buttons, links…) at the bottom of an `<Alert>`.
6601
+ * Must be used inside an `<Alert>` component.
6602
+ *
6603
+ * @example
6604
+ * <Alert variant="error">
6605
+ * <Alert.Title>Something went wrong</Alert.Title>
6606
+ * <Alert.Body>Please try again.</Alert.Body>
6607
+ * <Alert.Actions>
6608
+ * <Button size="sm" variant="outlined" color="error">Retry</Button>
6609
+ * </Alert.Actions>
6610
+ * </Alert>
6611
+ */
6612
+ const AlertActions = ({ children }) => (jsx(Stack, { flexDirection: 'row', alignItems: 'center', flexWrap: 'wrap', justifyContent: 'end', gap: 'sm', paddingTop: 'xs', children: children }));
6613
+ AlertActions.displayName = 'Alert.Actions';
6614
+
6586
6615
  const VARIANT_TOKENS = {
6587
6616
  default: { backgroundColor: 'surfacePaper', borderColor: 'defaultMain', accentColor: 'defaultActive' },
6588
6617
  success: { backgroundColor: 'successSubtle', borderColor: 'successMain', accentColor: 'successActive' },
@@ -6624,6 +6653,7 @@ AlertBase.displayName = 'Alert';
6624
6653
  const Alert = AlertBase;
6625
6654
  Alert.Title = AlertTitle;
6626
6655
  Alert.Body = AlertBody;
6656
+ Alert.Actions = AlertActions;
6627
6657
 
6628
6658
  const TRANSITION = `${DEFAULT_TRANSITION_DURATION_MS}ms ease`;
6629
6659
  const DIALOG_STYLES = createStyles((theme) => ({
@@ -6670,12 +6700,18 @@ const DIALOG_STYLES = createStyles((theme) => ({
6670
6700
  transform: 'translateY(0)',
6671
6701
  },
6672
6702
  },
6673
- // Full-height variant on mobile (applied via `fullscreen` prop)
6703
+ // Full-viewport variant (applied via `fullscreen` prop — all screen sizes)
6674
6704
  panelFullscreen: {
6675
- [`@media (${MEDIA_MAX.sm})`]: {
6676
- height: '100dvh',
6677
- maxHeight: 'none',
6678
- },
6705
+ top: 0,
6706
+ left: 0,
6707
+ right: 0,
6708
+ bottom: 0,
6709
+ margin: 0,
6710
+ width: '100%',
6711
+ height: '100dvh',
6712
+ maxWidth: 'none',
6713
+ maxHeight: 'none',
6714
+ borderRadius: 0,
6679
6715
  },
6680
6716
  }), { id: 'dialog' });
6681
6717
 
@@ -6772,6 +6808,53 @@ const Dialog = DialogBase;
6772
6808
  Dialog.Header = DialogHeader;
6773
6809
  Dialog.Body = DialogBody;
6774
6810
 
6811
+ /**
6812
+ * Listens to a CSS media query string and returns whether it currently matches.
6813
+ *
6814
+ * @param query - A valid CSS media query string, e.g. `'(max-width: 639px)'`.
6815
+ * @returns `true` when the media query matches, `false` otherwise.
6816
+ *
6817
+ * @example
6818
+ * const isMobile = useMediaQuery('(max-width: 639px)')
6819
+ */
6820
+ const useMediaQuery = (query) => {
6821
+ const [matches, setMatches] = useState(() => {
6822
+ if (typeof window === 'undefined') {
6823
+ return false;
6824
+ }
6825
+ return window.matchMedia(query).matches;
6826
+ });
6827
+ useEffect(() => {
6828
+ if (typeof window === 'undefined') {
6829
+ return;
6830
+ }
6831
+ const mediaQueryList = window.matchMedia(query);
6832
+ setMatches(mediaQueryList.matches);
6833
+ const listener = (event) => setMatches(event.matches);
6834
+ mediaQueryList.addEventListener('change', listener);
6835
+ return () => mediaQueryList.removeEventListener('change', listener);
6836
+ }, [query]);
6837
+ return matches;
6838
+ };
6839
+ /**
6840
+ * Returns `true` when the viewport width is **below** the given breakpoint (mobile-first max).
6841
+ *
6842
+ * @param breakpoint - One of the Aurora breakpoints: `xs` | `sm` | `md` | `lg` | `xl` | `2xl`.
6843
+ *
6844
+ * @example
6845
+ * const isMobile = useBreakpointMax('sm') // true when width < 640px
6846
+ */
6847
+ const useBreakpointMax = (breakpoint) => useMediaQuery(`(max-width: ${BREAKPOINTS[breakpoint] - 1}px)`);
6848
+ /**
6849
+ * Returns `true` when the viewport width is **at or above** the given breakpoint.
6850
+ *
6851
+ * @param breakpoint - One of the Aurora breakpoints: `xs` | `sm` | `md` | `lg` | `xl` | `2xl`.
6852
+ *
6853
+ * @example
6854
+ * const isDesktop = useBreakpointMin('md') // true when width >= 768px
6855
+ */
6856
+ const useBreakpointMin = (breakpoint) => useMediaQuery(`(min-width: ${BREAKPOINTS[breakpoint]}px)`);
6857
+
6775
6858
  /**
6776
6859
  * Manages keyboard navigation for a listbox-style menu.
6777
6860
  *
@@ -7241,5 +7324,5 @@ const darkTheme = createTheme({
7241
7324
  breakpoints: themeBreakpoints,
7242
7325
  });
7243
7326
 
7244
- export { Accordion, Alert, Article, Aside, Avatar, AvatarGroup, Backdrop, Badge, Box, Breadcrumb, Button, Card, Checkbox, DatePicker, DefaultErrorFallback, Dialog, Drawer, ErrorBoundary, Fab, Footer, Form, Grid, Header, Icon, IconButton, Image, InfoBubble, Link, LoaderScreen, Main, Menu, Nav, Pagination, RadioButton, RadioGroup, Section, Select, Separator, Skeleton, Stack, SvgImage, Switch, Table, Tabs, Text, TextField, ToggleButton, ToggleGroup, ToggleIconButton, Tooltip, darkTheme, lightTheme, useBodyScrollLock, useControllableState, useDrawerContext, useFocusTrap, useKeyPress, useListKeyNav, useMenuPosition, useMergedRefs, useTooltipPosition, useTransitionRender };
7327
+ export { Accordion, Alert, Article, Aside, Avatar, AvatarGroup, Backdrop, Badge, Box, Breadcrumb, Button, Card, Checkbox, DatePicker, DefaultErrorFallback, Dialog, Drawer, ErrorBoundary, Fab, Footer, Form, Grid, Header, Icon, IconButton, Image, InfoBubble, Link, LoaderScreen, Main, Menu, Nav, Pagination, RadioButton, RadioGroup, Section, Select, Separator, Skeleton, Stack, SvgImage, Switch, Table, Tabs, Text, TextField, ToggleButton, ToggleGroup, ToggleIconButton, Tooltip, darkTheme, lightTheme, useBodyScrollLock, useBreakpointMax, useBreakpointMin, useControllableState, useDrawerContext, useFocusTrap, useKeyPress, useListKeyNav, useMediaQuery, useMenuPosition, useMergedRefs, useTooltipPosition, useTransitionRender };
7245
7328
  //# sourceMappingURL=index.js.map