@payfit/unity-components 2.60.8 → 2.60.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/esm/components/action-bar/ActionBar.d.ts +4 -0
  2. package/dist/esm/components/actionable/Actionable.d.ts +4 -0
  3. package/dist/esm/components/alert/Alert.d.ts +5 -0
  4. package/dist/esm/components/alert/parts/AlertContent.d.ts +2 -2
  5. package/dist/esm/components/app-menu/parts/AppMenuFooter.d.ts +8 -33
  6. package/dist/esm/components/app-menu/parts/AppMenuFooter.js +14 -180
  7. package/dist/esm/components/app-profile-menu-button/AppProfileMenuButton.d.ts +25 -0
  8. package/dist/esm/components/app-profile-menu-button/AppProfileMenuButton.js +70 -0
  9. package/dist/esm/components/app-profile-menu-button/parts/AppProfileAvatar.d.ts +18 -0
  10. package/dist/esm/components/app-profile-menu-button/parts/AppProfileAvatar.js +79 -0
  11. package/dist/esm/components/app-profile-menu-button/parts/AppProfileMenuHeader.d.ts +14 -0
  12. package/dist/esm/components/app-profile-menu-button/parts/AppProfileMenuHeader.js +88 -0
  13. package/dist/esm/components/avatar/Avatar.d.ts +12 -27
  14. package/dist/esm/components/badge/Badge.d.ts +4 -0
  15. package/dist/esm/components/carousel/Carousel.d.ts +4 -0
  16. package/dist/esm/components/data-table/parts/DataTableBulkActions.d.ts +1 -0
  17. package/dist/esm/components/filter-toolbar/FilterToolbar.d.ts +1 -0
  18. package/dist/esm/components/icon/Icon.d.ts +3 -0
  19. package/dist/esm/components/link/RawLink.d.ts +3 -0
  20. package/dist/esm/components/payfit-brand/PayFitBrand.d.ts +3 -0
  21. package/dist/esm/components/radio-button-group/RadioButtonGroup.d.ts +3 -0
  22. package/dist/esm/components/skip-links/SkipLinks.d.ts +3 -0
  23. package/dist/esm/components/spinner/Spinner.d.ts +7 -0
  24. package/dist/esm/components/timeline/Timeline.d.ts +4 -0
  25. package/dist/esm/docs/reference/catalog/catalog.generated.d.ts +1 -1
  26. package/dist/esm/index.d.ts +1 -0
  27. package/dist/esm/index.js +215 -214
  28. package/i18n/en-GB.json +1 -0
  29. package/i18n/es-ES.json +1 -0
  30. package/i18n/fr-FR.json +1 -0
  31. package/package.json +7 -7
  32. package/src/agent-references/component-catalog.json +29 -0
@@ -84,6 +84,10 @@ export type { ActionBarActionItem, ActionBarActionItemBase, ActionBarBaseProps,
84
84
  * - Actions support `type: 'button'` (default) or `type: 'icon-button'` for icon-only buttons
85
85
  * - All action-specific props (onPress, prefixIcon, icon, isDisabled, isLoading) go in the `meta` object
86
86
  * - Includes proper ARIA labels and live regions for accessibility
87
+ * - Uses `role="toolbar"` to expose the toolbar semantics to assistive technologies
88
+ * - Groups related actions with `role="group"` inside the toolbar
89
+ * - Provide a concise `aria-label` when the default "Actions toolbar" label is not specific enough
90
+ * - Supports keyboard navigation between actions with Tab and the left and right arrow keys
87
91
  * @see {@link ActionBarProps} for all available props
88
92
  * @see {@link ActionBarActionItem} for action item structure
89
93
  * @see Source code in [Github](https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/action-bar)
@@ -53,6 +53,10 @@ export interface ActionableProps extends AriaButtonProps {
53
53
  * - Supports both static children and render prop pattern for dynamic content
54
54
  * - Use data attributes (`data-hovered`, `data-pressed`, `data-focused`, `data-disabled`, `data-focus-visible`) for styling non-button elements
55
55
  * - Marked as `uy:group` for styling child elements based on parent state
56
+ * - Provide an accessible name for every actionable surface
57
+ * - Use `aria-labelledby` when a visible label already exists, and `aria-describedby` when extra context describes the action
58
+ * - Use `aria-label`, `aria-description`, or `aria-details` when no visible label or description is available
59
+ * - Add relationship attributes such as `aria-controls`, `aria-expanded`, or `aria-haspopup` when the actionable surface controls another element
56
60
  * @see {@link ActionableProps} for all available props
57
61
  * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/actionable GitHub}
58
62
  * @see Developer docs in {@link https://unity-components.payfit.io/?path=/docs/primitives-actionable--docs unity-components.payfit.io}
@@ -50,6 +50,11 @@ export type AlertProps = BaseAlertProps & DismissableConfig & VariantConfig;
50
50
  * <AlertTitle>Pro Tip</AlertTitle>
51
51
  * <AlertContent>Use keyboard shortcuts to navigate faster.</AlertContent>
52
52
  * </Alert>
53
+ * @remarks
54
+ * - Uses `role="status"` with polite announcements for non-critical variants
55
+ * - Uses `role="alert"` with assertive announcements for the `danger` variant
56
+ * - Sets `aria-atomic` so assistive technologies announce the alert as a whole
57
+ * - Follow the WAI-ARIA alert guidance when deciding whether content should interrupt the user
53
58
  */
54
59
  declare const Alert: import('react').ForwardRefExoticComponent<AlertProps & import('react').RefAttributes<HTMLDivElement>>;
55
60
  export { Alert };
@@ -2,14 +2,14 @@ import { TextProps } from '../../text/Text.js';
2
2
  type ContentElements = 'div' | 'p' | 'span';
3
3
  export type AlertContentProps = Omit<TextProps, 'variant' | 'color' | 'className'> & {
4
4
  /**
5
- * The underlying HTML element to render the title as.
5
+ * The underlying HTML element to render the content as.
6
6
  * @default 'p'
7
7
  */
8
8
  asElement?: ContentElements;
9
9
  };
10
10
  declare const AlertContent: import('react').ForwardRefExoticComponent<Omit<TextProps, "color" | "className" | "variant"> & {
11
11
  /**
12
- * The underlying HTML element to render the title as.
12
+ * The underlying HTML element to render the content as.
13
13
  * @default 'p'
14
14
  */
15
15
  asElement?: ContentElements;
@@ -1,35 +1,10 @@
1
- import { ReactElement, ReactNode } from 'react';
2
- import { AvatarPairProps } from '../../avatar/parts/AvatarPair.js';
3
- type CommonProps = {
4
- avatar?: string;
5
- avatarPair?: ReactElement<AvatarPairProps>;
6
- title?: string;
7
- description?: ReactNode;
8
- badgeLabel?: string;
9
- /**
10
- * Use this to provide a custom context to the screen reader. Press this button to open the profile menu.
11
- */
12
- menuTriggerDescription?: string;
13
- uploadAvatarCallback?: () => void;
14
- /**
15
- * Use this to provide a custom context to the screen reader. Default is "Press enter to change profile picture"
16
- */
17
- uploadAvatarDescription?: string;
18
- /**
19
- * Use this to provide a custom context to the screen reader. Default is Change profile picture
20
- */
21
- uploadAvatarLabel?: string;
22
- /**
23
- * This slot is used to render the update notification.
24
- */
25
- updateNotificationSlot?: ReactNode;
26
- };
27
- export type AppMenuFooterProps = CommonProps & {
28
- children?: ReactNode;
1
+ import { ReactNode } from 'react';
2
+ import { AppProfileMenuButtonProps } from '../../app-profile-menu-button/AppProfileMenuButton.js';
3
+ export type AppMenuFooterProps = Omit<AppProfileMenuButtonProps, 'variant'> & {
29
4
  computeSlot?: ReactNode;
5
+ /** This slot is used to render the update notification. */
6
+ updateNotificationSlot?: ReactNode;
7
+ /** Whether the profile control is available at desktop breakpoints. */
8
+ isProfileMenuButtonVisibleOnDesktop?: boolean;
30
9
  };
31
- export type AppMenuFooterHeaderProps = CommonProps & {
32
- asMenuHeader?: boolean;
33
- };
34
- export declare const AppMenuFooter: ({ avatar, avatarPair, badgeLabel, children, computeSlot, description, title, menuTriggerDescription, uploadAvatarCallback, uploadAvatarLabel, uploadAvatarDescription, updateNotificationSlot, }: AppMenuFooterProps) => import("react/jsx-runtime").JSX.Element;
35
- export {};
10
+ export declare const AppMenuFooter: ({ children, computeSlot, isProfileMenuButtonVisibleOnDesktop, updateNotificationSlot, ...profileMenuButtonProps }: AppMenuFooterProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,190 +1,24 @@
1
- import { Actionable as e } from "../../actionable/Actionable.js";
2
- import { Icon as t } from "../../icon/Icon.js";
3
- import { Menu as n } from "../../menu/Menu.js";
4
- import { MenuContent as r } from "../../menu/parts/MenuContent.js";
5
- import { MenuTrigger as i } from "../../menu/parts/MenuTrigger.js";
6
- import { useAppMenuContext as a } from "./AppMenu.context.js";
7
- import { Avatar as o } from "../../avatar/Avatar.js";
8
- import { AvatarFallback as s } from "../../avatar/parts/AvatarFallback.js";
9
- import { AvatarImage as c } from "../../avatar/parts/AvatarImage.js";
10
- import { Badge as l } from "../../badge/Badge.js";
11
- import { MenuHeader as u } from "../../menu/parts/MenuHeader.js";
12
- import { cloneElement as d, isValidElement as f, useRef as p, useState as m } from "react";
13
- import { uyMerge as h } from "@payfit/unity-themes";
14
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
15
- import { FormattedMessage as v, useIntl as y } from "react-intl";
1
+ import { isDesktopBreakpoint as e, useBreakpointListener as t } from "../../../hooks/use-breakpoint-listener.js";
2
+ import { useAppMenuContext as n } from "./AppMenu.context.js";
3
+ import { AppProfileMenuButton as r } from "../../app-profile-menu-button/AppProfileMenuButton.js";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
16
5
  //#region src/components/app-menu/parts/AppMenuFooter.tsx
17
- var b = (e) => /* @__PURE__ */ _(o, {
18
- "aria-label": `${e.title} avatar`,
19
- size: "md",
20
- variant: "square",
21
- "aria-labelledby": "profile-button-label",
22
- children: [
23
- /* @__PURE__ */ g(c, {
24
- src: e.avatar,
25
- alt: e.title ?? ""
26
- }),
27
- /* @__PURE__ */ g(s, {
28
- variant: "initials",
29
- delayMs: 100,
30
- children: e.title
31
- }),
32
- e.avatarPair && f(e.avatarPair) && d(e.avatarPair, { isHidden: !e.isPairAvatarVisible })
33
- ]
34
- }), x = ({ avatar: n, avatarPair: r, title: i, uploadAvatarCallback: a, uploadAvatarLabel: o, uploadAvatarDescription: s }) => {
35
- let [c, l] = m(!0), u = y(), d = () => {
36
- r && l((e) => !e);
37
- }, f = h("uy:group/avatar uy:cursor-pointer uy:relative uy:leading-[0] uy:rounded-75 uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-utility-focus-ring uy:focus-visible:ring-offset-2");
38
- return /* @__PURE__ */ _(e, {
39
- "aria-describedby": "profile-picture-change-desc",
40
- "aria-label": o || u.formatMessage({
41
- id: "unity:component:app-menu:footer:profile-button:avatar:change",
42
- defaultMessage: "Change profile picture"
43
- }),
44
- className: f,
45
- onHoverStart: d,
46
- onHoverEnd: d,
47
- onFocus: d,
48
- onBlur: d,
49
- onPress: () => {
50
- a?.();
51
- },
52
- children: [/* @__PURE__ */ g(b, {
53
- avatar: n,
54
- avatarPair: r,
55
- title: i,
56
- isPairAvatarVisible: c
57
- }), /* @__PURE__ */ _("div", {
58
- className: "uy:flex uy:pointer-events-none uy:opacity-0 uy:group-hover/avatar:opacity-90 uy:group-hover/avatar:pointer-events-auto uy:group-focus-visible/avatar:opacity-90 uy:group-focus-visible/avatar:pointer-events-auto uy:bg-utility-backdrop uy:rounded-75 uy:absolute uy:top-0 uy:left-0 uy:w-full uy:h-full uy:transition-all uy:duration-200 uy:items-center uy:justify-center",
59
- children: [/* @__PURE__ */ g(t, {
60
- alt: "Camera",
61
- color: "content.inverted",
62
- size: 24,
63
- src: "CameraOutlined"
64
- }), /* @__PURE__ */ g("span", {
65
- className: "uy:sr-only",
66
- id: "profile-picture-change-desc",
67
- children: s || /* @__PURE__ */ g(v, {
68
- id: "unity:component:app-menu:footer:profile-button:avatar:change-description",
69
- defaultMessage: "Press enter to change profile picture"
70
- })
71
- })]
72
- })]
73
- });
74
- }, S = ({ asMenuHeader: e = !1, avatar: n, avatarPair: r, badgeLabel: i, description: a, menuTriggerDescription: o, title: s, uploadAvatarCallback: c, uploadAvatarLabel: u, uploadAvatarDescription: d }) => /* @__PURE__ */ _("div", {
75
- className: "uy:min-w-[240px] uy:w-full uy:flex uy:items-center",
76
- children: [
77
- /* @__PURE__ */ g("div", {
78
- className: "uy:mr-150 uy:flex uy:items-center",
79
- children: c ? /* @__PURE__ */ g(x, {
80
- avatar: n,
81
- avatarPair: r,
82
- title: s,
83
- uploadAvatarLabel: u,
84
- uploadAvatarDescription: d,
85
- uploadAvatarCallback: c
86
- }) : /* @__PURE__ */ g(b, {
87
- avatar: n,
88
- avatarPair: r,
89
- title: s,
90
- isPairAvatarVisible: !0
91
- })
92
- }),
93
- /* @__PURE__ */ _("div", {
94
- className: "uy:flex uy:flex-col uy:text-left uy:leading-[1.25] uy:min-w-[50%] uy:flex-grow",
95
- children: [
96
- /* @__PURE__ */ g("span", {
97
- id: "profile-button-label",
98
- className: "uy:typography-body-strong uy:text-content-neutral uy:text-wrap",
99
- "data-dd-privacy": "mask",
100
- children: s
101
- }),
102
- /* @__PURE__ */ g("span", {
103
- className: "uy:typography-body-small uy:text-content-neutral-low",
104
- "data-dd-privacy": "allow",
105
- children: a
106
- }),
107
- !e && /* @__PURE__ */ g("span", {
108
- id: "profile-button-description",
109
- className: "uy:sr-only",
110
- children: o || /* @__PURE__ */ g(v, {
111
- id: "unity:component:app-menu:footer:profile-button:description",
112
- defaultMessage: "Press this button to open the profile menu."
113
- })
114
- })
115
- ]
116
- }),
117
- /* @__PURE__ */ g("div", {
118
- className: "uy:p-100",
119
- children: e ? /* @__PURE__ */ g(l, {
120
- className: "uy:capitalize",
121
- variant: "neutral",
122
- children: i
123
- }) : /* @__PURE__ */ g(t, {
124
- src: "CaretUpDownOutlined",
125
- alt: "open",
126
- size: 20,
127
- color: "content.neutral.low"
128
- })
129
- })
130
- ]
131
- }), C = ({ avatar: t, avatarPair: o, badgeLabel: s, children: c, computeSlot: l, description: d, title: f, menuTriggerDescription: h, uploadAvatarCallback: v, uploadAvatarLabel: y, uploadAvatarDescription: b, updateNotificationSlot: x }) => {
132
- let { isMobileMenuOpen: C } = a(), [w, T] = m(!1), E = p(null);
133
- return /* @__PURE__ */ _("aside", {
6
+ var o = ({ children: o, computeSlot: s, isProfileMenuButtonVisibleOnDesktop: c = !0, updateNotificationSlot: l, ...u }) => {
7
+ let { isMobileMenuOpen: d } = n(), f = t();
8
+ return /* @__PURE__ */ a("aside", {
134
9
  className: "uy:shrink-0 uy:bg-canvas uy:md:mt-auto uy:md:bg-[transparent] uy:data-[mobile-open=false]:hidden uy:md:data-[mobile-open=false]:block uy:data-[mobile-open=true]:block",
135
- "data-mobile-open": C,
10
+ "data-mobile-open": d,
136
11
  id: "app-menu-profile-button",
137
12
  children: [
13
+ s,
138
14
  l,
139
- x,
140
- /* @__PURE__ */ _(n, {
141
- isOpen: w,
142
- onOpenChange: T,
143
- placement: "top left",
144
- triggerRef: E,
145
- children: [/* @__PURE__ */ g(i, {
146
- asChild: !0,
147
- children: /* @__PURE__ */ g(e, {
148
- ref: E,
149
- className: "uy:transition-colors uy:rounded-75 uy:px-150 uy:py-100 uy:w-full uy:theme-legacy:not-aria-disabled:hover:bg-surface-neutral-low-hover uy:theme-rebrand:not-aria-disabled:hover:bg-surface-neutral-lowest-hover uy:theme-legacy:not-aria-disabled:active:bg-surface-neutral-low-active uy:theme-rebrand:not-aria-disabled:active:bg-surface-neutral-lowest-active uy:theme-legacy:not-aria-disabled:data-[pressed=true]:bg-surface-neutral-low-pressed uy:theme-rebrand:not-aria-disabled:data-[pressed=true]:bg-surface-neutral-lowest-pressed uy:not-aria-disabled:focus-visible:outline-none uy:not-aria-disabled:focus-visible:ring-2 uy:not-aria-disabled:focus-visible:ring-utility-focus-ring uy:not-aria-disabled:focus-visible:ring-offset-2",
150
- "aria-labelledby": "profile-button-label",
151
- "aria-describedby": "profile-button-description",
152
- onPress: () => {
153
- T(!0);
154
- },
155
- children: /* @__PURE__ */ g(S, {
156
- avatar: t,
157
- avatarPair: o,
158
- badgeLabel: s,
159
- description: d,
160
- menuTriggerDescription: h,
161
- title: f,
162
- uploadAvatarCallback: v,
163
- uploadAvatarLabel: y,
164
- uploadAvatarDescription: b
165
- })
166
- })
167
- }), /* @__PURE__ */ _(r, {
168
- width: 312,
169
- children: [/* @__PURE__ */ g(u, {
170
- className: "uy:rounded-75",
171
- children: /* @__PURE__ */ g(S, {
172
- asMenuHeader: !0,
173
- avatar: t,
174
- avatarPair: o,
175
- badgeLabel: s,
176
- description: d,
177
- menuTriggerDescription: h,
178
- title: f,
179
- uploadAvatarCallback: v,
180
- uploadAvatarLabel: y,
181
- uploadAvatarDescription: b
182
- })
183
- }), c]
184
- })]
15
+ (c || !e(f)) && /* @__PURE__ */ i(r, {
16
+ ...u,
17
+ variant: "large",
18
+ children: o
185
19
  })
186
20
  ]
187
21
  });
188
22
  };
189
23
  //#endregion
190
- export { C as AppMenuFooter };
24
+ export { o as AppMenuFooter };
@@ -0,0 +1,25 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { MenuTriggerProps } from 'react-aria-components/Menu';
3
+ import { PopoverProps } from 'react-aria-components/Popover';
4
+ import { AvatarPairProps } from '../avatar/parts/AvatarPair.js';
5
+ export type AppProfileMenuButtonProps = {
6
+ avatar?: string;
7
+ avatarPair?: ReactElement<AvatarPairProps>;
8
+ title?: string;
9
+ description?: ReactNode;
10
+ badgeLabel?: string;
11
+ children?: ReactNode;
12
+ /** Use this to provide custom screen-reader context for the menu trigger. */
13
+ menuTriggerDescription?: string;
14
+ uploadAvatarCallback?: () => void;
15
+ /** Defaults to "Press enter to change profile picture". */
16
+ uploadAvatarDescription?: string;
17
+ /** Defaults to "Change profile picture". */
18
+ uploadAvatarLabel?: string;
19
+ /** Trigger treatment for application-shell surfaces. */
20
+ variant?: 'small' | 'large';
21
+ /** Defaults to square to preserve AppMenuFooter compatibility. */
22
+ avatarVariant?: 'circle' | 'square';
23
+ placement?: PopoverProps['placement'];
24
+ } & Pick<MenuTriggerProps, 'defaultOpen' | 'isOpen' | 'onOpenChange'>;
25
+ export declare const AppProfileMenuButton: ({ avatar, avatarPair, avatarVariant, badgeLabel, children, defaultOpen, description, isOpen, menuTriggerDescription, onOpenChange, placement, title, uploadAvatarCallback, uploadAvatarDescription, uploadAvatarLabel, variant, }: AppProfileMenuButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,70 @@
1
+ import { Actionable as e } from "../actionable/Actionable.js";
2
+ import { Menu as t } from "../menu/Menu.js";
3
+ import { MenuContent as n } from "../menu/parts/MenuContent.js";
4
+ import { MenuTrigger as r } from "../menu/parts/MenuTrigger.js";
5
+ import { MenuHeader as i } from "../menu/parts/MenuHeader.js";
6
+ import { AppProfileMenuHeader as a } from "./parts/AppProfileMenuHeader.js";
7
+ import { useId as o, useRef as s } from "react";
8
+ import { uyTv as c } from "@payfit/unity-themes";
9
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
10
+ //#region src/components/app-profile-menu-button/AppProfileMenuButton.tsx
11
+ var d = c({
12
+ base: [
13
+ "uy:transition-colors uy:rounded-75",
14
+ "uy:theme-legacy:data-[hovered=true]:bg-surface-neutral-low-hover uy:theme-legacy:hover:bg-surface-neutral-low-hover",
15
+ "uy:theme-rebrand:data-[hovered=true]:bg-surface-neutral-lowest-hover uy:theme-rebrand:hover:bg-surface-neutral-lowest-hover",
16
+ "uy:theme-legacy:data-[pressed=true]:bg-surface-neutral-low-pressed uy:theme-legacy:active:bg-surface-neutral-low-active",
17
+ "uy:theme-rebrand:data-[pressed=true]:bg-surface-neutral-lowest-pressed uy:theme-rebrand:active:bg-surface-neutral-lowest-active",
18
+ "uy:data-[focus-visible=true]:outline-none uy:data-[focus-visible=true]:ring-2 uy:data-[focus-visible=true]:ring-utility-focus-ring uy:data-[focus-visible=true]:ring-offset-2",
19
+ "uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-utility-focus-ring uy:focus-visible:ring-offset-2"
20
+ ],
21
+ variants: { variant: {
22
+ large: "uy:w-full uy:px-150 uy:py-100",
23
+ small: "uy:pr-0 uy:pl-100 uy:py-25"
24
+ } }
25
+ }), f = ({ avatar: c, avatarPair: f, avatarVariant: p = "square", badgeLabel: m, children: h, defaultOpen: g, description: _, isOpen: v, menuTriggerDescription: y, onOpenChange: b, placement: x, title: S, uploadAvatarCallback: C, uploadAvatarDescription: w, uploadAvatarLabel: T, variant: E = "large" }) => {
26
+ let D = s(null), O = o(), k = o(), A = {
27
+ avatar: c,
28
+ avatarPair: f,
29
+ avatarSize: E === "small" ? "md" : "lg",
30
+ avatarVariant: p,
31
+ badgeLabel: m,
32
+ description: _,
33
+ labelId: O,
34
+ menuTriggerDescription: y,
35
+ title: S,
36
+ triggerDescriptionId: k,
37
+ triggerVariant: E,
38
+ uploadAvatarCallback: C,
39
+ uploadAvatarDescription: w,
40
+ uploadAvatarLabel: T
41
+ };
42
+ return /* @__PURE__ */ u(t, {
43
+ defaultOpen: g,
44
+ isOpen: v,
45
+ onOpenChange: b,
46
+ placement: x ?? (E === "small" ? "bottom right" : "top left"),
47
+ triggerRef: D,
48
+ children: [/* @__PURE__ */ l(r, {
49
+ asChild: !0,
50
+ children: /* @__PURE__ */ l(e, {
51
+ ref: D,
52
+ "aria-describedby": k,
53
+ "aria-labelledby": O,
54
+ className: d({ variant: E }),
55
+ children: /* @__PURE__ */ l(a, { ...A })
56
+ })
57
+ }), /* @__PURE__ */ u(n, {
58
+ width: 312,
59
+ children: [/* @__PURE__ */ l(i, {
60
+ className: "uy:rounded-75",
61
+ children: /* @__PURE__ */ l(a, {
62
+ ...A,
63
+ asMenuHeader: !0
64
+ })
65
+ }), h]
66
+ })]
67
+ });
68
+ };
69
+ //#endregion
70
+ export { f as AppProfileMenuButton };
@@ -0,0 +1,18 @@
1
+ import { ReactElement } from 'react';
2
+ import { AvatarPairProps } from '../../avatar/parts/AvatarPair.js';
3
+ export type AppProfileAvatarProps = {
4
+ avatar?: string;
5
+ avatarPair?: ReactElement<AvatarPairProps>;
6
+ avatarSize: 'md' | 'lg';
7
+ avatarVariant: 'circle' | 'square';
8
+ isPairAvatarVisible: boolean;
9
+ labelId: string;
10
+ title?: string;
11
+ };
12
+ export declare const AppProfileAvatar: ({ avatar, avatarPair, avatarSize, avatarVariant, isPairAvatarVisible, labelId, title, }: AppProfileAvatarProps) => import("react/jsx-runtime").JSX.Element;
13
+ export type InteractiveAppProfileAvatarProps = Omit<AppProfileAvatarProps, 'isPairAvatarVisible'> & {
14
+ uploadAvatarCallback: () => void;
15
+ uploadAvatarDescription?: string;
16
+ uploadAvatarLabel?: string;
17
+ };
18
+ export declare const InteractiveAppProfileAvatar: ({ avatar, avatarPair, avatarSize, avatarVariant, labelId, title, uploadAvatarCallback, uploadAvatarDescription, uploadAvatarLabel, }: InteractiveAppProfileAvatarProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,79 @@
1
+ import { Actionable as e } from "../../actionable/Actionable.js";
2
+ import { Icon as t } from "../../icon/Icon.js";
3
+ import { Avatar as n } from "../../avatar/Avatar.js";
4
+ import { AvatarFallback as r } from "../../avatar/parts/AvatarFallback.js";
5
+ import { AvatarImage as i } from "../../avatar/parts/AvatarImage.js";
6
+ import { cloneElement as a, isValidElement as o, useId as s, useState as c } from "react";
7
+ import { uyMerge as l } from "@payfit/unity-themes";
8
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
9
+ import { FormattedMessage as f, useIntl as p } from "react-intl";
10
+ //#region src/components/app-profile-menu-button/parts/AppProfileAvatar.tsx
11
+ var m = ({ avatar: e, avatarPair: t, avatarSize: s, avatarVariant: c, isPairAvatarVisible: l, labelId: f, title: p }) => /* @__PURE__ */ d(n, {
12
+ "aria-labelledby": f,
13
+ size: s,
14
+ variant: c,
15
+ children: [
16
+ /* @__PURE__ */ u(i, {
17
+ src: e,
18
+ alt: p ?? ""
19
+ }),
20
+ /* @__PURE__ */ u(r, {
21
+ variant: "initials",
22
+ delayMs: 100,
23
+ children: p
24
+ }),
25
+ t && o(t) && a(t, { isHidden: !l })
26
+ ]
27
+ }), h = ({ avatar: n, avatarPair: r, avatarSize: i, avatarVariant: a, labelId: o, title: h, uploadAvatarCallback: g, uploadAvatarDescription: _, uploadAvatarLabel: v }) => {
28
+ let [y, b] = c(!1), [x, S] = c(!1), C = s(), w = p(), T = !(y || x);
29
+ return /* @__PURE__ */ d(e, {
30
+ "aria-describedby": C,
31
+ "aria-label": v ?? w.formatMessage({
32
+ id: "unity:component:app-menu:footer:profile-button:avatar:change",
33
+ defaultMessage: "Change profile picture"
34
+ }),
35
+ className: l("uy:group/avatar uy:cursor-pointer uy:relative uy:leading-[0] uy:rounded-75 uy:focus-visible:outline-none uy:focus-visible:ring-2 uy:focus-visible:ring-utility-focus-ring uy:focus-visible:ring-offset-2"),
36
+ onBlur: () => {
37
+ S(!1);
38
+ },
39
+ onFocus: () => {
40
+ S(!0);
41
+ },
42
+ onHoverEnd: () => {
43
+ b(!1);
44
+ },
45
+ onHoverStart: () => {
46
+ b(!0);
47
+ },
48
+ onPress: g,
49
+ children: [/* @__PURE__ */ u(m, {
50
+ avatar: n,
51
+ avatarPair: r,
52
+ avatarSize: i,
53
+ avatarVariant: a,
54
+ isPairAvatarVisible: T,
55
+ labelId: o,
56
+ title: h
57
+ }), /* @__PURE__ */ d("div", {
58
+ className: "uy:flex uy:pointer-events-none uy:opacity-0 uy:group-hover/avatar:opacity-90 uy:group-data-[focus-visible=true]/avatar:opacity-90 uy:group-focus-visible/avatar:opacity-90 uy:bg-utility-backdrop uy:rounded-75 uy:absolute uy:inset-0 uy:transition-all uy:duration-200 uy:items-center uy:justify-center",
59
+ children: [/* @__PURE__ */ u(t, {
60
+ alt: w.formatMessage({
61
+ id: "unity:component:app-menu:footer:profile-button:avatar:camera",
62
+ defaultMessage: "Camera"
63
+ }),
64
+ color: "content.inverted",
65
+ size: 24,
66
+ src: "CameraOutlined"
67
+ }), /* @__PURE__ */ u("span", {
68
+ className: "uy:sr-only",
69
+ id: C,
70
+ children: _ ?? /* @__PURE__ */ u(f, {
71
+ id: "unity:component:app-menu:footer:profile-button:avatar:change-description",
72
+ defaultMessage: "Press enter to change profile picture"
73
+ })
74
+ })]
75
+ })]
76
+ });
77
+ };
78
+ //#endregion
79
+ export { m as AppProfileAvatar, h as InteractiveAppProfileAvatar };
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { AppProfileAvatarProps } from './AppProfileAvatar.js';
3
+ export type AppProfileMenuHeaderProps = Pick<AppProfileAvatarProps, 'avatar' | 'avatarPair' | 'avatarSize' | 'avatarVariant' | 'labelId' | 'title'> & {
4
+ asMenuHeader?: boolean;
5
+ badgeLabel?: string;
6
+ description?: ReactNode;
7
+ menuTriggerDescription?: string;
8
+ triggerDescriptionId: string;
9
+ triggerVariant: 'small' | 'large';
10
+ uploadAvatarCallback?: () => void;
11
+ uploadAvatarDescription?: string;
12
+ uploadAvatarLabel?: string;
13
+ };
14
+ export declare const AppProfileMenuHeader: ({ asMenuHeader, avatar, avatarPair, avatarSize, avatarVariant, badgeLabel, description, labelId, menuTriggerDescription, title, triggerDescriptionId, triggerVariant, uploadAvatarCallback, uploadAvatarDescription, uploadAvatarLabel, }: AppProfileMenuHeaderProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,88 @@
1
+ import { Icon as e } from "../../icon/Icon.js";
2
+ import { Text as t } from "../../text/Text.js";
3
+ import { Badge as n } from "../../badge/Badge.js";
4
+ import { AppProfileAvatar as r, InteractiveAppProfileAvatar as i } from "./AppProfileAvatar.js";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ import { useIntl as s } from "react-intl";
7
+ //#region src/components/app-profile-menu-button/parts/AppProfileMenuHeader.tsx
8
+ var c = ({ asMenuHeader: c = !1, avatar: l, avatarPair: u, avatarSize: d, avatarVariant: f, badgeLabel: p, description: m, labelId: h, menuTriggerDescription: g, title: _, triggerDescriptionId: v, triggerVariant: y, uploadAvatarCallback: b, uploadAvatarDescription: x, uploadAvatarLabel: S }) => {
9
+ let C = s(), w = g ?? C.formatMessage({
10
+ id: "unity:component:app-menu:footer:profile-button:description",
11
+ defaultMessage: "Press this button to open the profile menu."
12
+ });
13
+ return /* @__PURE__ */ o("div", {
14
+ className: "uy:w-full uy:flex uy:items-center",
15
+ "data-unity-slot": "profile-summary",
16
+ children: [
17
+ /* @__PURE__ */ a("div", {
18
+ className: "uy:mr-150 uy:flex uy:items-center",
19
+ "data-unity-slot": "avatar",
20
+ children: b ? /* @__PURE__ */ a(i, {
21
+ avatar: l,
22
+ avatarPair: u,
23
+ avatarSize: d,
24
+ avatarVariant: f,
25
+ labelId: h,
26
+ title: _,
27
+ uploadAvatarCallback: b,
28
+ uploadAvatarDescription: x,
29
+ uploadAvatarLabel: S
30
+ }) : /* @__PURE__ */ a(r, {
31
+ avatar: l,
32
+ avatarPair: u,
33
+ avatarSize: d,
34
+ avatarVariant: f,
35
+ isPairAvatarVisible: !0,
36
+ labelId: h,
37
+ title: _
38
+ })
39
+ }),
40
+ /* @__PURE__ */ o("div", {
41
+ className: "uy:flex uy:flex-col uy:text-left uy:leading-[1.25] uy:min-w-0 uy:flex-grow",
42
+ "data-unity-slot": "profile-details",
43
+ children: [
44
+ /* @__PURE__ */ a(t, {
45
+ asElement: "span",
46
+ className: "uy:w-full",
47
+ color: "content.neutral",
48
+ "data-dd-privacy": "mask",
49
+ id: c ? void 0 : h,
50
+ lineClamp: 1,
51
+ variant: d === "md" ? "bodySmallStrong" : "bodyStrong",
52
+ children: _
53
+ }),
54
+ /* @__PURE__ */ a(t, {
55
+ asElement: "span",
56
+ className: "uy:w-full",
57
+ color: "content.neutral.low",
58
+ "data-dd-privacy": "allow",
59
+ lineClamp: 1,
60
+ variant: "bodySmall",
61
+ children: m
62
+ }),
63
+ !c && /* @__PURE__ */ a("span", {
64
+ id: v,
65
+ className: "uy:sr-only",
66
+ children: w
67
+ })
68
+ ]
69
+ }),
70
+ /* @__PURE__ */ a("div", {
71
+ className: "uy:p-100",
72
+ "data-unity-slot": "disclosure",
73
+ children: c ? p && /* @__PURE__ */ a(n, {
74
+ className: "uy:capitalize",
75
+ variant: "neutral",
76
+ children: p
77
+ }) : /* @__PURE__ */ a(e, {
78
+ src: y === "small" ? "CaretDownOutlined" : "CaretUpDownOutlined",
79
+ alt: w,
80
+ size: 20,
81
+ color: "content.neutral.low"
82
+ })
83
+ })
84
+ ]
85
+ });
86
+ };
87
+ //#endregion
88
+ export { c as AppProfileMenuHeader };