@mortenbrudvik/waveui 0.10.0 → 0.12.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.
- package/README.md +454 -74
- package/dist/components/button/Link.cjs +1 -1
- package/dist/components/button/Link.cjs.map +1 -1
- package/dist/components/button/Link.mjs +4 -4
- package/dist/components/button/Toolbar.cjs +1 -1
- package/dist/components/button/Toolbar.cjs.map +1 -1
- package/dist/components/button/Toolbar.mjs +25 -30
- package/dist/components/button/Toolbar.mjs.map +1 -1
- package/dist/components/button/Toolbar.navigation.cjs +2 -0
- package/dist/components/button/Toolbar.navigation.cjs.map +1 -0
- package/dist/components/button/Toolbar.navigation.mjs +17 -0
- package/dist/components/button/Toolbar.navigation.mjs.map +1 -0
- package/dist/components/data-display/Avatar.cjs +1 -1
- package/dist/components/data-display/Avatar.cjs.map +1 -1
- package/dist/components/data-display/Avatar.context.cjs +2 -0
- package/dist/components/data-display/Avatar.context.cjs.map +1 -0
- package/dist/components/data-display/Avatar.context.mjs +9 -0
- package/dist/components/data-display/Avatar.context.mjs.map +1 -0
- package/dist/components/data-display/Avatar.mjs +66 -61
- package/dist/components/data-display/Avatar.mjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.cjs +1 -1
- package/dist/components/data-display/AvatarGroup.cjs.map +1 -1
- package/dist/components/data-display/AvatarGroup.mjs +10 -10
- package/dist/components/data-display/InfoButton.cjs +1 -1
- package/dist/components/data-display/InfoButton.cjs.map +1 -1
- package/dist/components/data-display/InfoButton.mjs +12 -12
- package/dist/components/data-display/InteractionTag.cjs +2 -0
- package/dist/components/data-display/InteractionTag.cjs.map +1 -0
- package/dist/components/data-display/InteractionTag.mjs +234 -0
- package/dist/components/data-display/InteractionTag.mjs.map +1 -0
- package/dist/components/data-display/Tag.cjs +1 -1
- package/dist/components/data-display/Tag.cjs.map +1 -1
- package/dist/components/data-display/Tag.mjs +222 -90
- package/dist/components/data-display/Tag.mjs.map +1 -1
- package/dist/components/data-display/TagGroup.cjs +2 -0
- package/dist/components/data-display/TagGroup.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.cjs +2 -0
- package/dist/components/data-display/TagGroup.context.cjs.map +1 -0
- package/dist/components/data-display/TagGroup.context.mjs +113 -0
- package/dist/components/data-display/TagGroup.context.mjs.map +1 -0
- package/dist/components/data-display/TagGroup.mjs +149 -0
- package/dist/components/data-display/TagGroup.mjs.map +1 -0
- package/dist/components/data-display/tagStyles.cjs +2 -0
- package/dist/components/data-display/tagStyles.cjs.map +1 -0
- package/dist/components/data-display/tagStyles.mjs +108 -0
- package/dist/components/data-display/tagStyles.mjs.map +1 -0
- package/dist/components/feedback/Toaster.cjs +1 -1
- package/dist/components/feedback/Toaster.cjs.map +1 -1
- package/dist/components/feedback/Toaster.mjs +287 -255
- package/dist/components/feedback/Toaster.mjs.map +1 -1
- package/dist/components/input/Combobox.cjs +1 -1
- package/dist/components/input/Combobox.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.cjs +1 -1
- package/dist/components/input/Combobox.expand.cjs.map +1 -1
- package/dist/components/input/Combobox.expand.mjs +7 -7
- package/dist/components/input/Combobox.expand.mjs.map +1 -1
- package/dist/components/input/Combobox.mjs +176 -175
- package/dist/components/input/Combobox.mjs.map +1 -1
- package/dist/components/input/DatePicker.cjs +1 -1
- package/dist/components/input/DatePicker.cjs.map +1 -1
- package/dist/components/input/DatePicker.mjs +188 -187
- package/dist/components/input/DatePicker.mjs.map +1 -1
- package/dist/components/input/Dropdown.cjs +1 -1
- package/dist/components/input/Dropdown.cjs.map +1 -1
- package/dist/components/input/Dropdown.mjs +41 -40
- package/dist/components/input/Dropdown.mjs.map +1 -1
- package/dist/components/input/Option.cjs +1 -1
- package/dist/components/input/Option.cjs.map +1 -1
- package/dist/components/input/Option.mjs +101 -94
- package/dist/components/input/Option.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.cjs.map +1 -1
- package/dist/components/input/SwatchPicker.context.mjs.map +1 -1
- package/dist/components/input/SwatchPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.cjs +1 -1
- package/dist/components/input/TagPicker.cjs.map +1 -1
- package/dist/components/input/TagPicker.context.cjs +2 -0
- package/dist/components/input/TagPicker.context.cjs.map +1 -0
- package/dist/components/input/TagPicker.context.mjs +20 -0
- package/dist/components/input/TagPicker.context.mjs.map +1 -0
- package/dist/components/input/TagPicker.create.cjs +2 -0
- package/dist/components/input/TagPicker.create.cjs.map +1 -0
- package/dist/components/input/TagPicker.create.mjs +24 -0
- package/dist/components/input/TagPicker.create.mjs.map +1 -0
- package/dist/components/input/TagPicker.mjs +13 -279
- package/dist/components/input/TagPicker.mjs.map +1 -1
- package/dist/components/input/TagPicker.option.cjs +2 -0
- package/dist/components/input/TagPicker.option.cjs.map +1 -0
- package/dist/components/input/TagPicker.option.mjs +45 -0
- package/dist/components/input/TagPicker.option.mjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.cjs +2 -0
- package/dist/components/input/TagPicker.overflow.cjs.map +1 -0
- package/dist/components/input/TagPicker.overflow.mjs +153 -0
- package/dist/components/input/TagPicker.overflow.mjs.map +1 -0
- package/dist/components/input/TagPicker.parts.cjs +2 -0
- package/dist/components/input/TagPicker.parts.cjs.map +1 -0
- package/dist/components/input/TagPicker.parts.mjs +425 -0
- package/dist/components/input/TagPicker.parts.mjs.map +1 -0
- package/dist/components/input/TagPicker.root.cjs +2 -0
- package/dist/components/input/TagPicker.root.cjs.map +1 -0
- package/dist/components/input/TagPicker.root.mjs +417 -0
- package/dist/components/input/TagPicker.root.mjs.map +1 -0
- package/dist/components/input/TimePicker.cjs +1 -1
- package/dist/components/input/TimePicker.cjs.map +1 -1
- package/dist/components/input/TimePicker.mjs +156 -154
- package/dist/components/input/TimePicker.mjs.map +1 -1
- package/dist/components/layout/Accordion.cjs.map +1 -1
- package/dist/components/layout/Accordion.mjs.map +1 -1
- package/dist/components/navigation/Hamburger.cjs +2 -0
- package/dist/components/navigation/Hamburger.cjs.map +1 -0
- package/dist/components/navigation/Hamburger.mjs +54 -0
- package/dist/components/navigation/Hamburger.mjs.map +1 -0
- package/dist/components/navigation/Menu.popover.cjs +1 -1
- package/dist/components/navigation/Menu.popover.cjs.map +1 -1
- package/dist/components/navigation/Menu.popover.mjs +137 -127
- package/dist/components/navigation/Menu.popover.mjs.map +1 -1
- package/dist/components/navigation/Menu.root.cjs +1 -1
- package/dist/components/navigation/Menu.root.cjs.map +1 -1
- package/dist/components/navigation/Menu.root.mjs +4 -4
- package/dist/components/navigation/Nav.cjs +1 -1
- package/dist/components/navigation/Nav.cjs.map +1 -1
- package/dist/components/navigation/Nav.context.cjs +2 -0
- package/dist/components/navigation/Nav.context.cjs.map +1 -0
- package/dist/components/navigation/Nav.context.mjs +137 -0
- package/dist/components/navigation/Nav.context.mjs.map +1 -0
- package/dist/components/navigation/Nav.mjs +151 -258
- package/dist/components/navigation/Nav.mjs.map +1 -1
- package/dist/components/navigation/Nav.parts.cjs +2 -0
- package/dist/components/navigation/Nav.parts.cjs.map +1 -0
- package/dist/components/navigation/Nav.parts.mjs +77 -0
- package/dist/components/navigation/Nav.parts.mjs.map +1 -0
- package/dist/components/navigation/Nav.root.cjs +2 -0
- package/dist/components/navigation/Nav.root.cjs.map +1 -0
- package/dist/components/navigation/Nav.root.mjs +78 -0
- package/dist/components/navigation/Nav.root.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.cjs +2 -0
- package/dist/components/navigation/NavDrawer.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.cjs +2 -0
- package/dist/components/navigation/NavDrawer.context.cjs.map +1 -0
- package/dist/components/navigation/NavDrawer.context.mjs +11 -0
- package/dist/components/navigation/NavDrawer.context.mjs.map +1 -0
- package/dist/components/navigation/NavDrawer.mjs +179 -0
- package/dist/components/navigation/NavDrawer.mjs.map +1 -0
- package/dist/components/overlays/Dialog.cjs +1 -1
- package/dist/components/overlays/Dialog.cjs.map +1 -1
- package/dist/components/overlays/Dialog.mjs +188 -123
- package/dist/components/overlays/Dialog.mjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.cjs +1 -1
- package/dist/components/overlays/Dialog.shared.cjs.map +1 -1
- package/dist/components/overlays/Dialog.shared.mjs +157 -81
- package/dist/components/overlays/Dialog.shared.mjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.cjs +2 -0
- package/dist/components/overlays/Dialog.slots.cjs.map +1 -0
- package/dist/components/overlays/Dialog.slots.mjs +129 -0
- package/dist/components/overlays/Dialog.slots.mjs.map +1 -0
- package/dist/components/overlays/Drawer.cjs +1 -1
- package/dist/components/overlays/Drawer.cjs.map +1 -1
- package/dist/components/overlays/Drawer.context.cjs +2 -0
- package/dist/components/overlays/Drawer.context.cjs.map +1 -0
- package/dist/components/overlays/Drawer.context.mjs +29 -0
- package/dist/components/overlays/Drawer.context.mjs.map +1 -0
- package/dist/components/overlays/Drawer.mjs +12 -187
- package/dist/components/overlays/Drawer.mjs.map +1 -1
- package/dist/components/overlays/Drawer.panel.cjs +2 -0
- package/dist/components/overlays/Drawer.panel.cjs.map +1 -0
- package/dist/components/overlays/Drawer.panel.mjs +159 -0
- package/dist/components/overlays/Drawer.panel.mjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.cjs +2 -0
- package/dist/components/overlays/Drawer.parts.cjs.map +1 -0
- package/dist/components/overlays/Drawer.parts.mjs +152 -0
- package/dist/components/overlays/Drawer.parts.mjs.map +1 -0
- package/dist/components/overlays/Drawer.root.cjs +2 -0
- package/dist/components/overlays/Drawer.root.cjs.map +1 -0
- package/dist/components/overlays/Drawer.root.mjs +207 -0
- package/dist/components/overlays/Drawer.root.mjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.cjs +2 -0
- package/dist/components/overlays/Drawer.scroll.cjs.map +1 -0
- package/dist/components/overlays/Drawer.scroll.mjs +42 -0
- package/dist/components/overlays/Drawer.scroll.mjs.map +1 -0
- package/dist/components/overlays/Popover.cjs +1 -1
- package/dist/components/overlays/Popover.cjs.map +1 -1
- package/dist/components/overlays/Popover.mjs +173 -162
- package/dist/components/overlays/Popover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.mjs +96 -91
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/Tooltip.cjs +1 -1
- package/dist/components/overlays/Tooltip.cjs.map +1 -1
- package/dist/components/overlays/Tooltip.mjs +47 -47
- package/dist/components/overlays/Tooltip.mjs.map +1 -1
- package/dist/components/portal/Portal.cjs +1 -1
- package/dist/components/portal/Portal.cjs.map +1 -1
- package/dist/components/portal/Portal.mjs +5 -5
- package/dist/components/table/DataGrid.cjs +1 -1
- package/dist/components/table/DataGrid.cjs.map +1 -1
- package/dist/components/table/DataGrid.mjs +1 -1
- package/dist/hooks/useDismiss.cjs.map +1 -1
- package/dist/hooks/useDismiss.mjs.map +1 -1
- package/dist/hooks/useFocusTrap.cjs +1 -1
- package/dist/hooks/useFocusTrap.cjs.map +1 -1
- package/dist/hooks/useFocusTrap.mjs +115 -98
- package/dist/hooks/useFocusTrap.mjs.map +1 -1
- package/dist/hooks/useFocusVisible.cjs +2 -0
- package/dist/hooks/useFocusVisible.cjs.map +1 -0
- package/dist/hooks/useFocusVisible.mjs +49 -0
- package/dist/hooks/useFocusVisible.mjs.map +1 -0
- package/dist/hooks/useFocusableGroup.cjs +2 -0
- package/dist/hooks/useFocusableGroup.cjs.map +1 -0
- package/dist/hooks/useFocusableGroup.mjs +70 -0
- package/dist/hooks/useFocusableGroup.mjs.map +1 -0
- package/dist/hooks/useModalLayer.cjs +1 -1
- package/dist/hooks/useModalLayer.cjs.map +1 -1
- package/dist/hooks/useModalLayer.mjs +34 -21
- package/dist/hooks/useModalLayer.mjs.map +1 -1
- package/dist/hooks/useModalOpen.cjs +2 -0
- package/dist/hooks/useModalOpen.cjs.map +1 -0
- package/dist/hooks/useModalOpen.mjs +14 -0
- package/dist/hooks/useModalOpen.mjs.map +1 -0
- package/dist/hooks/usePopupPosition.cjs +1 -1
- package/dist/hooks/usePopupPosition.cjs.map +1 -1
- package/dist/hooks/usePopupPosition.mjs +82 -53
- package/dist/hooks/usePopupPosition.mjs.map +1 -1
- package/dist/hooks/useResolvedTarget.cjs +2 -0
- package/dist/hooks/useResolvedTarget.cjs.map +1 -0
- package/dist/hooks/useResolvedTarget.mjs +37 -0
- package/dist/hooks/useResolvedTarget.mjs.map +1 -0
- package/dist/hooks/useRestoreFocus.cjs +1 -1
- package/dist/hooks/useRestoreFocus.cjs.map +1 -1
- package/dist/hooks/useRestoreFocus.mjs +91 -78
- package/dist/hooks/useRestoreFocus.mjs.map +1 -1
- package/dist/hooks/useRovingGrid.cjs +1 -1
- package/dist/hooks/useRovingGrid.cjs.map +1 -1
- package/dist/hooks/useRovingGrid.mjs +8 -57
- package/dist/hooks/useRovingGrid.mjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.cjs +1 -1
- package/dist/hooks/useRovingTabIndex.cjs.map +1 -1
- package/dist/hooks/useRovingTabIndex.mjs +180 -121
- package/dist/hooks/useRovingTabIndex.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3070 -269
- package/dist/index.d.ts +3070 -269
- package/dist/index.mjs +127 -107
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +137 -77
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/icons.cjs +1 -1
- package/dist/lib/icons.cjs.map +1 -1
- package/dist/lib/icons.mjs +13 -6
- package/dist/lib/icons.mjs.map +1 -1
- package/dist/lib/layers.cjs +1 -1
- package/dist/lib/layers.cjs.map +1 -1
- package/dist/lib/layers.mjs +120 -111
- package/dist/lib/layers.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/styles/tokens.css +25 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/classNames.cjs"),i=require("
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/dev.cjs"),r=require("../../lib/classNames.cjs"),i=require("../../lib/styles.cjs"),a=require("./Button.semantics.cjs");let o=require("react");o=e.__toESM(o,1);let s=require("react/jsx-runtime");var c={inline:`text-primary underline not-disabled:not-aria-disabled:hover:decoration-2 focus-visible:decoration-2`,standalone:`font-semibold text-primary no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline`,subtle:`text-foreground no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline`},l=e=>{let{as:o,appearance:l,variant:u,disabled:d=!1,disabledFocusable:f=!1,className:p,onClick:m,onKeyDown:h,onKeyUp:g,onBlur:_,ref:v,...y}=e,b=n.resolveDeprecatedProp(`Link`,l,u,`variant`,`appearance`)??`inline`,x=o??`a`,{defaults:S,enforced:C,handlers:w}=a.useButtonSemantics({tag:typeof x==`string`?x:null,href:y.href,disabled:d,disabledFocusable:f,onClick:m,onKeyDown:h,onKeyUp:g,onBlur:_}),T={...y};for(let[e,t]of Object.entries(S))T[e]??=t;return(0,s.jsx)(x,{...T,...w,ref:v,className:t.cn(r.linkClassNames.root,`cursor-pointer transition-colors motion-reduce:transition-none`,i.focusRing,c[b],(d||f)&&`cursor-not-allowed opacity-50 aria-disabled:focus-visible:opacity-100`,p),...C})};l.displayName=`Link`,exports.Link=l;
|
|
2
2
|
//# sourceMappingURL=Link.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.cjs","names":["resolveDeprecatedProp","useButtonSemantics","cn","linkClassNames","focusRing","require_runtime","require_cn","require_dev","require_classNames","
|
|
1
|
+
{"version":3,"file":"Link.cjs","names":["resolveDeprecatedProp","useButtonSemantics","cn","linkClassNames","focusRing","require_runtime","require_cn","require_dev","require_classNames","require_styles","require_Button_semantics","react","react_jsx_runtime","appearanceClasses","Link","appearanceProp","rest","props","appearance","variant","Component","as","elementProps","key","value","defaults","handlers","disabled","disabledFocusable","className","enforced"],"sources":["../../../src/components/button/Link.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { linkClassNames } from '../../lib/classNames';\nimport { resolveDeprecatedProp } from '../../lib/dev';\nimport { focusRing } from '../../lib/styles';\nimport type { PolymorphicComponent, PolymorphicProps } from '../../lib/polymorphic';\nimport { useButtonSemantics } from './Button.semantics';\n\n/**\n * Color treatment of a {@link Link}.\n *\n * - `inline` (default): for links in running text. Always underlined (the underline thickens on\n * hover and focus), because the link color alone does not stand out enough from body text.\n * - `standalone`: semibold, underlined on hover/focus only. Use it only where the position or\n * container already marks the text as a link (a list of links, a card footer, navigation).\n * - `subtle`: foreground color, underlined on hover/focus only. It cannot be told apart from body\n * text, so never use it inside a paragraph; only where the context makes the link obvious.\n */\nexport type LinkAppearance = 'inline' | 'standalone' | 'subtle';\n\n/** @deprecated Use {@link LinkAppearance}. */\nexport type LinkVariant = LinkAppearance;\n\n/**\n * The Link's own props (the XOwnProps rule of `PolymorphicProps`: component-specific props only).\n * Every other prop comes from the rendered element (`as`, default `'a'`).\n */\nexport interface LinkOwnProps {\n /** Color treatment (see {@link LinkAppearance} for where each one may be used).\n * @default 'inline'\n */\n appearance?: LinkAppearance;\n /** @deprecated Use `appearance` (same values). */\n variant?: LinkVariant;\n /**\n * Makes the link unavailable. An `<a>` drops its `href` (no navigation by middle-click, the\n * context menu or drag), keeps `role=\"link\"` (`role=\"button\"` when it had no `href`), and gets\n * `aria-disabled=\"true\"`, `data-disabled` and `tabIndex={-1}` (none can be overridden); a custom\n * `as` (router link) gets the same attributes. Clicks, Enter and Space are prevented: your\n * `onClick` is not called and the click does not reach ancestor click handlers. `as=\"button\"`\n * uses the native `disabled` attribute.\n * @default false\n */\n disabled?: boolean;\n /**\n * Marks the link unavailable but keeps it focusable and in the tab order: for a toolbar item or\n * a disabled link that needs a Tooltip. Renders `aria-disabled=\"true\"`, `data-disabled` and\n * `data-disabled-focusable`; an `<a>` drops its `href`, keeps `role=\"link\"` (`role=\"button\"`\n * when it had no `href`) and gets `tabIndex={0}`, and `as=\"button\"` gets these attributes\n * instead of the native `disabled`.\n * Clicks, Enter and Space are prevented; your `onClick` is not called and the click does not\n * reach ancestor click handlers. Wins over `disabled` when both are set. In a `Toolbar` it stays\n * in the arrow-key order.\n * @default false\n */\n disabledFocusable?: boolean;\n}\n\n/**\n * Props of {@link Link} rendered as `C` (default `'a'`). `LinkProps` without a type argument is\n * the 0.4 name: the props of a Link rendered as an `<a>`, including `ref`.\n */\nexport type LinkProps<C extends React.ElementType = 'a'> = PolymorphicProps<C, LinkOwnProps>;\n\n/** The props the implementation reads, for any `as`. */\ntype LinkImplProps = LinkOwnProps &\n Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'onKeyDown' | 'onKeyUp'> & {\n as?: React.ElementType;\n ref?: React.Ref<HTMLElement>;\n /** The destination: without one, the anchor gets button semantics. */\n href?: string;\n onClick?: React.MouseEventHandler<HTMLElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLElement>;\n onKeyUp?: React.KeyboardEventHandler<HTMLElement>;\n };\n\nconst appearanceClasses: Record<LinkAppearance, string> = {\n inline:\n 'text-primary underline not-disabled:not-aria-disabled:hover:decoration-2 focus-visible:decoration-2',\n standalone:\n 'font-semibold text-primary no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline',\n subtle:\n 'text-foreground no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline',\n};\n\n/**\n * A hyperlink with Fluent link styling. Renders an `<a>` by default; `as` renders a router link\n * (`<Link as={RouterLink} to=\"/\">`) or a `<button>` styled as a link (`type=\"button\"` by default).\n *\n * - Without `href`, the `<a>` runs an action instead of navigating (\"Show more\"): it keeps its\n * element and gets `role=\"button\"`, a tab stop and Enter/Space activation (the consumer's\n * `role` and `tabIndex` win). A non-interactive `as` (`span`, `div`) is treated the same way;\n * any `href` string, `''` included, keeps the link semantics.\n *\n * @example\n * <p>Read the <Link href=\"/docs\">documentation</Link> first.</p>\n * <Link appearance=\"standalone\" href=\"/pricing\">See pricing</Link>\n * <Link onClick={showMore}>Show more</Link>\n */\nexport const Link: PolymorphicComponent<'a', LinkOwnProps> = (props) => {\n const {\n as,\n appearance: appearanceProp,\n variant,\n disabled = false,\n disabledFocusable = false,\n className,\n onClick,\n onKeyDown,\n onKeyUp,\n onBlur,\n ref,\n ...rest\n } = props as LinkImplProps;\n\n const appearance =\n resolveDeprecatedProp('Link', appearanceProp, variant, 'variant', 'appearance') ?? 'inline';\n\n const Component: React.ElementType = as ?? 'a';\n const tag = typeof Component === 'string' ? Component : null;\n // The activation semantics of Button: an `<a>` without `href` or a `span` is a button, and a\n // disabled link blocks its click (ancestors included), Enter and Space.\n const { defaults, enforced, handlers } = useButtonSemantics({\n tag,\n href: rest.href,\n disabled,\n disabledFocusable,\n onClick,\n onKeyDown,\n onKeyUp,\n onBlur,\n });\n\n // Defaults apply wherever the consumer's value is `undefined` or `null` (C-COMPOSE).\n const elementProps: Record<string, unknown> = { ...rest };\n for (const [key, value] of Object.entries(defaults)) elementProps[key] ??= value;\n\n return (\n <Component\n {...elementProps}\n {...handlers}\n ref={ref}\n className={cn(\n linkClassNames.root,\n 'cursor-pointer transition-colors motion-reduce:transition-none',\n focusRing,\n appearanceClasses[appearance],\n // Full opacity while a focusable disabled link shows its focus ring, which `opacity`\n // would dim below 3:1 (as for buttons).\n (disabled || disabledFocusable) &&\n 'cursor-not-allowed opacity-50 aria-disabled:focus-visible:opacity-100',\n className,\n )}\n {...enforced}\n />\n );\n};\n\nLink.displayName = 'Link';\n"],"mappings":"yTA4EA,IAAMa,EAAoD,CACxD,OACE,sGACF,WACE,iHACF,OACE,qGACJ,EAgBaC,EAAiD,GAAU,CACtE,GAAM,CACJ,KACA,WAAYC,EACZ,UACA,WAAW,GACX,oBAAoB,GACpB,YACA,UACA,YACA,UACA,SACA,MACA,GAAGC,GACDC,EAEEC,EACJlB,EAAAA,sBAAsB,OAAQe,EAAgBI,EAAS,UAAW,YAAY,GAAK,SAE/EC,EAA+BC,GAAM,IAIrC,CAAE,WAAU,WAAU,YAAapB,EAAAA,mBAAmB,CAC1D,IAJU,OAAOmB,GAAc,SAAWA,EAAY,KAKtD,KAAMJ,EAAK,KACX,WACA,oBACA,UACA,YACA,UACA,QACF,CAAC,EAGKM,EAAwC,CAAE,GAAGN,CAAK,EACxD,IAAK,GAAM,CAACO,EAAKC,KAAU,OAAO,QAAQC,CAAQ,EAAG,EAAaF,KAASC,EAE3E,OACE,EAAAZ,EAAA,IAAA,CAACQ,EAAD,CACE,GAAIE,EACJ,GAAII,EACC,MACL,UAAWxB,EAAAA,GACTC,EAAAA,eAAe,KACf,iEACAC,EAAAA,UACAS,EAAkBK,IAGjBS,GAAYC,IACX,wEACFC,CACF,EACA,GAAIC,CACL,CAAA,CAEL,EAEA,EAAK,YAAc"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { cn as e } from "../../lib/cn.mjs";
|
|
3
3
|
import { resolveDeprecatedProp as t } from "../../lib/dev.mjs";
|
|
4
4
|
import { linkClassNames as n } from "../../lib/classNames.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { focusRing as r } from "../../lib/styles.mjs";
|
|
6
|
+
import { useButtonSemantics as i } from "./Button.semantics.mjs";
|
|
7
7
|
import "react";
|
|
8
8
|
import { jsx as a } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/button/Link.tsx
|
|
@@ -12,7 +12,7 @@ var o = {
|
|
|
12
12
|
standalone: "font-semibold text-primary no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline",
|
|
13
13
|
subtle: "text-foreground no-underline not-disabled:not-aria-disabled:hover:underline focus-visible:underline"
|
|
14
14
|
}, s = (s) => {
|
|
15
|
-
let { as: c, appearance: l, variant: u, disabled: d = !1, disabledFocusable: f = !1, className: p, onClick: m, onKeyDown: h, onKeyUp: g, onBlur: _, ref: v, ...y } = s, b = t("Link", l, u, "variant", "appearance") ?? "inline", x = c ?? "a", { defaults: S, enforced: C, handlers: w } =
|
|
15
|
+
let { as: c, appearance: l, variant: u, disabled: d = !1, disabledFocusable: f = !1, className: p, onClick: m, onKeyDown: h, onKeyUp: g, onBlur: _, ref: v, ...y } = s, b = t("Link", l, u, "variant", "appearance") ?? "inline", x = c ?? "a", { defaults: S, enforced: C, handlers: w } = i({
|
|
16
16
|
tag: typeof x == "string" ? x : null,
|
|
17
17
|
href: y.href,
|
|
18
18
|
disabled: d,
|
|
@@ -27,7 +27,7 @@ var o = {
|
|
|
27
27
|
...T,
|
|
28
28
|
...w,
|
|
29
29
|
ref: v,
|
|
30
|
-
className: e(n.root, "cursor-pointer transition-colors motion-reduce:transition-none",
|
|
30
|
+
className: e(n.root, "cursor-pointer transition-colors motion-reduce:transition-none", r, o[b], (d || f) && "cursor-not-allowed opacity-50 aria-disabled:focus-visible:opacity-100", p),
|
|
31
31
|
...C
|
|
32
32
|
});
|
|
33
33
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/composeEventHandlers.cjs"),r=require("../../lib/classNames.cjs"),i=require("../../hooks/
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/composeEventHandlers.cjs"),r=require("../../lib/classNames.cjs"),i=require("../../hooks/useMergedRefs.cjs"),a=require("../../hooks/useCheckedValues.cjs"),o=require("./Toolbar.context.cjs"),s=require("./Toolbar.navigation.cjs"),c=require("./Toolbar.parts.cjs");let l=require("react");l=e.__toESM(l,1);let u=require("react/jsx-runtime");var d={"extra-small":`p-0.5`,small:`p-0.5`,medium:`p-1`,large:`p-1.5`,"extra-large":`p-2`},f=e=>{let{as:c,orientation:f=`horizontal`,size:p=`medium`,checkedValues:m,defaultCheckedValues:h,onCheckedValuesChange:g,className:_,ref:v,onKeyDown:y,onFocus:b,role:x,"aria-orientation":S,...C}=e,{containerProps:w}=s.useToolbarNavigation({orientation:f}),T=i.useMergedRefs(w.ref,v),E=a.useCheckedValues(m,h,g),D=o.useToolbarCheckableRegistry(),O=l.useMemo(()=>({orientation:f,size:p,checked:E,registerCheckable:D}),[f,p,E,D]),k=c??`div`;return(0,u.jsx)(o.ToolbarContext.Provider,{value:O,children:(0,u.jsx)(k,{"data-size":p,"data-orientation":f,...C,role:x??`toolbar`,"aria-orientation":S??f,ref:T,"data-roving-container":``,onKeyDown:n.composeEventHandlers(y,w.onKeyDown),onFocus:n.composeEventHandlers(b,w.onFocus,{checkDefaultPrevented:!1}),className:t.cn(r.toolbarClassNames.root,`inline-flex items-center gap-1 rounded border border-border`,d[p],f===`vertical`&&`flex-col items-stretch`,_)})})};f.displayName=`Toolbar`;var p=Object.assign(f,{Button:c.ToolbarButton,ToggleButton:c.ToolbarToggleButton,RadioGroup:c.ToolbarRadioGroup,RadioButton:c.ToolbarRadioButton,Group:c.ToolbarGroup,Divider:c.ToolbarDivider});exports.Toolbar=p,exports.ToolbarButton=c.ToolbarButton,exports.ToolbarDivider=c.ToolbarDivider,exports.ToolbarGroup=c.ToolbarGroup,exports.ToolbarRadioButton=c.ToolbarRadioButton,exports.ToolbarRadioGroup=c.ToolbarRadioGroup,exports.ToolbarToggleButton=c.ToolbarToggleButton;
|
|
2
2
|
//# sourceMappingURL=Toolbar.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.cjs","names":["useRovingTabIndex","useMergedRefs","useCheckedValues","useToolbarCheckableRegistry","React","ToolbarContext","composeEventHandlers","cn","toolbarClassNames","ToolbarButton","ToolbarToggleButton","ToolbarRadioGroup","ToolbarRadioButton","ToolbarGroup","ToolbarDivider","require_runtime","require_cn","require_composeEventHandlers","require_classNames","require_useRovingTabIndex","require_useMergedRefs","require_useCheckedValues","require_Toolbar_context","require_Toolbar_parts","react","react_jsx_runtime","TOOLBAR_ITEM_SELECTOR","toolbarPaddingClasses","ToolbarRoot","ariaOrientation","rest","props","mergedRef","containerProps","ref","checked","checkedValues","defaultCheckedValues","onCheckedValuesChange","registerCheckable","context","orientation","size","Component","as","role","onKeyDown","onFocus","className","Toolbar"],"sources":["../../../src/components/button/Toolbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { toolbarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport type { PolymorphicComponent, PolymorphicProps } from '../../lib/polymorphic';\nimport type { CheckedValues, CheckedValuesChangeHandler, Orientation, Size } from '../../lib/types';\nimport { useCheckedValues } from '../../hooks/useCheckedValues';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { ToolbarContext, useToolbarCheckableRegistry } from './Toolbar.context';\nimport type { ToolbarContextValue } from './Toolbar.context';\nimport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n} from './Toolbar.parts';\n\nexport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n};\nexport type {\n ToolbarButtonOwnProps,\n ToolbarButtonProps,\n ToolbarDividerProps,\n ToolbarGroupProps,\n ToolbarRadioButtonProps,\n ToolbarRadioGroupProps,\n ToolbarToggleButtonProps,\n} from './Toolbar.parts';\n\n/**\n * The Toolbar's own props (the XOwnProps rule of `PolymorphicProps`: component-specific props\n * only). Every other prop comes from the rendered element (`as`, default `'div'`). Give the\n * toolbar an `aria-label` (or `aria-labelledby`) that describes its purpose, e.g. \"Formatting\".\n */\nexport interface ToolbarOwnProps {\n /**\n * Layout and arrow-key axis: Left/Right move between items when horizontal (mirrored in RTL),\n * Up/Down when vertical. Exposed as `aria-orientation` and `data-orientation`.\n * @default 'horizontal'\n */\n orientation?: Orientation;\n /**\n * Default size of `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` (their\n * own `size` wins), and the toolbar's padding. Plain Buttons inside keep their own default.\n * Exposed as `data-size`.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Pressed `Toolbar.ToggleButton`s and checked `Toolbar.RadioButton`s, per group `name`\n * (controlled): `{ format: ['bold'], align: ['center'] }`.\n */\n checkedValues?: CheckedValues;\n /** Initial checked values for uncontrolled usage. @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when a toggle or radio changes them (only on change): the new checked values first,\n * then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`; always passed, typed optional until 1.0).\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n}\n\n/**\n * Props of {@link Toolbar} rendered as `C` (default `'div'`). `ToolbarProps` without a type\n * argument is the 0.4 name: the props of a Toolbar rendered as a `<div>`, including `ref`.\n */\nexport type ToolbarProps<C extends React.ElementType = 'div'> = PolymorphicProps<\n C,\n ToolbarOwnProps\n>;\n\n/** The props the implementation reads, for any `as`. */\ntype ToolbarImplProps = ToolbarOwnProps &\n React.HTMLAttributes<HTMLElement> & {\n as?: React.ElementType;\n ref?: React.Ref<HTMLElement>;\n };\n\n/**\n * Every focusable control a toolbar can contain, whatever component renders it. Matches that\n * cannot take focus (a `type=\"hidden\"` input, a control CSS hides) are dropped by the roving hook.\n */\nconst TOOLBAR_ITEM_SELECTOR =\n 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/** The toolbar's padding per size. */\nconst toolbarPaddingClasses: Record<Size, string> = {\n 'extra-small': 'p-0.5',\n small: 'p-0.5',\n medium: 'p-1',\n large: 'p-1.5',\n 'extra-large': 'p-2',\n};\n\n// The root of the Toolbar compound; its component JSDoc is on the `Toolbar` export below (C-DOCS).\nconst ToolbarRoot: PolymorphicComponent<'div', ToolbarOwnProps> = (props) => {\n const {\n as,\n orientation = 'horizontal',\n size = 'medium',\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n className,\n ref,\n onKeyDown,\n onFocus,\n role,\n 'aria-orientation': ariaOrientation,\n ...rest\n } = props as ToolbarImplProps;\n\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation,\n });\n const mergedRef = useMergedRefs<HTMLElement>(containerProps.ref, ref);\n\n const checked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const registerCheckable = useToolbarCheckableRegistry();\n const context = React.useMemo<ToolbarContextValue>(\n () => ({ orientation, size, checked, registerCheckable }),\n [orientation, size, checked, registerCheckable],\n );\n\n const Component: React.ElementType = as ?? 'div';\n // The role and `aria-orientation` defaults apply wherever the consumer's value is `undefined` or\n // `null` (as in Button), so a wrapper forwarding its own unset props keeps them.\n return (\n <ToolbarContext.Provider value={context}>\n <Component\n data-size={size}\n data-orientation={orientation}\n {...rest}\n role={role ?? 'toolbar'}\n aria-orientation={ariaOrientation ?? orientation}\n ref={mergedRef}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, containerProps.onKeyDown)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n className={cn(\n toolbarClassNames.root,\n 'inline-flex items-center gap-1 rounded border border-border',\n toolbarPaddingClasses[size],\n orientation === 'vertical' && 'flex-col items-stretch',\n className,\n )}\n />\n </ToolbarContext.Provider>\n );\n};\nToolbarRoot.displayName = 'Toolbar';\n\n/**\n * A container for a set of controls (APG Toolbar pattern): `role=\"toolbar\"`, one Tab stop, and\n * arrow-key navigation between its controls.\n *\n * - Works with any children (Buttons, ToggleButtons, links, inputs, value controls such as\n * Checkbox or Dropdown): the focusable controls are found in the DOM, and the Toolbar sets their\n * `tabIndex` itself (one `0`, the rest `-1`). The `type=\"hidden\"` input that a named value\n * control renders never counts as a control, and controls that CSS hides are skipped.\n * - Parts: `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` take the toolbar's\n * `size` (default `'medium'`) and the `subtle` appearance by default; `Toolbar.RadioGroup`,\n * `Toolbar.Group` and `Toolbar.Divider` lay them out. Plain Buttons keep their own defaults.\n * - State: the pressed `Toolbar.ToggleButton`s and the checked `Toolbar.RadioButton` of each\n * group live in `checkedValues`/`defaultCheckedValues`, per group `name`, and every change calls\n * `onCheckedValuesChange(checkedValues, details)`. The state is in the server HTML.\n * - Left/Right (Up/Down when `orientation=\"vertical\"`) move focus and wrap; Home/End jump to the\n * first/last control; Left/Right are mirrored in RTL. Natively disabled controls are skipped,\n * also when a child disables them on its own; `disabledFocusable` ones stay in the arrow-key\n * order (APG), so a Tooltip can explain why they are unavailable. The arrows never press a\n * toggle or check a radio: Space, Enter or a click does.\n * - The radios of a `Toolbar.RadioGroup` are part of that arrow-key order, and Up/Down (Left/Right\n * in a vertical toolbar) also move among them, wrapping inside the group.\n * - Tab returns to the last focused control. Focusing a nested composite (radio group, tab list)\n * or a text field, select, slider or spin button keeps the Tab stop where it was.\n * - Text fields, selects, sliders, spin buttons and editable comboboxes keep their own arrow keys\n * (the caret moves). A Dropdown (select-only combobox) does not: Left/Right move past it. It\n * keeps Up/Down, Home and End for its list, so in a vertical toolbar the arrows cannot leave it.\n * - Elements with their own `tabIndex={-1}` are left alone, and a nested composite widget (a\n * RadioGroup, a tab list, …; not `Toolbar.RadioGroup`) counts as one control that keeps its own\n * Tab stop and arrow keys.\n * - A Menu or Popover opened from a control keeps its own keys: arrows, Home and End pressed in\n * the popup never move focus back to the toolbar's controls.\n * - A consumer `onKeyDown` runs first; `event.preventDefault()` in it cancels the navigation.\n * - Renders `data-size` and `data-orientation`.\n *\n * React Server Components cannot dot into a client module: import the flat names\n * `ToolbarButton`, `ToolbarToggleButton`, `ToolbarRadioGroup`, `ToolbarRadioButton`,\n * `ToolbarGroup` and `ToolbarDivider` there; `Toolbar.Button` etc. work in client files.\n *\n * @example\n * <Toolbar aria-label=\"Formatting\" defaultCheckedValues={{ format: ['bold'], align: ['left'] }}>\n * <Toolbar.ToggleButton name=\"format\" value=\"bold\" icon={<BoldIcon />} aria-label=\"Bold\" />\n * <Toolbar.ToggleButton name=\"format\" value=\"code\" icon={<CodeIcon />} aria-label=\"Code\" />\n * <Toolbar.Divider />\n * <Toolbar.RadioGroup aria-label=\"Text alignment\">\n * <Toolbar.RadioButton name=\"align\" value=\"left\" icon={<AlignLeftIcon />} aria-label=\"Left\" />\n * <Toolbar.RadioButton name=\"align\" value=\"center\" icon={<AlignCenterIcon />} aria-label=\"Center\" />\n * </Toolbar.RadioGroup>\n * </Toolbar>\n */\nexport const Toolbar = /* @__PURE__ */ Object.assign(ToolbarRoot, {\n Button: ToolbarButton,\n ToggleButton: ToolbarToggleButton,\n RadioGroup: ToolbarRadioGroup,\n RadioButton: ToolbarRadioButton,\n Group: ToolbarGroup,\n Divider: ToolbarDivider,\n});\n"],"mappings":"gdA4FA,IAAM0B,EACJ,uEAGIC,EAA8C,CAClD,cAAe,QACf,MAAO,QACP,OAAQ,MACR,MAAO,QACP,cAAe,KACjB,EAGMC,EAA6D,GAAU,CAC3E,GAAM,CACJ,KACA,cAAc,aACd,OAAO,SACP,gBACA,uBACA,wBACA,YACA,MACA,YACA,UACA,OACA,mBAAoBC,EACpB,GAAGC,GACDC,EAEE,CAAE,kBAAmB/B,EAAAA,kBAAkB,CAC3C,aAAc0B,EACd,eAAgB,GAChB,QAAS,eACT,aACF,CAAC,EACKM,EAAY/B,EAAAA,cAA2BgC,EAAe,IAAKC,CAAG,EAE9DC,EAAUjC,EAAAA,iBAAiBkC,EAAeC,EAAsBC,CAAqB,EACrFC,EAAoBpC,EAAAA,4BAA4B,EAChDqC,EAAUpC,EAAM,aACb,CAAE,cAAa,OAAM,UAAS,mBAAkB,GACvD,CAACqC,EAAaC,EAAMP,EAASI,CAAiB,CAChD,EAEMI,EAA+BC,GAAM,MAG3C,OACE,EAAAnB,EAAA,IAAA,CAACpB,EAAAA,eAAe,SAAhB,CAAyB,MAAOmC,EAC9B,UAAA,EAAAf,EAAA,IAAA,CAACkB,EAAD,CACE,YAAWD,EACX,mBAAkBD,EAClB,GAAIX,EACJ,KAAMe,GAAQ,UACd,mBAAkBhB,GAAmBY,EACrC,IAAKT,EACL,wBAAsB,GACtB,UAAW1B,EAAAA,qBAAqBwC,EAAWb,EAAe,SAAS,EACnE,QAAS3B,EAAAA,qBAAqByC,EAASd,EAAe,QAAS,CAC7D,sBAAuB,EACzB,CAAC,EACD,UAAW1B,EAAAA,GACTC,EAAAA,kBAAkB,KAClB,8DACAmB,EAAsBe,GACtBD,IAAgB,YAAc,yBAC9BO,CACF,CACD,CAAA,CACsB,CAAA,CAE7B,EACA,EAAY,YAAc,UAmD1B,IAAaC,EAA0B,OAAO,OAAOrB,EAAa,CAChE,OAAQnB,EAAAA,cACR,aAAcC,EAAAA,oBACd,WAAYC,EAAAA,kBACZ,YAAaC,EAAAA,mBACb,MAAOC,EAAAA,aACP,QAASC,EAAAA,cACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"Toolbar.cjs","names":["useToolbarNavigation","useMergedRefs","useCheckedValues","useToolbarCheckableRegistry","React","ToolbarContext","composeEventHandlers","cn","toolbarClassNames","ToolbarButton","ToolbarToggleButton","ToolbarRadioGroup","ToolbarRadioButton","ToolbarGroup","ToolbarDivider","require_runtime","require_cn","require_composeEventHandlers","require_classNames","require_useMergedRefs","require_useCheckedValues","require_Toolbar_context","require_Toolbar_navigation","require_Toolbar_parts","react","react_jsx_runtime","toolbarPaddingClasses","ToolbarRoot","ariaOrientation","rest","props","mergedRef","containerProps","ref","checked","checkedValues","defaultCheckedValues","onCheckedValuesChange","registerCheckable","context","orientation","size","Component","as","role","onKeyDown","onFocus","className","Toolbar"],"sources":["../../../src/components/button/Toolbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { toolbarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport type { PolymorphicComponent, PolymorphicProps } from '../../lib/polymorphic';\nimport type { CheckedValues, CheckedValuesChangeHandler, Orientation, Size } from '../../lib/types';\nimport { useCheckedValues } from '../../hooks/useCheckedValues';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { ToolbarContext, useToolbarCheckableRegistry } from './Toolbar.context';\nimport type { ToolbarContextValue } from './Toolbar.context';\nimport { useToolbarNavigation } from './Toolbar.navigation';\nimport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n} from './Toolbar.parts';\n\nexport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n};\nexport type {\n ToolbarButtonOwnProps,\n ToolbarButtonProps,\n ToolbarDividerProps,\n ToolbarGroupProps,\n ToolbarRadioButtonProps,\n ToolbarRadioGroupProps,\n ToolbarToggleButtonProps,\n} from './Toolbar.parts';\n\n/**\n * The Toolbar's own props (the XOwnProps rule of `PolymorphicProps`: component-specific props\n * only). Every other prop comes from the rendered element (`as`, default `'div'`). Give the\n * toolbar an `aria-label` (or `aria-labelledby`) that describes its purpose, e.g. \"Formatting\".\n */\nexport interface ToolbarOwnProps {\n /**\n * Layout and arrow-key axis: Left/Right move between items when horizontal (mirrored in RTL),\n * Up/Down when vertical. Exposed as `aria-orientation` and `data-orientation`.\n * @default 'horizontal'\n */\n orientation?: Orientation;\n /**\n * Default size of `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` (their\n * own `size` wins), and the toolbar's padding. Plain Buttons inside keep their own default.\n * Exposed as `data-size`.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Pressed `Toolbar.ToggleButton`s and checked `Toolbar.RadioButton`s, per group `name`\n * (controlled): `{ format: ['bold'], align: ['center'] }`.\n */\n checkedValues?: CheckedValues;\n /** Initial checked values for uncontrolled usage. @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when a toggle or radio changes them (only on change): the new checked values first,\n * then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`; always passed, typed optional until 1.0).\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n}\n\n/**\n * Props of {@link Toolbar} rendered as `C` (default `'div'`). `ToolbarProps` without a type\n * argument is the 0.4 name: the props of a Toolbar rendered as a `<div>`, including `ref`.\n */\nexport type ToolbarProps<C extends React.ElementType = 'div'> = PolymorphicProps<\n C,\n ToolbarOwnProps\n>;\n\n/** The props the implementation reads, for any `as`. */\ntype ToolbarImplProps = ToolbarOwnProps &\n React.HTMLAttributes<HTMLElement> & {\n as?: React.ElementType;\n ref?: React.Ref<HTMLElement>;\n };\n\n/** The toolbar's padding per size. */\nconst toolbarPaddingClasses: Record<Size, string> = {\n 'extra-small': 'p-0.5',\n small: 'p-0.5',\n medium: 'p-1',\n large: 'p-1.5',\n 'extra-large': 'p-2',\n};\n\n// The root of the Toolbar compound; its component JSDoc is on the `Toolbar` export below (C-DOCS).\nconst ToolbarRoot: PolymorphicComponent<'div', ToolbarOwnProps> = (props) => {\n const {\n as,\n orientation = 'horizontal',\n size = 'medium',\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n className,\n ref,\n onKeyDown,\n onFocus,\n role,\n 'aria-orientation': ariaOrientation,\n ...rest\n } = props as ToolbarImplProps;\n\n const { containerProps } = useToolbarNavigation({ orientation });\n const mergedRef = useMergedRefs<HTMLElement>(containerProps.ref, ref);\n\n const checked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const registerCheckable = useToolbarCheckableRegistry();\n const context = React.useMemo<ToolbarContextValue>(\n () => ({ orientation, size, checked, registerCheckable }),\n [orientation, size, checked, registerCheckable],\n );\n\n const Component: React.ElementType = as ?? 'div';\n // The role and `aria-orientation` defaults apply wherever the consumer's value is `undefined` or\n // `null` (as in Button), so a wrapper forwarding its own unset props keeps them.\n return (\n <ToolbarContext.Provider value={context}>\n <Component\n data-size={size}\n data-orientation={orientation}\n {...rest}\n role={role ?? 'toolbar'}\n aria-orientation={ariaOrientation ?? orientation}\n ref={mergedRef}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, containerProps.onKeyDown)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n className={cn(\n toolbarClassNames.root,\n 'inline-flex items-center gap-1 rounded border border-border',\n toolbarPaddingClasses[size],\n orientation === 'vertical' && 'flex-col items-stretch',\n className,\n )}\n />\n </ToolbarContext.Provider>\n );\n};\nToolbarRoot.displayName = 'Toolbar';\n\n/**\n * A container for a set of controls (APG Toolbar pattern): `role=\"toolbar\"`, one Tab stop, and\n * arrow-key navigation between its controls.\n *\n * - Works with any children (Buttons, ToggleButtons, links, inputs, value controls such as\n * Checkbox or Dropdown): the focusable controls are found in the DOM, and the Toolbar sets their\n * `tabIndex` itself (one `0`, the rest `-1`). The `type=\"hidden\"` input that a named value\n * control renders never counts as a control, and controls that CSS hides are skipped.\n * - Parts: `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` take the toolbar's\n * `size` (default `'medium'`) and the `subtle` appearance by default; `Toolbar.RadioGroup`,\n * `Toolbar.Group` and `Toolbar.Divider` lay them out. Plain Buttons keep their own defaults.\n * - State: the pressed `Toolbar.ToggleButton`s and the checked `Toolbar.RadioButton` of each\n * group live in `checkedValues`/`defaultCheckedValues`, per group `name`, and every change calls\n * `onCheckedValuesChange(checkedValues, details)`. The state is in the server HTML.\n * - Left/Right (Up/Down when `orientation=\"vertical\"`) move focus and wrap; Home/End jump to the\n * first/last control; Left/Right are mirrored in RTL. Natively disabled controls are skipped,\n * also when a child disables them on its own; `disabledFocusable` ones stay in the arrow-key\n * order (APG), so a Tooltip can explain why they are unavailable. The arrows never press a\n * toggle or check a radio: Space, Enter or a click does.\n * - The radios of a `Toolbar.RadioGroup` are part of that arrow-key order, and Up/Down (Left/Right\n * in a vertical toolbar) also move among them, wrapping inside the group.\n * - Tab returns to the last focused control. Focusing a nested composite (radio group, tab list)\n * or a text field, select, slider or spin button keeps the Tab stop where it was.\n * - Text fields, selects, sliders, spin buttons and editable comboboxes keep their own arrow keys\n * (the caret moves). A Dropdown (select-only combobox) does not: Left/Right move past it. It\n * keeps Up/Down, Home and End for its list, so in a vertical toolbar the arrows cannot leave it.\n * - Elements with their own `tabIndex={-1}` are left alone, and a nested composite widget (a\n * RadioGroup, a tab list, …; not `Toolbar.RadioGroup`) counts as one control that keeps its own\n * Tab stop and arrow keys.\n * - A Menu or Popover opened from a control keeps its own keys: arrows, Home and End pressed in\n * the popup never move focus back to the toolbar's controls.\n * - A consumer `onKeyDown` runs first; `event.preventDefault()` in it cancels the navigation.\n * - Renders `data-size` and `data-orientation`.\n *\n * React Server Components cannot dot into a client module: import the flat names\n * `ToolbarButton`, `ToolbarToggleButton`, `ToolbarRadioGroup`, `ToolbarRadioButton`,\n * `ToolbarGroup` and `ToolbarDivider` there; `Toolbar.Button` etc. work in client files.\n *\n * @example\n * <Toolbar aria-label=\"Formatting\" defaultCheckedValues={{ format: ['bold'], align: ['left'] }}>\n * <Toolbar.ToggleButton name=\"format\" value=\"bold\" icon={<BoldIcon />} aria-label=\"Bold\" />\n * <Toolbar.ToggleButton name=\"format\" value=\"code\" icon={<CodeIcon />} aria-label=\"Code\" />\n * <Toolbar.Divider />\n * <Toolbar.RadioGroup aria-label=\"Text alignment\">\n * <Toolbar.RadioButton name=\"align\" value=\"left\" icon={<AlignLeftIcon />} aria-label=\"Left\" />\n * <Toolbar.RadioButton name=\"align\" value=\"center\" icon={<AlignCenterIcon />} aria-label=\"Center\" />\n * </Toolbar.RadioGroup>\n * </Toolbar>\n */\nexport const Toolbar = /* @__PURE__ */ Object.assign(ToolbarRoot, {\n Button: ToolbarButton,\n ToggleButton: ToolbarToggleButton,\n RadioGroup: ToolbarRadioGroup,\n RadioButton: ToolbarRadioButton,\n Group: ToolbarGroup,\n Divider: ToolbarDivider,\n});\n"],"mappings":"ucAyFA,IAAM0B,EAA8C,CAClD,cAAe,QACf,MAAO,QACP,OAAQ,MACR,MAAO,QACP,cAAe,KACjB,EAGMC,EAA6D,GAAU,CAC3E,GAAM,CACJ,KACA,cAAc,aACd,OAAO,SACP,gBACA,uBACA,wBACA,YACA,MACA,YACA,UACA,OACA,mBAAoBC,EACpB,GAAGC,GACDC,EAEE,CAAE,kBAAmB9B,EAAAA,qBAAqB,CAAE,aAAY,CAAC,EACzD+B,EAAY9B,EAAAA,cAA2B+B,EAAe,IAAKC,CAAG,EAE9DC,EAAUhC,EAAAA,iBAAiBiC,EAAeC,EAAsBC,CAAqB,EACrFC,EAAoBnC,EAAAA,4BAA4B,EAChDoC,EAAUnC,EAAM,aACb,CAAE,cAAa,OAAM,UAAS,mBAAkB,GACvD,CAACoC,EAAaC,EAAMP,EAASI,CAAiB,CAChD,EAEMI,EAA+BC,GAAM,MAG3C,OACE,EAAAlB,EAAA,IAAA,CAACpB,EAAAA,eAAe,SAAhB,CAAyB,MAAOkC,EAC9B,UAAA,EAAAd,EAAA,IAAA,CAACiB,EAAD,CACE,YAAWD,EACX,mBAAkBD,EAClB,GAAIX,EACJ,KAAMe,GAAQ,UACd,mBAAkBhB,GAAmBY,EACrC,IAAKT,EACL,wBAAsB,GACtB,UAAWzB,EAAAA,qBAAqBuC,EAAWb,EAAe,SAAS,EACnE,QAAS1B,EAAAA,qBAAqBwC,EAASd,EAAe,QAAS,CAC7D,sBAAuB,EACzB,CAAC,EACD,UAAWzB,EAAAA,GACTC,EAAAA,kBAAkB,KAClB,8DACAkB,EAAsBe,GACtBD,IAAgB,YAAc,yBAC9BO,CACF,CACD,CAAA,CACsB,CAAA,CAE7B,EACA,EAAY,YAAc,UAmD1B,IAAaC,EAA0B,OAAO,OAAOrB,EAAa,CAChE,OAAQlB,EAAAA,cACR,aAAcC,EAAAA,oBACd,WAAYC,EAAAA,kBACZ,YAAaC,EAAAA,mBACb,MAAOC,EAAAA,aACP,QAASC,EAAAA,cACX,CAAC"}
|
|
@@ -2,55 +2,50 @@
|
|
|
2
2
|
import { cn as e } from "../../lib/cn.mjs";
|
|
3
3
|
import { composeEventHandlers as t } from "../../lib/composeEventHandlers.mjs";
|
|
4
4
|
import { toolbarClassNames as n } from "../../lib/classNames.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { useMergedRefs as r } from "../../hooks/useMergedRefs.mjs";
|
|
6
|
+
import { useCheckedValues as i } from "../../hooks/useCheckedValues.mjs";
|
|
7
|
+
import { ToolbarContext as a, useToolbarCheckableRegistry as o } from "./Toolbar.context.mjs";
|
|
8
|
+
import { useToolbarNavigation as s } from "./Toolbar.navigation.mjs";
|
|
9
9
|
import { ToolbarButton as c, ToolbarDivider as l, ToolbarGroup as u, ToolbarRadioButton as d, ToolbarRadioGroup as f, ToolbarToggleButton as p } from "./Toolbar.parts.mjs";
|
|
10
10
|
import * as m from "react";
|
|
11
11
|
import { jsx as h } from "react/jsx-runtime";
|
|
12
12
|
//#region src/components/button/Toolbar.tsx
|
|
13
|
-
var g =
|
|
13
|
+
var g = {
|
|
14
14
|
"extra-small": "p-0.5",
|
|
15
15
|
small: "p-0.5",
|
|
16
16
|
medium: "p-1",
|
|
17
17
|
large: "p-1.5",
|
|
18
18
|
"extra-large": "p-2"
|
|
19
|
-
},
|
|
20
|
-
let { as: l, orientation: u = "horizontal", size: d = "medium", checkedValues: f, defaultCheckedValues: p, onCheckedValuesChange:
|
|
21
|
-
itemSelector: g,
|
|
22
|
-
manageTabIndex: !0,
|
|
23
|
-
tabStop: "last-focused",
|
|
24
|
-
orientation: u
|
|
25
|
-
}), D = i(E.ref, b), O = a(f, p, v), k = s(), A = m.useMemo(() => ({
|
|
19
|
+
}, _ = (c) => {
|
|
20
|
+
let { as: l, orientation: u = "horizontal", size: d = "medium", checkedValues: f, defaultCheckedValues: p, onCheckedValuesChange: _, className: v, ref: y, onKeyDown: b, onFocus: x, role: S, "aria-orientation": C, ...w } = c, { containerProps: T } = s({ orientation: u }), E = r(T.ref, y), D = i(f, p, _), O = o(), k = m.useMemo(() => ({
|
|
26
21
|
orientation: u,
|
|
27
22
|
size: d,
|
|
28
|
-
checked:
|
|
29
|
-
registerCheckable:
|
|
23
|
+
checked: D,
|
|
24
|
+
registerCheckable: O
|
|
30
25
|
}), [
|
|
31
26
|
u,
|
|
32
27
|
d,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
]),
|
|
36
|
-
return /* @__PURE__ */ h(
|
|
37
|
-
value:
|
|
38
|
-
children: /* @__PURE__ */ h(
|
|
28
|
+
D,
|
|
29
|
+
O
|
|
30
|
+
]), A = l ?? "div";
|
|
31
|
+
return /* @__PURE__ */ h(a.Provider, {
|
|
32
|
+
value: k,
|
|
33
|
+
children: /* @__PURE__ */ h(A, {
|
|
39
34
|
"data-size": d,
|
|
40
35
|
"data-orientation": u,
|
|
41
|
-
...
|
|
42
|
-
role:
|
|
43
|
-
"aria-orientation":
|
|
44
|
-
ref:
|
|
36
|
+
...w,
|
|
37
|
+
role: S ?? "toolbar",
|
|
38
|
+
"aria-orientation": C ?? u,
|
|
39
|
+
ref: E,
|
|
45
40
|
"data-roving-container": "",
|
|
46
|
-
onKeyDown: t(
|
|
47
|
-
onFocus: t(
|
|
48
|
-
className: e(n.root, "inline-flex items-center gap-1 rounded border border-border",
|
|
41
|
+
onKeyDown: t(b, T.onKeyDown),
|
|
42
|
+
onFocus: t(x, T.onFocus, { checkDefaultPrevented: !1 }),
|
|
43
|
+
className: e(n.root, "inline-flex items-center gap-1 rounded border border-border", g[d], u === "vertical" && "flex-col items-stretch", v)
|
|
49
44
|
})
|
|
50
45
|
});
|
|
51
46
|
};
|
|
52
|
-
|
|
53
|
-
var
|
|
47
|
+
_.displayName = "Toolbar";
|
|
48
|
+
var v = /* @__PURE__ */ Object.assign(_, {
|
|
54
49
|
Button: c,
|
|
55
50
|
ToggleButton: p,
|
|
56
51
|
RadioGroup: f,
|
|
@@ -59,6 +54,6 @@ var y = /* @__PURE__ */ Object.assign(v, {
|
|
|
59
54
|
Divider: l
|
|
60
55
|
});
|
|
61
56
|
//#endregion
|
|
62
|
-
export {
|
|
57
|
+
export { v as Toolbar, c as ToolbarButton, l as ToolbarDivider, u as ToolbarGroup, d as ToolbarRadioButton, f as ToolbarRadioGroup, p as ToolbarToggleButton };
|
|
63
58
|
|
|
64
59
|
//# sourceMappingURL=Toolbar.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.mjs","names":["React","TOOLBAR_ITEM_SELECTOR","toolbarPaddingClasses","ToolbarRoot","ariaOrientation","rest","props","useRovingTabIndex","mergedRef","useMergedRefs","containerProps","ref","checked","useCheckedValues","checkedValues","defaultCheckedValues","onCheckedValuesChange","registerCheckable","useToolbarCheckableRegistry","context","orientation","size","Component","as","ToolbarContext","role","composeEventHandlers","onKeyDown","onFocus","cn","toolbarClassNames","className","Toolbar","ToolbarButton","ToolbarToggleButton","ToolbarRadioGroup","ToolbarRadioButton","ToolbarGroup","ToolbarDivider"],"sources":["../../../src/components/button/Toolbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { toolbarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport type { PolymorphicComponent, PolymorphicProps } from '../../lib/polymorphic';\nimport type { CheckedValues, CheckedValuesChangeHandler, Orientation, Size } from '../../lib/types';\nimport { useCheckedValues } from '../../hooks/useCheckedValues';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { useRovingTabIndex } from '../../hooks/useRovingTabIndex';\nimport { ToolbarContext, useToolbarCheckableRegistry } from './Toolbar.context';\nimport type { ToolbarContextValue } from './Toolbar.context';\nimport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n} from './Toolbar.parts';\n\nexport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n};\nexport type {\n ToolbarButtonOwnProps,\n ToolbarButtonProps,\n ToolbarDividerProps,\n ToolbarGroupProps,\n ToolbarRadioButtonProps,\n ToolbarRadioGroupProps,\n ToolbarToggleButtonProps,\n} from './Toolbar.parts';\n\n/**\n * The Toolbar's own props (the XOwnProps rule of `PolymorphicProps`: component-specific props\n * only). Every other prop comes from the rendered element (`as`, default `'div'`). Give the\n * toolbar an `aria-label` (or `aria-labelledby`) that describes its purpose, e.g. \"Formatting\".\n */\nexport interface ToolbarOwnProps {\n /**\n * Layout and arrow-key axis: Left/Right move between items when horizontal (mirrored in RTL),\n * Up/Down when vertical. Exposed as `aria-orientation` and `data-orientation`.\n * @default 'horizontal'\n */\n orientation?: Orientation;\n /**\n * Default size of `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` (their\n * own `size` wins), and the toolbar's padding. Plain Buttons inside keep their own default.\n * Exposed as `data-size`.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Pressed `Toolbar.ToggleButton`s and checked `Toolbar.RadioButton`s, per group `name`\n * (controlled): `{ format: ['bold'], align: ['center'] }`.\n */\n checkedValues?: CheckedValues;\n /** Initial checked values for uncontrolled usage. @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when a toggle or radio changes them (only on change): the new checked values first,\n * then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`; always passed, typed optional until 1.0).\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n}\n\n/**\n * Props of {@link Toolbar} rendered as `C` (default `'div'`). `ToolbarProps` without a type\n * argument is the 0.4 name: the props of a Toolbar rendered as a `<div>`, including `ref`.\n */\nexport type ToolbarProps<C extends React.ElementType = 'div'> = PolymorphicProps<\n C,\n ToolbarOwnProps\n>;\n\n/** The props the implementation reads, for any `as`. */\ntype ToolbarImplProps = ToolbarOwnProps &\n React.HTMLAttributes<HTMLElement> & {\n as?: React.ElementType;\n ref?: React.Ref<HTMLElement>;\n };\n\n/**\n * Every focusable control a toolbar can contain, whatever component renders it. Matches that\n * cannot take focus (a `type=\"hidden\"` input, a control CSS hides) are dropped by the roving hook.\n */\nconst TOOLBAR_ITEM_SELECTOR =\n 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/** The toolbar's padding per size. */\nconst toolbarPaddingClasses: Record<Size, string> = {\n 'extra-small': 'p-0.5',\n small: 'p-0.5',\n medium: 'p-1',\n large: 'p-1.5',\n 'extra-large': 'p-2',\n};\n\n// The root of the Toolbar compound; its component JSDoc is on the `Toolbar` export below (C-DOCS).\nconst ToolbarRoot: PolymorphicComponent<'div', ToolbarOwnProps> = (props) => {\n const {\n as,\n orientation = 'horizontal',\n size = 'medium',\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n className,\n ref,\n onKeyDown,\n onFocus,\n role,\n 'aria-orientation': ariaOrientation,\n ...rest\n } = props as ToolbarImplProps;\n\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation,\n });\n const mergedRef = useMergedRefs<HTMLElement>(containerProps.ref, ref);\n\n const checked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const registerCheckable = useToolbarCheckableRegistry();\n const context = React.useMemo<ToolbarContextValue>(\n () => ({ orientation, size, checked, registerCheckable }),\n [orientation, size, checked, registerCheckable],\n );\n\n const Component: React.ElementType = as ?? 'div';\n // The role and `aria-orientation` defaults apply wherever the consumer's value is `undefined` or\n // `null` (as in Button), so a wrapper forwarding its own unset props keeps them.\n return (\n <ToolbarContext.Provider value={context}>\n <Component\n data-size={size}\n data-orientation={orientation}\n {...rest}\n role={role ?? 'toolbar'}\n aria-orientation={ariaOrientation ?? orientation}\n ref={mergedRef}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, containerProps.onKeyDown)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n className={cn(\n toolbarClassNames.root,\n 'inline-flex items-center gap-1 rounded border border-border',\n toolbarPaddingClasses[size],\n orientation === 'vertical' && 'flex-col items-stretch',\n className,\n )}\n />\n </ToolbarContext.Provider>\n );\n};\nToolbarRoot.displayName = 'Toolbar';\n\n/**\n * A container for a set of controls (APG Toolbar pattern): `role=\"toolbar\"`, one Tab stop, and\n * arrow-key navigation between its controls.\n *\n * - Works with any children (Buttons, ToggleButtons, links, inputs, value controls such as\n * Checkbox or Dropdown): the focusable controls are found in the DOM, and the Toolbar sets their\n * `tabIndex` itself (one `0`, the rest `-1`). The `type=\"hidden\"` input that a named value\n * control renders never counts as a control, and controls that CSS hides are skipped.\n * - Parts: `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` take the toolbar's\n * `size` (default `'medium'`) and the `subtle` appearance by default; `Toolbar.RadioGroup`,\n * `Toolbar.Group` and `Toolbar.Divider` lay them out. Plain Buttons keep their own defaults.\n * - State: the pressed `Toolbar.ToggleButton`s and the checked `Toolbar.RadioButton` of each\n * group live in `checkedValues`/`defaultCheckedValues`, per group `name`, and every change calls\n * `onCheckedValuesChange(checkedValues, details)`. The state is in the server HTML.\n * - Left/Right (Up/Down when `orientation=\"vertical\"`) move focus and wrap; Home/End jump to the\n * first/last control; Left/Right are mirrored in RTL. Natively disabled controls are skipped,\n * also when a child disables them on its own; `disabledFocusable` ones stay in the arrow-key\n * order (APG), so a Tooltip can explain why they are unavailable. The arrows never press a\n * toggle or check a radio: Space, Enter or a click does.\n * - The radios of a `Toolbar.RadioGroup` are part of that arrow-key order, and Up/Down (Left/Right\n * in a vertical toolbar) also move among them, wrapping inside the group.\n * - Tab returns to the last focused control. Focusing a nested composite (radio group, tab list)\n * or a text field, select, slider or spin button keeps the Tab stop where it was.\n * - Text fields, selects, sliders, spin buttons and editable comboboxes keep their own arrow keys\n * (the caret moves). A Dropdown (select-only combobox) does not: Left/Right move past it. It\n * keeps Up/Down, Home and End for its list, so in a vertical toolbar the arrows cannot leave it.\n * - Elements with their own `tabIndex={-1}` are left alone, and a nested composite widget (a\n * RadioGroup, a tab list, …; not `Toolbar.RadioGroup`) counts as one control that keeps its own\n * Tab stop and arrow keys.\n * - A Menu or Popover opened from a control keeps its own keys: arrows, Home and End pressed in\n * the popup never move focus back to the toolbar's controls.\n * - A consumer `onKeyDown` runs first; `event.preventDefault()` in it cancels the navigation.\n * - Renders `data-size` and `data-orientation`.\n *\n * React Server Components cannot dot into a client module: import the flat names\n * `ToolbarButton`, `ToolbarToggleButton`, `ToolbarRadioGroup`, `ToolbarRadioButton`,\n * `ToolbarGroup` and `ToolbarDivider` there; `Toolbar.Button` etc. work in client files.\n *\n * @example\n * <Toolbar aria-label=\"Formatting\" defaultCheckedValues={{ format: ['bold'], align: ['left'] }}>\n * <Toolbar.ToggleButton name=\"format\" value=\"bold\" icon={<BoldIcon />} aria-label=\"Bold\" />\n * <Toolbar.ToggleButton name=\"format\" value=\"code\" icon={<CodeIcon />} aria-label=\"Code\" />\n * <Toolbar.Divider />\n * <Toolbar.RadioGroup aria-label=\"Text alignment\">\n * <Toolbar.RadioButton name=\"align\" value=\"left\" icon={<AlignLeftIcon />} aria-label=\"Left\" />\n * <Toolbar.RadioButton name=\"align\" value=\"center\" icon={<AlignCenterIcon />} aria-label=\"Center\" />\n * </Toolbar.RadioGroup>\n * </Toolbar>\n */\nexport const Toolbar = /* @__PURE__ */ Object.assign(ToolbarRoot, {\n Button: ToolbarButton,\n ToggleButton: ToolbarToggleButton,\n RadioGroup: ToolbarRadioGroup,\n RadioButton: ToolbarRadioButton,\n Group: ToolbarGroup,\n Divider: ToolbarDivider,\n});\n"],"mappings":";;;;;;;;;;;;AA4FA,IAAMC,IACJ,0EAGIC,IAA8C;CAClD,eAAe;CACf,OAAO;CACP,QAAQ;CACR,OAAO;CACP,eAAe;AACjB,GAGMC,KAA6D,MAAU;CAC3E,IAAM,EACJ,OACA,iBAAc,cACd,UAAO,UACP,kBACA,yBACA,0BACA,cACA,QACA,cACA,YACA,SACA,oBAAoBC,GACpB,GAAGC,MACDC,GAEE,EAAE,sBAAmBC,EAAkB;EAC3C,cAAcN;EACd,gBAAgB;EAChB,SAAS;EACT;CACF,CAAC,GACKO,IAAYC,EAA2BC,EAAe,KAAKC,CAAG,GAE9DC,IAAUC,EAAiBC,GAAeC,GAAsBC,CAAqB,GACrFC,IAAoBC,EAA4B,GAChDC,IAAUnB,EAAM,eACb;EAAE;EAAa;EAAM;EAAS;CAAkB,IACvD;EAACoB;EAAaC;EAAMT;EAASK;CAAiB,CAChD,GAEMK,IAA+BC,KAAM;CAG3C,OACE,kBAACC,EAAe,UAAhB;EAAyB,OAAOL;EAC9B,UAAA,kBAACG,GAAD;GACE,aAAWD;GACX,oBAAkBD;GAClB,GAAIf;GACJ,MAAMoB,KAAQ;GACd,oBAAkBrB,KAAmBgB;GACrC,KAAKZ;GACL,yBAAsB;GACtB,WAAWkB,EAAqBC,GAAWjB,EAAe,SAAS;GACnE,SAASgB,EAAqBE,GAASlB,EAAe,SAAS,EAC7D,uBAAuB,GACzB,CAAC;GACD,WAAWmB,EACTC,EAAkB,MAClB,+DACA5B,EAAsBmB,IACtBD,MAAgB,cAAc,0BAC9BW,CACF;EACD,CAAA;CACsB,CAAA;AAE7B;AACA,EAAY,cAAc;AAmD1B,IAAaC,IAA0B,uBAAO,OAAO7B,GAAa;CAChE,QAAQ8B;CACR,cAAcC;CACd,YAAYC;CACZ,aAAaC;CACb,OAAOC;CACP,SAASC;AACX,CAAC"}
|
|
1
|
+
{"version":3,"file":"Toolbar.mjs","names":["React","toolbarPaddingClasses","ToolbarRoot","ariaOrientation","rest","props","useToolbarNavigation","mergedRef","useMergedRefs","containerProps","ref","checked","useCheckedValues","checkedValues","defaultCheckedValues","onCheckedValuesChange","registerCheckable","useToolbarCheckableRegistry","context","orientation","size","Component","as","ToolbarContext","role","composeEventHandlers","onKeyDown","onFocus","cn","toolbarClassNames","className","Toolbar","ToolbarButton","ToolbarToggleButton","ToolbarRadioGroup","ToolbarRadioButton","ToolbarGroup","ToolbarDivider"],"sources":["../../../src/components/button/Toolbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { cn } from '../../lib/cn';\nimport { toolbarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport type { PolymorphicComponent, PolymorphicProps } from '../../lib/polymorphic';\nimport type { CheckedValues, CheckedValuesChangeHandler, Orientation, Size } from '../../lib/types';\nimport { useCheckedValues } from '../../hooks/useCheckedValues';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { ToolbarContext, useToolbarCheckableRegistry } from './Toolbar.context';\nimport type { ToolbarContextValue } from './Toolbar.context';\nimport { useToolbarNavigation } from './Toolbar.navigation';\nimport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n} from './Toolbar.parts';\n\nexport {\n ToolbarButton,\n ToolbarDivider,\n ToolbarGroup,\n ToolbarRadioButton,\n ToolbarRadioGroup,\n ToolbarToggleButton,\n};\nexport type {\n ToolbarButtonOwnProps,\n ToolbarButtonProps,\n ToolbarDividerProps,\n ToolbarGroupProps,\n ToolbarRadioButtonProps,\n ToolbarRadioGroupProps,\n ToolbarToggleButtonProps,\n} from './Toolbar.parts';\n\n/**\n * The Toolbar's own props (the XOwnProps rule of `PolymorphicProps`: component-specific props\n * only). Every other prop comes from the rendered element (`as`, default `'div'`). Give the\n * toolbar an `aria-label` (or `aria-labelledby`) that describes its purpose, e.g. \"Formatting\".\n */\nexport interface ToolbarOwnProps {\n /**\n * Layout and arrow-key axis: Left/Right move between items when horizontal (mirrored in RTL),\n * Up/Down when vertical. Exposed as `aria-orientation` and `data-orientation`.\n * @default 'horizontal'\n */\n orientation?: Orientation;\n /**\n * Default size of `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` (their\n * own `size` wins), and the toolbar's padding. Plain Buttons inside keep their own default.\n * Exposed as `data-size`.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Pressed `Toolbar.ToggleButton`s and checked `Toolbar.RadioButton`s, per group `name`\n * (controlled): `{ format: ['bold'], align: ['center'] }`.\n */\n checkedValues?: CheckedValues;\n /** Initial checked values for uncontrolled usage. @default {} */\n defaultCheckedValues?: CheckedValues;\n /**\n * Called when a toggle or radio changes them (only on change): the new checked values first,\n * then `details` with the group's `name`, its `checkedItems` and the `event` (Fluent's\n * `onCheckedValueChange(event, { name, checkedItems })`; always passed, typed optional until 1.0).\n */\n onCheckedValuesChange?: CheckedValuesChangeHandler;\n}\n\n/**\n * Props of {@link Toolbar} rendered as `C` (default `'div'`). `ToolbarProps` without a type\n * argument is the 0.4 name: the props of a Toolbar rendered as a `<div>`, including `ref`.\n */\nexport type ToolbarProps<C extends React.ElementType = 'div'> = PolymorphicProps<\n C,\n ToolbarOwnProps\n>;\n\n/** The props the implementation reads, for any `as`. */\ntype ToolbarImplProps = ToolbarOwnProps &\n React.HTMLAttributes<HTMLElement> & {\n as?: React.ElementType;\n ref?: React.Ref<HTMLElement>;\n };\n\n/** The toolbar's padding per size. */\nconst toolbarPaddingClasses: Record<Size, string> = {\n 'extra-small': 'p-0.5',\n small: 'p-0.5',\n medium: 'p-1',\n large: 'p-1.5',\n 'extra-large': 'p-2',\n};\n\n// The root of the Toolbar compound; its component JSDoc is on the `Toolbar` export below (C-DOCS).\nconst ToolbarRoot: PolymorphicComponent<'div', ToolbarOwnProps> = (props) => {\n const {\n as,\n orientation = 'horizontal',\n size = 'medium',\n checkedValues,\n defaultCheckedValues,\n onCheckedValuesChange,\n className,\n ref,\n onKeyDown,\n onFocus,\n role,\n 'aria-orientation': ariaOrientation,\n ...rest\n } = props as ToolbarImplProps;\n\n const { containerProps } = useToolbarNavigation({ orientation });\n const mergedRef = useMergedRefs<HTMLElement>(containerProps.ref, ref);\n\n const checked = useCheckedValues(checkedValues, defaultCheckedValues, onCheckedValuesChange);\n const registerCheckable = useToolbarCheckableRegistry();\n const context = React.useMemo<ToolbarContextValue>(\n () => ({ orientation, size, checked, registerCheckable }),\n [orientation, size, checked, registerCheckable],\n );\n\n const Component: React.ElementType = as ?? 'div';\n // The role and `aria-orientation` defaults apply wherever the consumer's value is `undefined` or\n // `null` (as in Button), so a wrapper forwarding its own unset props keeps them.\n return (\n <ToolbarContext.Provider value={context}>\n <Component\n data-size={size}\n data-orientation={orientation}\n {...rest}\n role={role ?? 'toolbar'}\n aria-orientation={ariaOrientation ?? orientation}\n ref={mergedRef}\n data-roving-container=\"\"\n onKeyDown={composeEventHandlers(onKeyDown, containerProps.onKeyDown)}\n onFocus={composeEventHandlers(onFocus, containerProps.onFocus, {\n checkDefaultPrevented: false,\n })}\n className={cn(\n toolbarClassNames.root,\n 'inline-flex items-center gap-1 rounded border border-border',\n toolbarPaddingClasses[size],\n orientation === 'vertical' && 'flex-col items-stretch',\n className,\n )}\n />\n </ToolbarContext.Provider>\n );\n};\nToolbarRoot.displayName = 'Toolbar';\n\n/**\n * A container for a set of controls (APG Toolbar pattern): `role=\"toolbar\"`, one Tab stop, and\n * arrow-key navigation between its controls.\n *\n * - Works with any children (Buttons, ToggleButtons, links, inputs, value controls such as\n * Checkbox or Dropdown): the focusable controls are found in the DOM, and the Toolbar sets their\n * `tabIndex` itself (one `0`, the rest `-1`). The `type=\"hidden\"` input that a named value\n * control renders never counts as a control, and controls that CSS hides are skipped.\n * - Parts: `Toolbar.Button`, `Toolbar.ToggleButton` and `Toolbar.RadioButton` take the toolbar's\n * `size` (default `'medium'`) and the `subtle` appearance by default; `Toolbar.RadioGroup`,\n * `Toolbar.Group` and `Toolbar.Divider` lay them out. Plain Buttons keep their own defaults.\n * - State: the pressed `Toolbar.ToggleButton`s and the checked `Toolbar.RadioButton` of each\n * group live in `checkedValues`/`defaultCheckedValues`, per group `name`, and every change calls\n * `onCheckedValuesChange(checkedValues, details)`. The state is in the server HTML.\n * - Left/Right (Up/Down when `orientation=\"vertical\"`) move focus and wrap; Home/End jump to the\n * first/last control; Left/Right are mirrored in RTL. Natively disabled controls are skipped,\n * also when a child disables them on its own; `disabledFocusable` ones stay in the arrow-key\n * order (APG), so a Tooltip can explain why they are unavailable. The arrows never press a\n * toggle or check a radio: Space, Enter or a click does.\n * - The radios of a `Toolbar.RadioGroup` are part of that arrow-key order, and Up/Down (Left/Right\n * in a vertical toolbar) also move among them, wrapping inside the group.\n * - Tab returns to the last focused control. Focusing a nested composite (radio group, tab list)\n * or a text field, select, slider or spin button keeps the Tab stop where it was.\n * - Text fields, selects, sliders, spin buttons and editable comboboxes keep their own arrow keys\n * (the caret moves). A Dropdown (select-only combobox) does not: Left/Right move past it. It\n * keeps Up/Down, Home and End for its list, so in a vertical toolbar the arrows cannot leave it.\n * - Elements with their own `tabIndex={-1}` are left alone, and a nested composite widget (a\n * RadioGroup, a tab list, …; not `Toolbar.RadioGroup`) counts as one control that keeps its own\n * Tab stop and arrow keys.\n * - A Menu or Popover opened from a control keeps its own keys: arrows, Home and End pressed in\n * the popup never move focus back to the toolbar's controls.\n * - A consumer `onKeyDown` runs first; `event.preventDefault()` in it cancels the navigation.\n * - Renders `data-size` and `data-orientation`.\n *\n * React Server Components cannot dot into a client module: import the flat names\n * `ToolbarButton`, `ToolbarToggleButton`, `ToolbarRadioGroup`, `ToolbarRadioButton`,\n * `ToolbarGroup` and `ToolbarDivider` there; `Toolbar.Button` etc. work in client files.\n *\n * @example\n * <Toolbar aria-label=\"Formatting\" defaultCheckedValues={{ format: ['bold'], align: ['left'] }}>\n * <Toolbar.ToggleButton name=\"format\" value=\"bold\" icon={<BoldIcon />} aria-label=\"Bold\" />\n * <Toolbar.ToggleButton name=\"format\" value=\"code\" icon={<CodeIcon />} aria-label=\"Code\" />\n * <Toolbar.Divider />\n * <Toolbar.RadioGroup aria-label=\"Text alignment\">\n * <Toolbar.RadioButton name=\"align\" value=\"left\" icon={<AlignLeftIcon />} aria-label=\"Left\" />\n * <Toolbar.RadioButton name=\"align\" value=\"center\" icon={<AlignCenterIcon />} aria-label=\"Center\" />\n * </Toolbar.RadioGroup>\n * </Toolbar>\n */\nexport const Toolbar = /* @__PURE__ */ Object.assign(ToolbarRoot, {\n Button: ToolbarButton,\n ToggleButton: ToolbarToggleButton,\n RadioGroup: ToolbarRadioGroup,\n RadioButton: ToolbarRadioButton,\n Group: ToolbarGroup,\n Divider: ToolbarDivider,\n});\n"],"mappings":";;;;;;;;;;;;AAyFA,IAAMC,IAA8C;CAClD,eAAe;CACf,OAAO;CACP,QAAQ;CACR,OAAO;CACP,eAAe;AACjB,GAGMC,KAA6D,MAAU;CAC3E,IAAM,EACJ,OACA,iBAAc,cACd,UAAO,UACP,kBACA,yBACA,0BACA,cACA,QACA,cACA,YACA,SACA,oBAAoBC,GACpB,GAAGC,MACDC,GAEE,EAAE,sBAAmBC,EAAqB,EAAE,eAAY,CAAC,GACzDC,IAAYC,EAA2BC,EAAe,KAAKC,CAAG,GAE9DC,IAAUC,EAAiBC,GAAeC,GAAsBC,CAAqB,GACrFC,IAAoBC,EAA4B,GAChDC,IAAUlB,EAAM,eACb;EAAE;EAAa;EAAM;EAAS;CAAkB,IACvD;EAACmB;EAAaC;EAAMT;EAASK;CAAiB,CAChD,GAEMK,IAA+BC,KAAM;CAG3C,OACE,kBAACC,EAAe,UAAhB;EAAyB,OAAOL;EAC9B,UAAA,kBAACG,GAAD;GACE,aAAWD;GACX,oBAAkBD;GAClB,GAAIf;GACJ,MAAMoB,KAAQ;GACd,oBAAkBrB,KAAmBgB;GACrC,KAAKZ;GACL,yBAAsB;GACtB,WAAWkB,EAAqBC,GAAWjB,EAAe,SAAS;GACnE,SAASgB,EAAqBE,GAASlB,EAAe,SAAS,EAC7D,uBAAuB,GACzB,CAAC;GACD,WAAWmB,EACTC,EAAkB,MAClB,+DACA5B,EAAsBmB,IACtBD,MAAgB,cAAc,0BAC9BW,CACF;EACD,CAAA;CACsB,CAAA;AAE7B;AACA,EAAY,cAAc;AAmD1B,IAAaC,IAA0B,uBAAO,OAAO7B,GAAa;CAChE,QAAQ8B;CACR,cAAcC;CACd,YAAYC;CACZ,aAAaC;CACb,OAAOC;CACP,SAASC;AACX,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../../hooks/useRovingTabIndex.cjs");var t=`button, [href], input, select, textarea, [role="button"], [tabindex]`;function n({orientation:n}){let{containerProps:r}=e.useRovingTabIndex({itemSelector:t,manageTabIndex:!0,tabStop:`last-focused`,orientation:n});return{containerProps:r}}exports.TOOLBAR_ITEM_SELECTOR=t,exports.useToolbarNavigation=n;
|
|
2
|
+
//# sourceMappingURL=Toolbar.navigation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.navigation.cjs","names":["useRovingTabIndex","require_useRovingTabIndex","TOOLBAR_ITEM_SELECTOR","useToolbarNavigation"],"sources":["../../../src/components/button/Toolbar.navigation.ts"],"sourcesContent":["import type { Orientation } from '../../lib/types';\nimport { useRovingTabIndex, type RovingContainerProps } from '../../hooks/useRovingTabIndex';\n\n/*\n * The roving configuration of a toolbar, shared by every component that renders one. Internal: it\n * imports nothing but the roving hook and a type, so a component that reads it pulls in no Toolbar\n * code.\n */\n\n/**\n * Every focusable control a toolbar can contain, whatever component renders it (Toolbar,\n * TagGroup, and NavDrawer.Body's arrow mode). Matches that cannot take focus (a `type=\"hidden\"`\n * input, a control CSS hides) are dropped by the roving hook.\n */\nexport const TOOLBAR_ITEM_SELECTOR =\n 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/** Options of {@link useToolbarNavigation}. */\nexport interface UseToolbarNavigationOptions {\n /** The arrow-key axis: Left/Right (mirrored in RTL) when horizontal, Up/Down when vertical. */\n orientation: Orientation;\n}\n\n/**\n * The one roving configuration of an APG toolbar (`buttons-22`), shared by Toolbar and TagGroup:\n * one Tab stop (the last focused control, at first the first enabled one), the arrow keys along\n * `orientation` only, Home and End, wrapping. The caller merges `containerProps.ref` with its own,\n * renders `data-roving-container`, composes its consumer's `onKeyDown` first and `onFocus` with\n * `checkDefaultPrevented: false`. Not spreading `containerProps` detaches the container, and the\n * hook then hands every control its own `tabIndex` back.\n */\nexport function useToolbarNavigation({ orientation }: UseToolbarNavigationOptions): {\n containerProps: RovingContainerProps;\n} {\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation,\n });\n return { containerProps };\n}\n"],"mappings":"kEAcA,IAAaE,EACX,uEAgBF,SAAgBC,EAAqB,CAAE,eAErC,CACA,GAAM,CAAE,kBAAmBH,EAAAA,kBAAkB,CAC3C,aAAcE,EACd,eAAgB,GAChB,QAAS,eACT,aACF,CAAC,EACD,MAAO,CAAE,gBAAe,CAC1B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRovingTabIndex as e } from "../../hooks/useRovingTabIndex.mjs";
|
|
3
|
+
//#region src/components/button/Toolbar.navigation.ts
|
|
4
|
+
var t = "button, [href], input, select, textarea, [role=\"button\"], [tabindex]";
|
|
5
|
+
function n({ orientation: n }) {
|
|
6
|
+
let { containerProps: r } = e({
|
|
7
|
+
itemSelector: t,
|
|
8
|
+
manageTabIndex: !0,
|
|
9
|
+
tabStop: "last-focused",
|
|
10
|
+
orientation: n
|
|
11
|
+
});
|
|
12
|
+
return { containerProps: r };
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { t as TOOLBAR_ITEM_SELECTOR, n as useToolbarNavigation };
|
|
16
|
+
|
|
17
|
+
//# sourceMappingURL=Toolbar.navigation.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toolbar.navigation.mjs","names":["TOOLBAR_ITEM_SELECTOR","useToolbarNavigation","useRovingTabIndex"],"sources":["../../../src/components/button/Toolbar.navigation.ts"],"sourcesContent":["import type { Orientation } from '../../lib/types';\nimport { useRovingTabIndex, type RovingContainerProps } from '../../hooks/useRovingTabIndex';\n\n/*\n * The roving configuration of a toolbar, shared by every component that renders one. Internal: it\n * imports nothing but the roving hook and a type, so a component that reads it pulls in no Toolbar\n * code.\n */\n\n/**\n * Every focusable control a toolbar can contain, whatever component renders it (Toolbar,\n * TagGroup, and NavDrawer.Body's arrow mode). Matches that cannot take focus (a `type=\"hidden\"`\n * input, a control CSS hides) are dropped by the roving hook.\n */\nexport const TOOLBAR_ITEM_SELECTOR =\n 'button, [href], input, select, textarea, [role=\"button\"], [tabindex]';\n\n/** Options of {@link useToolbarNavigation}. */\nexport interface UseToolbarNavigationOptions {\n /** The arrow-key axis: Left/Right (mirrored in RTL) when horizontal, Up/Down when vertical. */\n orientation: Orientation;\n}\n\n/**\n * The one roving configuration of an APG toolbar (`buttons-22`), shared by Toolbar and TagGroup:\n * one Tab stop (the last focused control, at first the first enabled one), the arrow keys along\n * `orientation` only, Home and End, wrapping. The caller merges `containerProps.ref` with its own,\n * renders `data-roving-container`, composes its consumer's `onKeyDown` first and `onFocus` with\n * `checkDefaultPrevented: false`. Not spreading `containerProps` detaches the container, and the\n * hook then hands every control its own `tabIndex` back.\n */\nexport function useToolbarNavigation({ orientation }: UseToolbarNavigationOptions): {\n containerProps: RovingContainerProps;\n} {\n const { containerProps } = useRovingTabIndex({\n itemSelector: TOOLBAR_ITEM_SELECTOR,\n manageTabIndex: true,\n tabStop: 'last-focused',\n orientation,\n });\n return { containerProps };\n}\n"],"mappings":";;;AAcA,IAAaA,IACX;AAgBF,SAAgBC,EAAqB,EAAE,kBAErC;CACA,IAAM,EAAE,sBAAmBC,EAAkB;EAC3C,cAAcF;EACd,gBAAgB;EAChB,SAAS;EACT;CACF,CAAC;CACD,OAAO,EAAE,kBAAe;AAC1B"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/slot.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useMergedRefs.cjs"),
|
|
1
|
+
"use client";const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../lib/cn.cjs"),n=require("../../lib/slot.cjs"),r=require("../../lib/composeEventHandlers.cjs"),i=require("../../lib/classNames.cjs"),a=require("../../hooks/useMergedRefs.cjs"),o=require("../../lib/aria.cjs"),ee=require("../../lib/icons.cjs"),te=require("./Avatar.context.cjs");let s=require("react");s=e.__toESM(s,1);let c=require("react/jsx-runtime");var l={"extra-small":`w-6 h-6 text-[10px]`,small:`w-8 h-8 text-xs`,medium:`w-10 h-10 text-sm`,large:`w-12 h-12 text-base`,"extra-large":`w-14 h-14 text-lg`},ne={24:l[`extra-small`],20:`w-5 h-5 text-[10px]`,16:`w-4 h-4 text-[10px]`},u=`w-full h-full object-cover`;function re(e){let t=e.trim().split(/\s+/).filter(Boolean);return t.length===0?``:((Array.from(t[0])[0]??``)+(t.length>1?Array.from(t[t.length-1])[0]??``:``)).toUpperCase()}function d(e){return e?.trim().replace(/\s+/g,` `)||void 0}function ie(e){if(s.isValidElement(e))return e.props;if(typeof e==`object`&&e&&!(Symbol.iterator in e))return e}function ae(e,t,n){if(e===void 0)return[void 0,void 0,n||void 0,void 0];if(typeof e==`string`)return[void 0,void 0,e,void 0];let r=s.isValidElement(e)?e:void 0;return[r?.type,r?.key,t?.src,t?.srcSet]}function f(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function p(e,t){if(Object.is(e,t))return!0;if(!f(e)||!f(t))return!1;let n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>Object.prototype.hasOwnProperty.call(t,n)&&Object.is(e[n],t[n]))}function oe(e,t){return e.every((e,n)=>p(e,t[n]))}var m=({src:e,name:f,size:p,icon:m,image:h,badge:g,decorative:_=!1,className:v,ref:y,role:b,"aria-label":x,"aria-labelledby":S,"aria-describedby":C,"aria-description":se,"aria-details":ce,...w})=>{let T=s.useContext(te.AvatarSizeContext),E=h==null||typeof h==`boolean`||h===``?void 0:h,D=ie(E),O=ae(E,D,e),[le,k]=s.useState(!1),[ue,A]=s.useState(O);oe(ue,O)||(A(O),k(!1));let j=s.useRef(null);s.useLayoutEffect(()=>{let e=j.current?.querySelector(`img`);if(!e||!e.complete||e.naturalWidth!==0)return;let t=!0,n=e.getAttribute(`src`),r=e.getAttribute(`srcset`),i=()=>{t&&e.isConnected&&e.getAttribute(`src`)===n&&e.getAttribute(`srcset`)===r&&k(!0)};return typeof e.decode==`function`?e.decode().then(void 0,i):queueMicrotask(i),()=>{t=!1}},[]);let M=a.useMergedRefs(y,j),N=x!==void 0||S!==void 0,P=b!==void 0&&b!==`presentation`&&b!==`none`,F=d(f),I=_||N||P?``:F??``,L=()=>k(!0),R=D?.alt,z=R!=null,B=z?R:I,V={"aria-describedby":C,"aria-description":se,"aria-details":ce},H=!_&&!N&&!P&&typeof B==`string`&&B.trim()!==``,U=H?V:{},W=null;if(!le){if(typeof E==`string`)W=(0,c.jsx)(`img`,{src:E,alt:I,...U,className:t.cn(i.avatarClassNames.image,u),onError:L});else if(E!==void 0){let e={onError:r.composeEventHandlers(D?.onError,L)};if(z||(e.alt=I),H){let t=D?.[`aria-describedby`];e[`aria-describedby`]=o.joinIds(C,typeof t==`string`?t:void 0)}let a=s.isValidElement(E)?s.cloneElement(E,e):D?{...E,...e}:E;W=n.renderSlot(a,`img`,t.cn(i.avatarClassNames.image,u),{alt:I,...U})}else e&&(W=(0,c.jsx)(`img`,{src:e,alt:I,...U,className:t.cn(i.avatarClassNames.image,u),onError:L}))}let G=W!==null&&H?{}:V,K=W===null&&m&&n.slotRendersContent(m)?n.renderSlot(m,`span`,t.cn(i.avatarClassNames.icon,`inline-flex`),{"aria-hidden":!0}):null,q=W===null&&K===null&&f?re(f):``,J,Y;W===null?K===null?q?(J=(0,c.jsx)(`span`,{"aria-hidden":`true`,className:i.avatarClassNames.initials,children:q}),Y=`bg-primary text-primary-foreground`):(J=(0,c.jsx)(ee.PersonIcon,{size:`60%`,className:i.avatarClassNames.icon}),Y=`bg-muted text-muted-foreground`):(J=K,Y=`bg-muted text-muted-foreground`):J=W;let de=W!==null&&P&&typeof B==`string`?d(B):void 0,fe=typeof R==`string`?d(R):void 0,X=x??(W===null?F??fe:P?de??F:void 0),Z;Z=_?{"aria-hidden":!0,...G}:X!==void 0||S!==void 0?{role:b??`img`,"aria-label":X,"aria-labelledby":S,...G}:W!==null||b!==void 0?{role:b,...G}:{"aria-hidden":!0,...G};let Q=g&&n.slotRendersContent(g)?n.renderSlot(g,`span`,t.cn(i.avatarClassNames.badge,`absolute bottom-0 end-0 inline-flex`)):null,pe=Q!==null,me=p===void 0?T?ne[T.size]:l.medium:l[p],$=t.cn(i.avatarClassNames.visual,`inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold`,me,Y);return pe?(0,c.jsxs)(`span`,{ref:y,...w,className:t.cn(i.avatarClassNames.root,`relative inline-flex shrink-0`,v),children:[(0,c.jsx)(`span`,{ref:j,...Z,className:$,children:J}),Q]}):(0,c.jsx)(`span`,{ref:M,...Z,...w,className:t.cn(i.avatarClassNames.root,$,v),children:J})};m.displayName=`Avatar`,exports.Avatar=m,exports.avatarSizeClasses=l;
|
|
2
2
|
//# sourceMappingURL=Avatar.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.cjs","names":["React","useMergedRefs","cn","avatarClassNames","composeEventHandlers","joinIds","renderSlot","slotRendersContent","PersonIcon","require_runtime","require_cn","require_slot","require_composeEventHandlers","require_classNames","require_useMergedRefs","require_aria","require_icons","react","react_jsx_runtime","avatarSizeClasses","IMAGE_CLASS","getInitials","parts","name","normaliseName","readSlotProps","slot","getImageKey","imageSlot","src","element","slotProps","isPlainObject","value","proto","sameKeyPart","a","b","keys","k","sameImageKey","part","i","Avatar","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaDescription","ariaDetails","rest","image","imageKey","failed","setFailed","prevImageKey","setPrevImageKey","visualRef","img","active","checkedSrc","checkedSrcSet","markFailed","rootVisualRef","ref","hasConsumerName","roleCarriesName","role","normalisedName","imageAlt","decorative","handleError","ownAlt","hasOwnAlt","renderedAlt","description","imageIsNamed","imageDescription","imageNode","overrides","ownIds","visualDescription","iconNode","icon","initials","content","colorClass","imageName","slotAltName","label","a11yProps","badgeNode","badge","hasBadge","visualClassName","size","className"],"sources":["../../../src/components/data-display/Avatar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { cn } from '../../lib/cn';\nimport { avatarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { PersonIcon } from '../../lib/icons';\nimport type { Size, Slot } from '../../lib/types';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\n\n/** Properties for the Avatar component. */\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n /**\n * URL of the avatar image. When it fails to load (also before hydration, for server-rendered\n * markup), the avatar falls back to its icon or initials; a new `src` is tried again.\n */\n src?: string;\n /**\n * Full name of the person. It names the avatar for assistive technology (the image `alt`; in\n * initials and icon mode, or with a consumer `role`, the avatar's `aria-label`, with\n * `role=\"img\"` unless `role` is given) and generates the initials shown when there is no image.\n */\n name?: string;\n /** Size of the avatar.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Icon shown instead of the initials when there is no image. Rendered in an `aria-hidden`\n * `<span>` (a slot object can override its attributes). A falsy value (`null`, `false`, `''`,\n * `0`, `NaN`, e.g. `icon={count && <Icon />}`) counts as no icon, as in 0.4, and so does an\n * array, `Set` or generator whose items render nothing. Without `icon` and without a usable\n * `name`, a generic person glyph is shown.\n */\n icon?: Slot<'span'>;\n /**\n * Custom image. Accepts a URL string (treated like `src`), an element (rendered as the image\n * itself, e.g. `<img>` or a framework image component) or an object of `<img>` attributes\n * (`{ src, alt, … }`). Takes precedence over `src`; its `alt` defaults to `name` (an `alt` that\n * is `undefined` counts as not given). When its alt names the avatar, the avatar's\n * `aria-describedby` ids are joined with the slot's own, while the slot's own `aria-description`\n * and `aria-details` win over the avatar's. When the image fails to load, an avatar without a\n * `name` keeps the name of the slot's own `alt`. After a load failure, a new image is tried\n * again: another `src` or `srcSet` of any type (an equal inline object is the same image), or\n * for an element slot another component type or `key`.\n */\n image?: Slot<'img'>;\n /**\n * Badge shown at the bottom end corner, e.g. `<PresenceBadge status=\"busy\" />`. With a badge\n * the avatar is wrapped in an outer `<span>` that receives `ref`, `className` and the other\n * props; `role`, `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-description` and\n * `aria-details` stay on the avatar visual, so the badge keeps its own accessible name. A falsy\n * value (`null`, `false`, `''`, `0`, `NaN`, e.g. `badge={count && <CounterBadge count={count} />}`)\n * counts as no badge, as in 0.4, and so does an array, `Set` or generator whose items render\n * nothing: the avatar then renders without the wrapper.\n */\n badge?: Slot<'span'>;\n /**\n * Hides the avatar visual from assistive technology (`aria-hidden`, empty image `alt`, no\n * `role=\"img\"`). Use it when the name is already shown next to the avatar (Persona). A badge\n * stays exposed.\n * @default false\n */\n decorative?: boolean;\n /** Ref to the root `<span>`: the avatar itself, or the badge wrapper when `badge` is set. */\n ref?: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * Width, height and text size classes of the avatar per `size`. Module-only (not in the barrel):\n * AvatarGroup sizes its overflow button with the same classes, so the two always match.\n */\nexport const avatarSizeClasses: Readonly<Record<Size, string>> = {\n 'extra-small': 'w-6 h-6 text-[10px]', // 24px\n small: 'w-8 h-8 text-xs', // 32px\n medium: 'w-10 h-10 text-sm', // 40px\n large: 'w-12 h-12 text-base', // 48px\n 'extra-large': 'w-14 h-14 text-lg', // 56px\n};\n\nconst IMAGE_CLASS = 'w-full h-full object-cover';\n\n/** First letter of the first and last word, upper-cased; `''` for a blank name. */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n const first = Array.from(parts[0]!)[0] ?? '';\n const last = parts.length > 1 ? (Array.from(parts[parts.length - 1]!)[0] ?? '') : '';\n return (first + last).toUpperCase();\n}\n\n/** A name with its whitespace collapsed, or `undefined` when it is blank. */\nfunction normaliseName(name: string | undefined): string | undefined {\n return name?.trim().replace(/\\s+/g, ' ') || undefined;\n}\n\ntype ImageErrorHandler = React.ReactEventHandler<HTMLImageElement>;\n\n/** Description props that go to the element carrying the avatar's name (data-display#19). */\ntype DescriptionProps = Pick<\n React.HTMLAttributes<HTMLElement>,\n 'aria-describedby' | 'aria-description' | 'aria-details'\n>;\n\n/** Props the avatar sets on an element or object image slot, over the slot's own. */\ninterface SlotOverrides {\n onError: ImageErrorHandler;\n alt?: string;\n 'aria-describedby'?: string;\n}\n\n/** The props of an element or object image slot that the avatar reads. */\ninterface ImageSlotProps {\n src?: unknown;\n srcSet?: unknown;\n alt?: unknown;\n onError?: unknown;\n 'aria-describedby'?: unknown;\n}\n\n/** The props of an element or object image slot (to read its `src`, `alt` and handlers). */\nfunction readSlotProps(slot: unknown): ImageSlotProps | undefined {\n if (React.isValidElement(slot)) return slot.props as ImageSlotProps;\n if (typeof slot === 'object' && slot !== null && !(Symbol.iterator in slot)) {\n return slot as ImageSlotProps;\n }\n return undefined;\n}\n\n/**\n * What identifies the image, so a load failure is kept for it and a new image is tried again\n * (data-display#4): the `src` and `srcSet`, of any type (a framework image component may take a\n * static-import object), and for an element slot also its type and `key`.\n */\ntype ImageKey = readonly [type: unknown, key: unknown, src: unknown, srcSet: unknown];\n\nfunction getImageKey(\n imageSlot: unknown,\n slotProps: ImageSlotProps | undefined,\n src: string | undefined,\n): ImageKey {\n if (imageSlot === undefined) return [undefined, undefined, src || undefined, undefined];\n if (typeof imageSlot === 'string') return [undefined, undefined, imageSlot, undefined];\n const element = React.isValidElement(imageSlot) ? imageSlot : undefined;\n return [element?.type, element?.key, slotProps?.src, slotProps?.srcSet];\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** Same value, or plain objects with the same entries (an inline `src={{ … }}` on each render). */\nfunction sameKeyPart(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && Object.is(a[k], b[k]))\n );\n}\n\nfunction sameImageKey(a: ImageKey, b: ImageKey): boolean {\n return a.every((part, i) => sameKeyPart(part, b[i]));\n}\n\n/**\n * A circular picture of a person: their image, an icon, or the initials of their `name`.\n *\n * - **Image**: `image` (URL string, element or `{ src, alt }` object) or `src`. If the image fails\n * to load, the avatar falls back to `icon`, the initials or a person glyph, with their\n * background; a new image is tried again. A server-rendered image that failed before hydration\n * is detected after mount (settled without a natural size, confirmed by `decode()`).\n * - **Accessible name**: an image uses `name` (whitespace collapsed) as its `alt`, or `''` when the\n * name is blank. Without an image (none given, or it failed to load) the avatar is `role=\"img\"`\n * with `aria-label={name}` (without a name: the image slot's own `alt`) and the initials/icon\n * are hidden; without either (and without `aria-label`/`aria-labelledby`) it is decorative\n * (`aria-hidden`). A consumer `aria-label`, `aria-labelledby` or `role` (other than\n * `presentation`/`none`) puts the name on the avatar visual, and an image inside it gets\n * `alt=\"\"`. `decorative` hides it in every mode. `aria-describedby`, `aria-description` and\n * `aria-details` go to the element that carries the name: the `<img>` when a non-blank `alt`\n * names it, otherwise the avatar visual (never an `alt=\"\"` image).\n * - **Badge**: `badge` renders at the bottom end corner (logical, RTL-safe) as a sibling of the\n * avatar visual, so a `PresenceBadge` keeps its own name. With a badge, `ref`, `className` and\n * the rest props go to the outer wrapper.\n *\n * @example\n * <Avatar name=\"Jane Doe\" src=\"/jane.jpg\" badge={<PresenceBadge status=\"available\" />} />\n */\nexport const Avatar = ({\n src,\n name,\n size = 'medium',\n icon,\n image,\n badge,\n decorative = false,\n className,\n ref,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n ...rest\n}: AvatarProps) => {\n const imageSlot =\n image === null || image === undefined || typeof image === 'boolean' || image === ''\n ? undefined\n : image;\n const slotProps = readSlotProps(imageSlot);\n const imageKey = getImageKey(imageSlot, slotProps, src);\n\n // Load failure of the current image; a new image is tried again (C-HOOKS: adjust state during\n // render on prop change).\n const [failed, setFailed] = React.useState(false);\n const [prevImageKey, setPrevImageKey] = React.useState(imageKey);\n if (!sameImageKey(prevImageKey, imageKey)) {\n setPrevImageKey(imageKey);\n setFailed(false);\n }\n\n // An image that failed before hydration (a fast 404 of server-rendered markup) never reaches\n // `onError`: React attaches the listener while hydrating and does not replay the event. After\n // mount, a settled image without a natural size is broken, unless it is an SVG without one, so\n // `decode()` (which rejects for a broken image) confirms it where the browser supports it. Later\n // images, rendered by the client, report their errors through `onError`.\n const visualRef = React.useRef<HTMLSpanElement>(null);\n React.useLayoutEffect(() => {\n const img = visualRef.current?.querySelector('img');\n if (!img || !img.complete || img.naturalWidth !== 0) return;\n let active = true;\n const checkedSrc = img.getAttribute('src');\n const checkedSrcSet = img.getAttribute('srcset');\n const markFailed = () => {\n // Deferred (C-HOOKS); skipped if the image was replaced or got another source meanwhile.\n if (\n active &&\n img.isConnected &&\n img.getAttribute('src') === checkedSrc &&\n img.getAttribute('srcset') === checkedSrcSet\n ) {\n setFailed(true);\n }\n };\n if (typeof img.decode === 'function') img.decode().then(undefined, markFailed);\n else queueMicrotask(markFailed);\n return () => {\n active = false;\n };\n }, []);\n const rootVisualRef = useMergedRefs(ref, visualRef);\n\n const hasConsumerName = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n // A consumer role goes to the visual span together with the name (data-display#19), so the\n // image inside it is presentational (`alt=\"\"`), as with a consumer `aria-label`: the children\n // of `role=\"img\"` are not exposed. A presentational role (`presentation`, `none`) cannot carry\n // a name, so the image keeps it.\n const roleCarriesName = role !== undefined && role !== 'presentation' && role !== 'none';\n const normalisedName = normaliseName(name);\n const imageAlt = decorative || hasConsumerName || roleCarriesName ? '' : (normalisedName ?? '');\n const handleError: ImageErrorHandler = () => setFailed(true);\n\n // The alt text the image renders with: an element or object slot's own `alt` wins over ours. An\n // `alt` that is `undefined` (an optional `alt: user.photoAlt`, a wrapper forwarding `alt={alt}`)\n // or `null` is not given, so ours applies (the slot's own value would otherwise override it).\n const ownAlt = slotProps?.alt;\n const hasOwnAlt = ownAlt !== undefined && ownAlt !== null;\n const renderedAlt: unknown = hasOwnAlt ? ownAlt : imageAlt;\n\n // The description goes to the element that carries the name: the image itself when a non-blank\n // `alt` names it (the visual span then has no role, or a presentational one), otherwise the\n // visual span. An image with an empty `alt` is presentational, and a description on it would\n // conflict with that role.\n const description: DescriptionProps = {\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n };\n const imageIsNamed =\n !decorative &&\n !hasConsumerName &&\n !roleCarriesName &&\n typeof renderedAlt === 'string' &&\n renderedAlt.trim() !== '';\n const imageDescription: DescriptionProps = imageIsNamed ? description : {};\n\n let imageNode: React.ReactNode = null;\n if (!failed) {\n if (typeof imageSlot === 'string') {\n imageNode = (\n <img\n src={imageSlot}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n } else if (imageSlot !== undefined) {\n // The slot's own props win over renderSlot's defaults, so the composed `onError`, the\n // default `alt` (when the slot gives none) and the joined `aria-describedby` (the avatar's\n // ids, then the slot's) are set on the slot itself. A slot's own `aria-description` and\n // `aria-details` win over the avatar's.\n const overrides: SlotOverrides = {\n onError: composeEventHandlers(\n slotProps?.onError as ImageErrorHandler | undefined,\n handleError,\n ),\n };\n if (!hasOwnAlt) overrides.alt = imageAlt;\n if (imageIsNamed) {\n const ownIds = slotProps?.['aria-describedby'];\n overrides['aria-describedby'] = joinIds(\n ariaDescribedBy,\n typeof ownIds === 'string' ? ownIds : undefined,\n );\n }\n const slot = React.isValidElement(imageSlot)\n ? React.cloneElement(imageSlot as React.ReactElement<SlotOverrides>, overrides)\n : slotProps\n ? { ...(imageSlot as object), ...overrides }\n : imageSlot;\n imageNode = renderSlot(slot as Slot<'img'>, 'img', cn(avatarClassNames.image, IMAGE_CLASS), {\n alt: imageAlt,\n ...imageDescription,\n });\n } else if (src) {\n imageNode = (\n <img\n src={src}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n }\n }\n const visualDescription = imageNode !== null && imageIsNamed ? {} : description;\n\n // A falsy icon (`icon={count && <Icon />}` with count 0) is no icon, as in 0.4, and so is a\n // collection whose items render nothing (`icon={items.map(…)}` mapping to nothing). The check\n // does not consume a generator: renderSlot still renders its items.\n const iconNode =\n imageNode === null && icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(avatarClassNames.icon, 'inline-flex'), { 'aria-hidden': true })\n : null;\n const initials = imageNode === null && iconNode === null && name ? getInitials(name) : '';\n\n let content: React.ReactNode;\n let colorClass: string | undefined;\n if (imageNode !== null) {\n content = imageNode;\n } else if (iconNode !== null) {\n content = iconNode;\n colorClass = 'bg-muted text-muted-foreground';\n } else if (initials) {\n content = (\n <span aria-hidden=\"true\" className={avatarClassNames.initials}>\n {initials}\n </span>\n );\n colorClass = 'bg-primary text-primary-foreground';\n } else {\n content = <PersonIcon size=\"60%\" className={avatarClassNames.icon} />;\n colorClass = 'bg-muted text-muted-foreground';\n }\n\n // Accessible name of the avatar visual (data-display#19, #27). With a consumer role and an\n // image it is the name the image would carry: an element or object slot's own alt, else `name`.\n // Without an image (none given, or it failed to load) it is `name`, else the slot's own alt: an\n // avatar named only by its image alt keeps that name when the image fails.\n const imageName =\n imageNode !== null && roleCarriesName && typeof renderedAlt === 'string'\n ? normaliseName(renderedAlt)\n : undefined;\n const slotAltName = typeof ownAlt === 'string' ? normaliseName(ownAlt) : undefined;\n const label =\n ariaLabel ??\n (imageNode === null\n ? (normalisedName ?? slotAltName)\n : roleCarriesName\n ? (imageName ?? normalisedName)\n : undefined);\n let a11yProps: React.HTMLAttributes<HTMLSpanElement>;\n if (decorative) {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n } else if (label !== undefined || ariaLabelledBy !== undefined) {\n a11yProps = {\n role: role ?? 'img',\n 'aria-label': label,\n 'aria-labelledby': ariaLabelledBy,\n ...visualDescription,\n };\n } else if (imageNode !== null || role !== undefined) {\n a11yProps = { role, ...visualDescription };\n } else {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n }\n\n // A falsy or empty badge (`badge={count && <CounterBadge … />}` with count 0) is no badge, as in\n // 0.4 and like `icon`: no stray \"0\" in the corner, and no wrapper taking the root props.\n const badgeNode =\n badge && slotRendersContent(badge)\n ? renderSlot(badge, 'span', cn(avatarClassNames.badge, 'absolute bottom-0 end-0 inline-flex'))\n : null;\n const hasBadge = badgeNode !== null;\n\n const visualClassName = cn(\n avatarClassNames.visual,\n 'inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold',\n avatarSizeClasses[size],\n colorClass,\n );\n\n if (!hasBadge) {\n return (\n <span\n ref={rootVisualRef}\n {...a11yProps}\n {...rest}\n className={cn(avatarClassNames.root, visualClassName, className)}\n >\n {content}\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n {...rest}\n className={cn(avatarClassNames.root, 'relative inline-flex shrink-0', className)}\n >\n <span ref={visualRef} {...a11yProps} className={visualClassName}>\n {content}\n </span>\n {badgeNode}\n </span>\n );\n};\n\nAvatar.displayName = 'Avatar';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Avatar.cjs","names":["React","AvatarSizeContext","useMergedRefs","cn","avatarClassNames","composeEventHandlers","joinIds","renderSlot","slotRendersContent","PersonIcon","require_runtime","require_cn","require_slot","require_composeEventHandlers","require_classNames","require_useMergedRefs","require_aria","require_icons","require_Avatar_context","react","react_jsx_runtime","avatarSizeClasses","AVATAR_BOX_CLASSES","IMAGE_CLASS","getInitials","parts","name","normaliseName","readSlotProps","slot","getImageKey","imageSlot","src","element","slotProps","isPlainObject","value","proto","sameKeyPart","a","b","keys","k","sameImageKey","part","i","Avatar","sizeProp","ariaLabel","ariaLabelledBy","ariaDescribedBy","ariaDescription","ariaDetails","rest","box","image","imageKey","failed","setFailed","prevImageKey","setPrevImageKey","visualRef","img","active","checkedSrc","checkedSrcSet","markFailed","rootVisualRef","ref","hasConsumerName","roleCarriesName","role","normalisedName","imageAlt","decorative","handleError","ownAlt","hasOwnAlt","renderedAlt","description","imageIsNamed","imageDescription","imageNode","overrides","ownIds","visualDescription","iconNode","icon","initials","content","colorClass","imageName","slotAltName","label","a11yProps","badgeNode","badge","hasBadge","sizeClasses","visualClassName","className"],"sources":["../../../src/components/data-display/Avatar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { joinIds } from '../../lib/aria';\nimport { cn } from '../../lib/cn';\nimport { avatarClassNames } from '../../lib/classNames';\nimport { composeEventHandlers } from '../../lib/composeEventHandlers';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { PersonIcon } from '../../lib/icons';\nimport type { Size, Slot } from '../../lib/types';\nimport { renderSlot, slotRendersContent } from '../../lib/slot';\nimport { AvatarSizeContext, type AvatarSizeContextValue } from './Avatar.context';\n\n/** Properties for the Avatar component. */\nexport interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {\n /**\n * URL of the avatar image. When it fails to load (also before hydration, for server-rendered\n * markup), the avatar falls back to its icon or initials; a new `src` is tried again.\n */\n src?: string;\n /**\n * Full name of the person. It names the avatar for assistive technology (the image `alt`; in\n * initials and icon mode, or with a consumer `role`, the avatar's `aria-label`, with\n * `role=\"img\"` unless `role` is given) and generates the initials shown when there is no image.\n */\n name?: string;\n /**\n * Size of the avatar. Without it, an Avatar in the `media` of a tag (Tag, InteractionTag) takes\n * the tag's media box instead: 24, 20 or 16px by the tag's size.\n * @default 'medium'\n */\n size?: Size;\n /**\n * Icon shown instead of the initials when there is no image. Rendered in an `aria-hidden`\n * `<span>` (a slot object can override its attributes). A falsy value (`null`, `false`, `''`,\n * `0`, `NaN`, e.g. `icon={count && <Icon />}`) counts as no icon, as in 0.4, and so does an\n * array, `Set` or generator whose items render nothing. Without `icon` and without a usable\n * `name`, a generic person glyph is shown.\n */\n icon?: Slot<'span'>;\n /**\n * Custom image. Accepts a URL string (treated like `src`), an element (rendered as the image\n * itself, e.g. `<img>` or a framework image component) or an object of `<img>` attributes\n * (`{ src, alt, … }`). Takes precedence over `src`; its `alt` defaults to `name` (an `alt` that\n * is `undefined` counts as not given). When its alt names the avatar, the avatar's\n * `aria-describedby` ids are joined with the slot's own, while the slot's own `aria-description`\n * and `aria-details` win over the avatar's. When the image fails to load, an avatar without a\n * `name` keeps the name of the slot's own `alt`. After a load failure, a new image is tried\n * again: another `src` or `srcSet` of any type (an equal inline object is the same image), or\n * for an element slot another component type or `key`.\n */\n image?: Slot<'img'>;\n /**\n * Badge shown at the bottom end corner, e.g. `<PresenceBadge status=\"busy\" />`. With a badge\n * the avatar is wrapped in an outer `<span>` that receives `ref`, `className` and the other\n * props; `role`, `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-description` and\n * `aria-details` stay on the avatar visual, so the badge keeps its own accessible name. A falsy\n * value (`null`, `false`, `''`, `0`, `NaN`, e.g. `badge={count && <CounterBadge count={count} />}`)\n * counts as no badge, as in 0.4, and so does an array, `Set` or generator whose items render\n * nothing: the avatar then renders without the wrapper.\n */\n badge?: Slot<'span'>;\n /**\n * Hides the avatar visual from assistive technology (`aria-hidden`, empty image `alt`, no\n * `role=\"img\"`). Use it when the name is already shown next to the avatar (Persona). A badge\n * stays exposed.\n * @default false\n */\n decorative?: boolean;\n /** Ref to the root `<span>`: the avatar itself, or the badge wrapper when `badge` is set. */\n ref?: React.Ref<HTMLSpanElement>;\n}\n\n/**\n * Width, height and text size classes of the avatar per `size`. Module-only (not in the barrel):\n * AvatarGroup sizes its overflow button with the same classes, so the two always match.\n */\nexport const avatarSizeClasses: Readonly<Record<Size, string>> = {\n 'extra-small': 'w-6 h-6 text-[10px]', // 24px\n small: 'w-8 h-8 text-xs', // 32px\n medium: 'w-10 h-10 text-sm', // 40px\n large: 'w-12 h-12 text-base', // 48px\n 'extra-large': 'w-14 h-14 text-lg', // 56px\n};\n\n/**\n * Width, height and text size classes of each box of {@link AvatarSizeContext}, for an Avatar\n * that sets no `size`: 24px is the `extra-small` size, 20px and 16px are internal boxes.\n */\nconst AVATAR_BOX_CLASSES: Readonly<Record<AvatarSizeContextValue['size'], string>> = {\n 24: avatarSizeClasses['extra-small'],\n 20: 'w-5 h-5 text-[10px]',\n 16: 'w-4 h-4 text-[10px]',\n};\n\nconst IMAGE_CLASS = 'w-full h-full object-cover';\n\n/** First letter of the first and last word, upper-cased; `''` for a blank name. */\nfunction getInitials(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return '';\n const first = Array.from(parts[0]!)[0] ?? '';\n const last = parts.length > 1 ? (Array.from(parts[parts.length - 1]!)[0] ?? '') : '';\n return (first + last).toUpperCase();\n}\n\n/** A name with its whitespace collapsed, or `undefined` when it is blank. */\nfunction normaliseName(name: string | undefined): string | undefined {\n return name?.trim().replace(/\\s+/g, ' ') || undefined;\n}\n\ntype ImageErrorHandler = React.ReactEventHandler<HTMLImageElement>;\n\n/** Description props that go to the element carrying the avatar's name (data-display#19). */\ntype DescriptionProps = Pick<\n React.HTMLAttributes<HTMLElement>,\n 'aria-describedby' | 'aria-description' | 'aria-details'\n>;\n\n/** Props the avatar sets on an element or object image slot, over the slot's own. */\ninterface SlotOverrides {\n onError: ImageErrorHandler;\n alt?: string;\n 'aria-describedby'?: string;\n}\n\n/** The props of an element or object image slot that the avatar reads. */\ninterface ImageSlotProps {\n src?: unknown;\n srcSet?: unknown;\n alt?: unknown;\n onError?: unknown;\n 'aria-describedby'?: unknown;\n}\n\n/** The props of an element or object image slot (to read its `src`, `alt` and handlers). */\nfunction readSlotProps(slot: unknown): ImageSlotProps | undefined {\n if (React.isValidElement(slot)) return slot.props as ImageSlotProps;\n if (typeof slot === 'object' && slot !== null && !(Symbol.iterator in slot)) {\n return slot as ImageSlotProps;\n }\n return undefined;\n}\n\n/**\n * What identifies the image, so a load failure is kept for it and a new image is tried again\n * (data-display#4): the `src` and `srcSet`, of any type (a framework image component may take a\n * static-import object), and for an element slot also its type and `key`.\n */\ntype ImageKey = readonly [type: unknown, key: unknown, src: unknown, srcSet: unknown];\n\nfunction getImageKey(\n imageSlot: unknown,\n slotProps: ImageSlotProps | undefined,\n src: string | undefined,\n): ImageKey {\n if (imageSlot === undefined) return [undefined, undefined, src || undefined, undefined];\n if (typeof imageSlot === 'string') return [undefined, undefined, imageSlot, undefined];\n const element = React.isValidElement(imageSlot) ? imageSlot : undefined;\n return [element?.type, element?.key, slotProps?.src, slotProps?.srcSet];\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** Same value, or plain objects with the same entries (an inline `src={{ … }}` on each render). */\nfunction sameKeyPart(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (!isPlainObject(a) || !isPlainObject(b)) return false;\n const keys = Object.keys(a);\n return (\n keys.length === Object.keys(b).length &&\n keys.every((k) => Object.prototype.hasOwnProperty.call(b, k) && Object.is(a[k], b[k]))\n );\n}\n\nfunction sameImageKey(a: ImageKey, b: ImageKey): boolean {\n return a.every((part, i) => sameKeyPart(part, b[i]));\n}\n\n/**\n * A circular picture of a person: their image, an icon, or the initials of their `name`.\n *\n * - **Image**: `image` (URL string, element or `{ src, alt }` object) or `src`. If the image fails\n * to load, the avatar falls back to `icon`, the initials or a person glyph, with their\n * background; a new image is tried again. A server-rendered image that failed before hydration\n * is detected after mount (settled without a natural size, confirmed by `decode()`).\n * - **Accessible name**: an image uses `name` (whitespace collapsed) as its `alt`, or `''` when the\n * name is blank. Without an image (none given, or it failed to load) the avatar is `role=\"img\"`\n * with `aria-label={name}` (without a name: the image slot's own `alt`) and the initials/icon\n * are hidden; without either (and without `aria-label`/`aria-labelledby`) it is decorative\n * (`aria-hidden`). A consumer `aria-label`, `aria-labelledby` or `role` (other than\n * `presentation`/`none`) puts the name on the avatar visual, and an image inside it gets\n * `alt=\"\"`. `decorative` hides it in every mode. `aria-describedby`, `aria-description` and\n * `aria-details` go to the element that carries the name: the `<img>` when a non-blank `alt`\n * names it, otherwise the avatar visual (never an `alt=\"\"` image).\n * - **Badge**: `badge` renders at the bottom end corner (logical, RTL-safe) as a sibling of the\n * avatar visual, so a `PresenceBadge` keeps its own name. With a badge, `ref`, `className` and\n * the rest props go to the outer wrapper.\n *\n * @example\n * <Avatar name=\"Jane Doe\" src=\"/jane.jpg\" badge={<PresenceBadge status=\"available\" />} />\n */\nexport const Avatar = ({\n src,\n name,\n size: sizeProp,\n icon,\n image,\n badge,\n decorative = false,\n className,\n ref,\n role,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n ...rest\n}: AvatarProps) => {\n // The media box of a surrounding Tag or InteractionTag, for an Avatar without its own `size`.\n const box = React.useContext(AvatarSizeContext);\n const imageSlot =\n image === null || image === undefined || typeof image === 'boolean' || image === ''\n ? undefined\n : image;\n const slotProps = readSlotProps(imageSlot);\n const imageKey = getImageKey(imageSlot, slotProps, src);\n\n // Load failure of the current image; a new image is tried again (C-HOOKS: adjust state during\n // render on prop change).\n const [failed, setFailed] = React.useState(false);\n const [prevImageKey, setPrevImageKey] = React.useState(imageKey);\n if (!sameImageKey(prevImageKey, imageKey)) {\n setPrevImageKey(imageKey);\n setFailed(false);\n }\n\n // An image that failed before hydration (a fast 404 of server-rendered markup) never reaches\n // `onError`: React attaches the listener while hydrating and does not replay the event. After\n // mount, a settled image without a natural size is broken, unless it is an SVG without one, so\n // `decode()` (which rejects for a broken image) confirms it where the browser supports it. Later\n // images, rendered by the client, report their errors through `onError`.\n const visualRef = React.useRef<HTMLSpanElement>(null);\n React.useLayoutEffect(() => {\n const img = visualRef.current?.querySelector('img');\n if (!img || !img.complete || img.naturalWidth !== 0) return;\n let active = true;\n const checkedSrc = img.getAttribute('src');\n const checkedSrcSet = img.getAttribute('srcset');\n const markFailed = () => {\n // Deferred (C-HOOKS); skipped if the image was replaced or got another source meanwhile.\n if (\n active &&\n img.isConnected &&\n img.getAttribute('src') === checkedSrc &&\n img.getAttribute('srcset') === checkedSrcSet\n ) {\n setFailed(true);\n }\n };\n if (typeof img.decode === 'function') img.decode().then(undefined, markFailed);\n else queueMicrotask(markFailed);\n return () => {\n active = false;\n };\n }, []);\n const rootVisualRef = useMergedRefs(ref, visualRef);\n\n const hasConsumerName = ariaLabel !== undefined || ariaLabelledBy !== undefined;\n // A consumer role goes to the visual span together with the name (data-display#19), so the\n // image inside it is presentational (`alt=\"\"`), as with a consumer `aria-label`: the children\n // of `role=\"img\"` are not exposed. A presentational role (`presentation`, `none`) cannot carry\n // a name, so the image keeps it.\n const roleCarriesName = role !== undefined && role !== 'presentation' && role !== 'none';\n const normalisedName = normaliseName(name);\n const imageAlt = decorative || hasConsumerName || roleCarriesName ? '' : (normalisedName ?? '');\n const handleError: ImageErrorHandler = () => setFailed(true);\n\n // The alt text the image renders with: an element or object slot's own `alt` wins over ours. An\n // `alt` that is `undefined` (an optional `alt: user.photoAlt`, a wrapper forwarding `alt={alt}`)\n // or `null` is not given, so ours applies (the slot's own value would otherwise override it).\n const ownAlt = slotProps?.alt;\n const hasOwnAlt = ownAlt !== undefined && ownAlt !== null;\n const renderedAlt: unknown = hasOwnAlt ? ownAlt : imageAlt;\n\n // The description goes to the element that carries the name: the image itself when a non-blank\n // `alt` names it (the visual span then has no role, or a presentational one), otherwise the\n // visual span. An image with an empty `alt` is presentational, and a description on it would\n // conflict with that role.\n const description: DescriptionProps = {\n 'aria-describedby': ariaDescribedBy,\n 'aria-description': ariaDescription,\n 'aria-details': ariaDetails,\n };\n const imageIsNamed =\n !decorative &&\n !hasConsumerName &&\n !roleCarriesName &&\n typeof renderedAlt === 'string' &&\n renderedAlt.trim() !== '';\n const imageDescription: DescriptionProps = imageIsNamed ? description : {};\n\n let imageNode: React.ReactNode = null;\n if (!failed) {\n if (typeof imageSlot === 'string') {\n imageNode = (\n <img\n src={imageSlot}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n } else if (imageSlot !== undefined) {\n // The slot's own props win over renderSlot's defaults, so the composed `onError`, the\n // default `alt` (when the slot gives none) and the joined `aria-describedby` (the avatar's\n // ids, then the slot's) are set on the slot itself. A slot's own `aria-description` and\n // `aria-details` win over the avatar's.\n const overrides: SlotOverrides = {\n onError: composeEventHandlers(\n slotProps?.onError as ImageErrorHandler | undefined,\n handleError,\n ),\n };\n if (!hasOwnAlt) overrides.alt = imageAlt;\n if (imageIsNamed) {\n const ownIds = slotProps?.['aria-describedby'];\n overrides['aria-describedby'] = joinIds(\n ariaDescribedBy,\n typeof ownIds === 'string' ? ownIds : undefined,\n );\n }\n const slot = React.isValidElement(imageSlot)\n ? React.cloneElement(imageSlot as React.ReactElement<SlotOverrides>, overrides)\n : slotProps\n ? { ...(imageSlot as object), ...overrides }\n : imageSlot;\n imageNode = renderSlot(slot as Slot<'img'>, 'img', cn(avatarClassNames.image, IMAGE_CLASS), {\n alt: imageAlt,\n ...imageDescription,\n });\n } else if (src) {\n imageNode = (\n <img\n src={src}\n alt={imageAlt}\n {...imageDescription}\n className={cn(avatarClassNames.image, IMAGE_CLASS)}\n onError={handleError}\n />\n );\n }\n }\n const visualDescription = imageNode !== null && imageIsNamed ? {} : description;\n\n // A falsy icon (`icon={count && <Icon />}` with count 0) is no icon, as in 0.4, and so is a\n // collection whose items render nothing (`icon={items.map(…)}` mapping to nothing). The check\n // does not consume a generator: renderSlot still renders its items.\n const iconNode =\n imageNode === null && icon && slotRendersContent(icon)\n ? renderSlot(icon, 'span', cn(avatarClassNames.icon, 'inline-flex'), { 'aria-hidden': true })\n : null;\n const initials = imageNode === null && iconNode === null && name ? getInitials(name) : '';\n\n let content: React.ReactNode;\n let colorClass: string | undefined;\n if (imageNode !== null) {\n content = imageNode;\n } else if (iconNode !== null) {\n content = iconNode;\n colorClass = 'bg-muted text-muted-foreground';\n } else if (initials) {\n content = (\n <span aria-hidden=\"true\" className={avatarClassNames.initials}>\n {initials}\n </span>\n );\n colorClass = 'bg-primary text-primary-foreground';\n } else {\n content = <PersonIcon size=\"60%\" className={avatarClassNames.icon} />;\n colorClass = 'bg-muted text-muted-foreground';\n }\n\n // Accessible name of the avatar visual (data-display#19, #27). With a consumer role and an\n // image it is the name the image would carry: an element or object slot's own alt, else `name`.\n // Without an image (none given, or it failed to load) it is `name`, else the slot's own alt: an\n // avatar named only by its image alt keeps that name when the image fails.\n const imageName =\n imageNode !== null && roleCarriesName && typeof renderedAlt === 'string'\n ? normaliseName(renderedAlt)\n : undefined;\n const slotAltName = typeof ownAlt === 'string' ? normaliseName(ownAlt) : undefined;\n const label =\n ariaLabel ??\n (imageNode === null\n ? (normalisedName ?? slotAltName)\n : roleCarriesName\n ? (imageName ?? normalisedName)\n : undefined);\n let a11yProps: React.HTMLAttributes<HTMLSpanElement>;\n if (decorative) {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n } else if (label !== undefined || ariaLabelledBy !== undefined) {\n a11yProps = {\n role: role ?? 'img',\n 'aria-label': label,\n 'aria-labelledby': ariaLabelledBy,\n ...visualDescription,\n };\n } else if (imageNode !== null || role !== undefined) {\n a11yProps = { role, ...visualDescription };\n } else {\n a11yProps = { 'aria-hidden': true, ...visualDescription };\n }\n\n // A falsy or empty badge (`badge={count && <CounterBadge … />}` with count 0) is no badge, as in\n // 0.4 and like `icon`: no stray \"0\" in the corner, and no wrapper taking the root props.\n const badgeNode =\n badge && slotRendersContent(badge)\n ? renderSlot(badge, 'span', cn(avatarClassNames.badge, 'absolute bottom-0 end-0 inline-flex'))\n : null;\n const hasBadge = badgeNode !== null;\n\n // An own `size` wins; without one, the box of a surrounding tag's media, else medium. With a\n // badge the visual is sized, not the wrapper.\n const sizeClasses =\n sizeProp !== undefined\n ? avatarSizeClasses[sizeProp]\n : box\n ? AVATAR_BOX_CLASSES[box.size]\n : avatarSizeClasses.medium;\n const visualClassName = cn(\n avatarClassNames.visual,\n 'inline-flex items-center justify-center rounded-full overflow-hidden shrink-0 font-bold',\n sizeClasses,\n colorClass,\n );\n\n if (!hasBadge) {\n return (\n <span\n ref={rootVisualRef}\n {...a11yProps}\n {...rest}\n className={cn(avatarClassNames.root, visualClassName, className)}\n >\n {content}\n </span>\n );\n }\n\n return (\n <span\n ref={ref}\n {...rest}\n className={cn(avatarClassNames.root, 'relative inline-flex shrink-0', className)}\n >\n <span ref={visualRef} {...a11yProps} className={visualClassName}>\n {content}\n </span>\n {badgeNode}\n </span>\n );\n};\n\nAvatar.displayName = 'Avatar';\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.context.cjs","names":["React","require_runtime","react","AvatarSizeContext"],"sources":["../../../src/components/data-display/Avatar.context.ts"],"sourcesContent":["import * as React from 'react';\n\n/*\n * The box a container gives the Avatars inside it that set no `size`: Tag and\n * InteractionTag.Primary provide it around their `media`, so a person's Avatar there matches the\n * tag's size. Internal (never exported from a barrel); imports no component, so a Tag that reads\n * it holds no Avatar code.\n */\n\n/**\n * The box a container gives the Avatars inside it that set no `size` (Tag and InteractionTag\n * media). Internal.\n */\nexport interface AvatarSizeContextValue {\n /** The box: 24px (Avatar's `extra-small`), or the internal 20px and 16px boxes. */\n size: 16 | 20 | 24;\n}\n\n/** Internal: provided by Tag and InteractionTag.Primary around their `media`; `null` elsewhere. */\nexport const AvatarSizeContext = React.createContext<AvatarSizeContextValue | null>(null);\nAvatarSizeContext.displayName = 'AvatarSizeContext';\n"],"mappings":"6GAmBA,IAAaG,EAAoBH,EAAM,cAA6C,IAAI,EACxF,EAAkB,YAAc"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import * as e from "react";
|
|
3
|
+
//#region src/components/data-display/Avatar.context.ts
|
|
4
|
+
var t = e.createContext(null);
|
|
5
|
+
t.displayName = "AvatarSizeContext";
|
|
6
|
+
//#endregion
|
|
7
|
+
export { t as AvatarSizeContext };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=Avatar.context.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Avatar.context.mjs","names":["React","AvatarSizeContext"],"sources":["../../../src/components/data-display/Avatar.context.ts"],"sourcesContent":["import * as React from 'react';\n\n/*\n * The box a container gives the Avatars inside it that set no `size`: Tag and\n * InteractionTag.Primary provide it around their `media`, so a person's Avatar there matches the\n * tag's size. Internal (never exported from a barrel); imports no component, so a Tag that reads\n * it holds no Avatar code.\n */\n\n/**\n * The box a container gives the Avatars inside it that set no `size` (Tag and InteractionTag\n * media). Internal.\n */\nexport interface AvatarSizeContextValue {\n /** The box: 24px (Avatar's `extra-small`), or the internal 20px and 16px boxes. */\n size: 16 | 20 | 24;\n}\n\n/** Internal: provided by Tag and InteractionTag.Primary around their `media`; `null` elsewhere. */\nexport const AvatarSizeContext = React.createContext<AvatarSizeContextValue | null>(null);\nAvatarSizeContext.displayName = 'AvatarSizeContext';\n"],"mappings":";;;AAmBA,IAAaC,IAAoBD,EAAM,cAA6C,IAAI;AACxF,EAAkB,cAAc"}
|