@payfit/unity-components 2.19.3 → 2.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/esm/components/action-bar/ActionBar.d.ts +61 -120
  2. package/dist/esm/components/action-bar/ActionBar.js +48 -151
  3. package/dist/esm/components/action-bar/ActionBar.types.d.ts +116 -0
  4. package/dist/esm/components/action-bar/ActionBar.variants.d.ts +31 -0
  5. package/dist/esm/components/action-bar/ActionBar.variants.js +26 -0
  6. package/dist/esm/components/action-bar/hooks/use-action-bar-state.d.ts +19 -0
  7. package/dist/esm/components/action-bar/hooks/use-action-bar-state.js +22 -0
  8. package/dist/esm/components/action-bar/parts/ActionBarButton.d.ts +58 -0
  9. package/dist/esm/components/action-bar/parts/ActionBarButton.js +35 -0
  10. package/dist/esm/components/action-bar/parts/ActionBarIconButton.d.ts +61 -0
  11. package/dist/esm/components/action-bar/parts/ActionBarIconButton.js +41 -0
  12. package/dist/esm/components/action-bar/parts/ActionBarOverflowMenu.d.ts +10 -0
  13. package/dist/esm/components/action-bar/parts/ActionBarOverflowMenu.js +45 -0
  14. package/dist/esm/components/action-bar/parts/ActionBarPrefixArea.d.ts +11 -0
  15. package/dist/esm/components/action-bar/parts/ActionBarPrefixArea.js +35 -0
  16. package/dist/esm/components/action-bar/parts/ActionBarRoot.d.ts +23 -0
  17. package/dist/esm/components/action-bar/parts/ActionBarRoot.js +23 -13
  18. package/dist/esm/components/action-bar/utils/action-bar-helpers.d.ts +14 -0
  19. package/dist/esm/components/action-bar/utils/action-bar-helpers.js +29 -0
  20. package/dist/esm/components/data-table/parts/DataTableBulkActions.d.ts +16 -6
  21. package/dist/esm/components/data-table/parts/DataTableBulkActions.js +122 -37
  22. package/dist/esm/components/icon-button/IconButton.d.ts +4 -0
  23. package/dist/esm/components/icon-button/IconButton.js +40 -31
  24. package/dist/esm/components/menu/parts/RawMenuItem.d.ts +2 -1
  25. package/dist/esm/components/menu/parts/RawMenuItem.js +14 -12
  26. package/dist/esm/index.d.ts +2 -1
  27. package/dist/esm/index.js +545 -543
  28. package/i18n/en-GB.json +2 -0
  29. package/i18n/es-ES.json +2 -0
  30. package/i18n/fr-FR.json +2 -0
  31. package/package.json +17 -17
  32. package/dist/esm/components/action-bar/parts/ActionBarAction.d.ts +0 -44
  33. package/dist/esm/components/action-bar/parts/ActionBarAction.js +0 -45
@@ -0,0 +1,58 @@
1
+ import { ButtonProps } from '../../button/Button.js';
2
+ export type ActionBarButtonProps = Omit<ButtonProps, 'variant' | 'size' | 'color' | 'type'> & {
3
+ /**
4
+ * The visual variant of the button.
5
+ * @default 'secondary'
6
+ */
7
+ variant?: 'primary' | 'secondary';
8
+ };
9
+ /**
10
+ * @deprecated Use ActionBarButtonProps instead
11
+ */
12
+ export type ActionBarActionProps = ActionBarButtonProps;
13
+ /**
14
+ * The ActionBarButton component represents an individual button action within an ActionBar.
15
+ * It renders as a button with appropriate styling for the inverted ActionBar context.
16
+ * @param {ActionBarButtonProps} props - Props for the button. Identical to the `Button` component props.
17
+ * @example
18
+ * ```tsx
19
+ * import { ActionBarButton } from '@payfit/unity-components'
20
+ *
21
+ * function Example() {
22
+ * return (
23
+ * <ActionBarButton
24
+ * variant="primary"
25
+ * onPress={() => console.log('Button clicked')}
26
+ * prefixIcon="TrashOutlined"
27
+ * >
28
+ * Delete Items
29
+ * </ActionBarButton>
30
+ * )
31
+ * }
32
+ * ```
33
+ * @remarks
34
+ * - Automatically uses inverted button variants to work on dark ActionBar background
35
+ * - Secondary buttons use 'ghost-inverted' button variant
36
+ * - Primary buttons use 'inverted-primary' button variant
37
+ * @see {@link ActionBarButtonProps} for all available props
38
+ * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/action-bar GitHub}
39
+ * @see Design specs {@link https://www.figma.com/design/poaMyU7abAgL9VRhx4ygyy/Unity-DS-%3E-Components-Library Figma}
40
+ */
41
+ declare const ActionBarButton: import('react').ForwardRefExoticComponent<Omit<ButtonProps, "size" | "color" | "type" | "variant"> & {
42
+ /**
43
+ * The visual variant of the button.
44
+ * @default 'secondary'
45
+ */
46
+ variant?: "primary" | "secondary";
47
+ } & import('react').RefAttributes<HTMLButtonElement>>;
48
+ /**
49
+ * @deprecated Use ActionBarButton instead
50
+ */
51
+ declare const ActionBarAction: import('react').ForwardRefExoticComponent<Omit<ButtonProps, "size" | "color" | "type" | "variant"> & {
52
+ /**
53
+ * The visual variant of the button.
54
+ * @default 'secondary'
55
+ */
56
+ variant?: "primary" | "secondary";
57
+ } & import('react').RefAttributes<HTMLButtonElement>>;
58
+ export { ActionBarButton, ActionBarAction };
@@ -0,0 +1,35 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { forwardRef as s } from "react";
3
+ import { Button as m } from "../../button/Button.js";
4
+ const o = s(
5
+ ({ variant: r = "secondary", children: n, onPress: a, ...i }, c) => {
6
+ const t = {
7
+ primary: {
8
+ variant: "primary",
9
+ color: "inverted"
10
+ },
11
+ secondary: {
12
+ variant: "ghost",
13
+ color: "inverted"
14
+ }
15
+ }[r];
16
+ return /* @__PURE__ */ e(
17
+ m,
18
+ {
19
+ ref: c,
20
+ variant: t.variant,
21
+ color: t.color,
22
+ onPress: a,
23
+ size: "default",
24
+ ...i,
25
+ children: n
26
+ }
27
+ );
28
+ }
29
+ );
30
+ o.displayName = "ActionBarButton";
31
+ const l = o;
32
+ export {
33
+ l as ActionBarAction,
34
+ o as ActionBarButton
35
+ };
@@ -0,0 +1,61 @@
1
+ import { UnityIcon } from '@payfit/unity-icons';
2
+ import { IconButtonProps } from '../../icon-button/IconButton.js';
3
+ export interface ActionBarIconButtonProps {
4
+ /**
5
+ * The icon to display inside the button.
6
+ */
7
+ icon: UnityIcon;
8
+ /**
9
+ * The label for accessibility. This is used as the aria-label and shown in a tooltip.
10
+ */
11
+ label: string;
12
+ /**
13
+ * The visual variant of the button.
14
+ * @default 'secondary'
15
+ */
16
+ variant?: 'primary' | 'secondary';
17
+ /**
18
+ * Callback fired when the button is pressed.
19
+ */
20
+ onPress?: IconButtonProps['onPress'];
21
+ /**
22
+ * Whether the button is disabled.
23
+ * @default false
24
+ */
25
+ isDisabled?: boolean;
26
+ /**
27
+ * Whether the button is in a loading state.
28
+ * @default false
29
+ */
30
+ isLoading?: boolean;
31
+ }
32
+ /**
33
+ * The ActionBarIconButton component represents an icon-only button action within an ActionBar.
34
+ * It renders as an icon button with appropriate styling for the inverted ActionBar context.
35
+ * @param {ActionBarIconButtonProps} props - Props for the icon button.
36
+ * @example
37
+ * ```tsx
38
+ * import { ActionBarIconButton } from '@payfit/unity-components'
39
+ *
40
+ * function Example() {
41
+ * return (
42
+ * <ActionBarIconButton
43
+ * icon="TrashOutlined"
44
+ * label="Delete items"
45
+ * variant="primary"
46
+ * onPress={() => console.log('Delete clicked')}
47
+ * />
48
+ * )
49
+ * }
50
+ * ```
51
+ * @remarks
52
+ * - Automatically uses inverted icon button variants to work on dark ActionBar background
53
+ * - The label prop is required for accessibility and is shown in a tooltip on hover
54
+ * - Secondary icon buttons are hidden on mobile viewports (overflow menu handles them)
55
+ * - Primary icon buttons remain visible on all screen sizes
56
+ * @see {@link ActionBarIconButtonProps} for all available props
57
+ * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/action-bar GitHub}
58
+ * @see Design specs {@link https://www.figma.com/design/poaMyU7abAgL9VRhx4ygyy/Unity-DS-%3E-Components-Library Figma}
59
+ */
60
+ declare const ActionBarIconButton: import('react').ForwardRefExoticComponent<ActionBarIconButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
61
+ export { ActionBarIconButton };
@@ -0,0 +1,41 @@
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import { forwardRef as m } from "react";
3
+ import { IconButton as f } from "../../icon-button/IconButton.js";
4
+ const l = m(
5
+ ({
6
+ icon: r,
7
+ label: t,
8
+ variant: n = "secondary",
9
+ onPress: a,
10
+ isDisabled: i = !1,
11
+ isLoading: c = !1
12
+ }, e) => {
13
+ const o = {
14
+ primary: {
15
+ variant: "primary",
16
+ color: "inverted"
17
+ },
18
+ secondary: {
19
+ variant: "ghost",
20
+ color: "inverted"
21
+ }
22
+ }[n];
23
+ return /* @__PURE__ */ s(
24
+ f,
25
+ {
26
+ ref: e,
27
+ icon: r,
28
+ label: t,
29
+ variant: o.variant,
30
+ color: o.color,
31
+ onPress: a,
32
+ isDisabled: i,
33
+ isLoading: c
34
+ }
35
+ );
36
+ }
37
+ );
38
+ l.displayName = "ActionBarIconButton";
39
+ export {
40
+ l as ActionBarIconButton
41
+ };
@@ -0,0 +1,10 @@
1
+ import { ActionBarButtonActionItem } from '../ActionBar.types.js';
2
+ interface ActionBarOverflowMenuProps {
3
+ actions: ActionBarButtonActionItem[];
4
+ }
5
+ /**
6
+ * Mobile overflow menu for non-primary actions
7
+ * @internal
8
+ */
9
+ export declare const ActionBarOverflowMenu: ({ actions, }: ActionBarOverflowMenuProps) => import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,45 @@
1
+ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
+ import { useIntl as s } from "react-intl";
3
+ import { IconButton as m } from "../../icon-button/IconButton.js";
4
+ import { Icon as c } from "../../icon/Icon.js";
5
+ import { Menu as a } from "../../menu/Menu.js";
6
+ import { MenuContent as l } from "../../menu/parts/MenuContent.js";
7
+ import { MenuTrigger as d } from "../../menu/parts/MenuTrigger.js";
8
+ import { RawMenuItem as u } from "../../menu/parts/RawMenuItem.js";
9
+ const v = ({
10
+ actions: i
11
+ }) => {
12
+ const n = s();
13
+ return /* @__PURE__ */ e("div", { className: "uy:block uy:md:hidden", children: /* @__PURE__ */ t(a, { children: [
14
+ /* @__PURE__ */ e(d, { asChild: !0, children: /* @__PURE__ */ e(
15
+ m,
16
+ {
17
+ icon: "DotsThreeOutlined",
18
+ label: n.formatMessage({
19
+ id: "unity:component:action-bar:actions:more-actions",
20
+ defaultMessage: "More actions"
21
+ }),
22
+ variant: "ghost",
23
+ color: "inverted"
24
+ }
25
+ ) }),
26
+ /* @__PURE__ */ e(l, { children: i.map((r) => {
27
+ const o = r.meta;
28
+ return /* @__PURE__ */ e(
29
+ u,
30
+ {
31
+ isDisabled: o?.isDisabled,
32
+ onAction: () => {
33
+ o?.onPress?.({});
34
+ },
35
+ prefix: o?.prefixIcon ? /* @__PURE__ */ e(c, { src: o.prefixIcon, size: 20 }) : void 0,
36
+ children: r.label
37
+ },
38
+ r.id
39
+ );
40
+ }) })
41
+ ] }) });
42
+ };
43
+ export {
44
+ v as ActionBarOverflowMenu
45
+ };
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+ interface ActionBarPrefixAreaProps {
3
+ children: ReactNode;
4
+ ariaKeyshortcuts?: string;
5
+ }
6
+ /**
7
+ * Prefix content area with optional keyboard shortcut announcement
8
+ * @internal
9
+ */
10
+ export declare const ActionBarPrefixArea: ({ children, ariaKeyshortcuts, }: ActionBarPrefixAreaProps) => import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,35 @@
1
+ import { jsxs as a, jsx as s } from "react/jsx-runtime";
2
+ import { Group as n } from "react-aria-components";
3
+ import { useIntl as i } from "react-intl";
4
+ import { actionBar as c } from "../ActionBar.variants.js";
5
+ const p = ({
6
+ children: r,
7
+ ariaKeyshortcuts: o
8
+ }) => {
9
+ const t = i(), { prefixArea: e } = c();
10
+ return /* @__PURE__ */ a(
11
+ n,
12
+ {
13
+ className: e(),
14
+ "aria-label": t.formatMessage({
15
+ id: "unity:component:action-bar:group:label",
16
+ defaultMessage: "Toolbar information"
17
+ }),
18
+ children: [
19
+ r,
20
+ o && /* @__PURE__ */ s("span", { className: "uy:sr-only", children: t.formatMessage(
21
+ {
22
+ id: "unity:component:action-bar:key-shortcuts-text",
23
+ defaultMessage: "Use {keyShortcuts} to focus the action bar"
24
+ },
25
+ {
26
+ keyShortcuts: o
27
+ }
28
+ ) })
29
+ ]
30
+ }
31
+ );
32
+ };
33
+ export {
34
+ p as ActionBarPrefixArea
35
+ };
@@ -4,21 +4,44 @@ export declare const actionBarRoot: import('tailwind-variants').TVReturnType<{
4
4
  true: string[];
5
5
  false: string[];
6
6
  };
7
+ position: {
8
+ absolute: string[];
9
+ fixed: string[];
10
+ };
7
11
  }, undefined, string[], {
8
12
  isVisible: {
9
13
  true: string[];
10
14
  false: string[];
11
15
  };
16
+ position: {
17
+ absolute: string[];
18
+ fixed: string[];
19
+ };
12
20
  }, undefined, import('tailwind-variants').TVReturnType<{
13
21
  isVisible: {
14
22
  true: string[];
15
23
  false: string[];
16
24
  };
25
+ position: {
26
+ absolute: string[];
27
+ fixed: string[];
28
+ };
17
29
  }, undefined, string[], unknown, unknown, undefined>>;
18
30
  export interface ActionBarRootProps extends PropsWithChildren {
19
31
  /** Offset from the bottom of the table. It uses Unity's standard spacing tokens. */
20
32
  offsetBottom?: '$25' | '$50' | '$75' | '$100' | '$125' | '$200' | '$300' | '$400' | '$500' | '$600' | '$800' | '$1000' | number;
33
+ /**
34
+ * Control the visibility of the Action bar root, which will in turn hide and show the action bar
35
+ * @default false
36
+ */
21
37
  isVisible?: boolean;
38
+ /**
39
+ * The positioning mode to use:
40
+ * - `absolute` will place the root at the bottom-center of the closest parent with `position: relative`
41
+ * - `fixed` will place the root at the bottom-center of the viewport
42
+ * @default "absolute"
43
+ */
44
+ position?: 'absolute' | 'fixed';
22
45
  }
23
46
  /**
24
47
  * The ActionBarRoot component provides positioning context for ActionBar components.
@@ -1,9 +1,9 @@
1
- import { jsx as s } from "react/jsx-runtime";
2
- import { forwardRef as i } from "react";
3
- import { uyTv as y } from "@payfit/unity-themes";
4
- const c = y({
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { forwardRef as y } from "react";
3
+ import { uyTv as c } from "@payfit/unity-themes";
4
+ const l = c({
5
5
  base: [
6
- "uy:absolute uy:left-1/2 uy:-translate-x-1/2 uy:z-10",
6
+ "uy:left-1/2 uy:-translate-x-1/2 uy:z-10",
7
7
  "uy:duration-200 uy:ease-out",
8
8
  "uy:bottom-[calc(var(--uy-spacing-200)+var(--uy-spacing-offset-bottom))]",
9
9
  "uy:starting:opacity-0"
@@ -18,19 +18,29 @@ const c = y({
18
18
  "uy:opacity-0",
19
19
  "uy:translate-y-10"
20
20
  ]
21
+ },
22
+ position: {
23
+ absolute: ["uy:absolute"],
24
+ fixed: ["uy:fixed"]
21
25
  }
22
26
  }
23
- }), p = i(
24
- ({ children: o, offsetBottom: a = 0, isVisible: t = !1, ...n }, u) => {
25
- const e = typeof a == "number" ? a : a.replace("$", ""), r = typeof a == "number" ? `calc(var(--uy-spacing)*${e})` : `var(--uy-spacing-${e})`;
26
- return /* @__PURE__ */ s(
27
+ }), p = y(
28
+ ({
29
+ children: o,
30
+ offsetBottom: a = 0,
31
+ isVisible: t = !1,
32
+ position: u = "absolute",
33
+ ...n
34
+ }, i) => {
35
+ const e = typeof a == "number" ? a : a.replace("$", ""), s = typeof a == "number" ? `calc(var(--uy-spacing)*${e})` : `var(--uy-spacing-${e})`;
36
+ return /* @__PURE__ */ r(
27
37
  "div",
28
38
  {
29
- ref: u,
30
- className: c({ isVisible: t }),
39
+ ref: i,
40
+ className: l({ isVisible: t, position: u }),
31
41
  ...n,
32
42
  style: {
33
- "--uy-spacing-offset-bottom": r
43
+ "--uy-spacing-offset-bottom": s
34
44
  },
35
45
  tabIndex: -1,
36
46
  inert: t ? void 0 : "",
@@ -42,5 +52,5 @@ const c = y({
42
52
  p.displayName = "ActionBarRoot";
43
53
  export {
44
54
  p as ActionBarRoot,
45
- c as actionBarRoot
55
+ l as actionBarRoot
46
56
  };
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ import { ActionBarActionItem, ActionBarButtonActionItem, ActionBarIconButtonActionItem } from '../ActionBar.types.js';
3
+ /**
4
+ * Helper function to check if an action is an icon-button type
5
+ */
6
+ export declare const isIconButtonAction: (action: ActionBarActionItem) => action is ActionBarIconButtonActionItem;
7
+ /**
8
+ * Extract non-primary actions from dynamic actions array for mobile overflow
9
+ */
10
+ export declare const extractMobileActionsFromArray: (actions: ActionBarActionItem[]) => ActionBarButtonActionItem[];
11
+ /**
12
+ * Extract non-primary actions from static children for mobile overflow
13
+ */
14
+ export declare const extractMobileActionsFromChildren: (children: ReactNode) => ActionBarButtonActionItem[];
@@ -0,0 +1,29 @@
1
+ import c, { isValidElement as s } from "react";
2
+ import { ActionBarButton as p } from "../parts/ActionBarButton.js";
3
+ import { ActionBarIconButton as n } from "../parts/ActionBarIconButton.js";
4
+ const u = (e) => e.filter(
5
+ (o) => o.variant !== "primary"
6
+ ), y = (e) => {
7
+ const o = [];
8
+ return c.Children.forEach(e, (t) => {
9
+ if (!s(t) || t.type !== p && t.type !== n)
10
+ return;
11
+ const r = t.props;
12
+ if (r.variant === "primary") return;
13
+ const i = t.type === n ? r.label : r.children, a = t.type === n ? r.icon : r.prefixIcon;
14
+ o.push({
15
+ //eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
16
+ id: t.key ?? r.id,
17
+ label: i,
18
+ variant: r.variant,
19
+ meta: {
20
+ onPress: r.onPress,
21
+ prefixIcon: a
22
+ }
23
+ });
24
+ }), o;
25
+ };
26
+ export {
27
+ u as extractMobileActionsFromArray,
28
+ y as extractMobileActionsFromChildren
29
+ };
@@ -1,25 +1,34 @@
1
1
  import { Table as TableType } from '@tanstack/react-table';
2
- import { ActionBarProps } from '../../action-bar/ActionBar.js';
2
+ import { ActionBarActionItem } from '../../action-bar/ActionBar.js';
3
3
  export interface DataTableBulkActionsProps<TData> {
4
4
  /** The table instance from @tanstack/react-table */
5
5
  table: TableType<TData>;
6
6
  /** Bulk actions to perform over the table, rendered in the action bar */
7
- actions: ActionBarProps['actions'];
7
+ actions: ActionBarActionItem[];
8
+ /**
9
+ * Custom function to render selection count text.
10
+ * When provided, pluralization is your responsibility.
11
+ */
12
+ renderSelectionText?: (count: number) => string;
8
13
  }
9
14
  /**
10
15
  * The DataTableBulkActions component provides contextual bulk actions when table rows are selected.
11
- * It automatically shows/hides based on row selection and provides keyboard accessibility via Alt+A (Option+A on Mac).
16
+ * It automatically shows/hides based on row selection and provides keyboard accessibility via F6.
17
+ *
18
+ * This component wraps the ActionBar and handles the selection UI (selection count + clear button)
19
+ * via the `prefixContent` prop, while accepting bulk actions to display.
12
20
  * @param {DataTableBulkActionsProps} props - The props for the DataTableBulkActions component
13
21
  * @param props.table - The table instance from `@tanstack/react-table`
14
22
  * @param props.actions - Bulk actions to perform over the table, rendered in the action bar
23
+ * @param props.renderSelectionText - Custom function to render selection count text
15
24
  * @example
16
25
  * ```tsx
17
26
  * import { DataTableRoot, DataTable, DataTableBulkActions } from '@payfit/unity-components'
18
27
  *
19
28
  * function Example() {
20
29
  * const actions = [
21
- * { id: 'delete', label: 'Delete', onPress: handleDelete },
22
- * { id: 'archive', label: 'Archive', onPress: handleArchive },
30
+ * { id: 'delete', label: 'Delete', meta: { onPress: handleDelete } },
31
+ * { id: 'archive', label: 'Archive', meta: { onPress: handleArchive } },
23
32
  * ]
24
33
  *
25
34
  * return (
@@ -45,10 +54,11 @@ export interface DataTableBulkActionsProps<TData> {
45
54
  * - The keyboard shortcut provides quick access to bulk actions for users with disabilities
46
55
  * - When triggered, focus moves to the first focusable element in the action bar (typically the first action button)
47
56
  * - The shortcut only works when rows are selected and the action bar is visible
57
+ * - The selection count and clear button are rendered automatically via `prefixContent`
48
58
  * @see {@link DataTableBulkActionsProps} for all available props
49
59
  * @see Source code in [Github](https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/data-table)
50
60
  */
51
- declare function DataTableBulkActions<TData extends object>({ table, actions, }: DataTableBulkActionsProps<TData>): import("react/jsx-runtime").JSX.Element | null;
61
+ declare function DataTableBulkActions<TData extends object>({ table, actions, renderSelectionText, }: DataTableBulkActionsProps<TData>): import("react/jsx-runtime").JSX.Element;
52
62
  declare namespace DataTableBulkActions {
53
63
  var displayName: string;
54
64
  }