@payfit/unity-components 2.19.2 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +8 -8
  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
@@ -1,138 +1,76 @@
1
- import { default as React, ReactNode } from 'react';
2
- import { ActionBarActionProps } from './parts/ActionBarAction.js';
3
- export declare const actionBar: import('tailwind-variants').TVReturnType<{
4
- [key: string]: {
5
- [key: string]: import('tailwind-merge').ClassNameValue | {
6
- base?: import('tailwind-merge').ClassNameValue;
7
- selectionArea?: import('tailwind-merge').ClassNameValue;
8
- actionArea?: import('tailwind-merge').ClassNameValue;
9
- selectionCountText?: import('tailwind-merge').ClassNameValue;
10
- };
11
- };
12
- } | {
13
- [x: string]: {
14
- [x: string]: import('tailwind-merge').ClassNameValue | {
15
- base?: import('tailwind-merge').ClassNameValue;
16
- selectionArea?: import('tailwind-merge').ClassNameValue;
17
- actionArea?: import('tailwind-merge').ClassNameValue;
18
- selectionCountText?: import('tailwind-merge').ClassNameValue;
19
- };
20
- };
21
- } | {}, {
22
- base: string[];
23
- selectionArea: string[];
24
- actionArea: string[];
25
- selectionCountText: string[];
26
- }, undefined, {
27
- [key: string]: {
28
- [key: string]: import('tailwind-merge').ClassNameValue | {
29
- base?: import('tailwind-merge').ClassNameValue;
30
- selectionArea?: import('tailwind-merge').ClassNameValue;
31
- actionArea?: import('tailwind-merge').ClassNameValue;
32
- selectionCountText?: import('tailwind-merge').ClassNameValue;
33
- };
34
- };
35
- } | {}, {
36
- base: string[];
37
- selectionArea: string[];
38
- actionArea: string[];
39
- selectionCountText: string[];
40
- }, import('tailwind-variants').TVReturnType<unknown, {
41
- base: string[];
42
- selectionArea: string[];
43
- actionArea: string[];
44
- selectionCountText: string[];
45
- }, undefined, unknown, unknown, undefined>>;
1
+ import { ActionBarProps } from './ActionBar.types.js';
2
+ export type { ActionBarActionItem, ActionBarActionItemBase, ActionBarBaseProps, ActionBarButtonActionItem, ActionBarButtonMeta, ActionBarDynamicProps, ActionBarIconButtonActionItem, ActionBarIconButtonMeta, ActionBarProps, ActionBarStaticProps, } from './ActionBar.types.js';
46
3
  /**
47
- * Action item interface for dynamic API
48
- * Extends ActionBarActionProps but uses onClick instead of onPress and requires id
49
- */
50
- export interface ActionBarActionItem extends Omit<ActionBarActionProps, 'children'> {
51
- /** The unique identifier for the action */
52
- id: string;
53
- /** The label for the action */
54
- label: string;
55
- }
56
- interface ActionBarBaseProps {
57
- /** Unique identifier for the action bar (required for skip links integration) */
58
- id?: string;
59
- /** Number of selected items */
60
- selectionCount: number;
61
- /** Callback when selection is cleared */
62
- onClearSelection: () => void;
63
- /**
64
- * Custom text for selection count (optional)
65
- */
66
- renderSelectionText?: (count: number) => string;
67
- /** ARIA label for the toolbar */
68
- 'aria-label'?: string;
69
- /** ARIA keyshortcuts for the action bar */
70
- 'aria-keyshortcuts'?: string;
71
- /** Callback when the action bar is focused */
72
- onFocus?: () => void;
73
- /** Callback when the action bar is blurred */
74
- onBlur?: () => void;
75
- }
76
- interface ActionBarStaticProps extends ActionBarBaseProps {
77
- /** Static ActionBarAction components */
78
- children?: ReactNode;
79
- /** Actions prop is not allowed with static API */
80
- actions?: never;
81
- }
82
- interface ActionBarDynamicProps extends ActionBarBaseProps {
83
- /** Array of action items */
84
- actions: ActionBarActionItem[];
85
- /** Render function that receives action and index */
86
- children: (action: ActionBarActionItem, index: number) => ReactNode;
87
- }
88
- /**
89
- * Represents the props for an ActionBar component, which can be either static or dynamic.
90
- *
91
- * This type is a union of `ActionBarStaticProps` and `ActionBarDynamicProps`, allowing
92
- * flexibility in specifying the props for the ActionBar depending on its behavior.
93
- *
94
- * Use `ActionBarStaticProps` when the ActionBar requires fixed, unchanging properties,
95
- * and utilize `ActionBarDynamicProps` for scenarios where the properties need to be
96
- * dynamic or state-dependent.
97
- * @see {@link ActionBarStaticProps} for static API props
98
- * @see {@link ActionBarDynamicProps} for dynamic API props
99
- */
100
- export type ActionBarProps = ActionBarStaticProps | ActionBarDynamicProps;
101
- /**
102
- * The ActionBar component provides contextual bulk actions when table rows are selected.
4
+ * The ActionBar component provides a generic floating toolbar with action buttons.
103
5
  * It supports both static (declarative) and dynamic (render prop) APIs for maximum flexibility.
104
- * @param {ActionBarProps} props - Props for ActionBar including id, selectionCount and onClearSelection
105
- * @example
6
+ *
7
+ * The component can render both regular buttons (`ActionBarButton`) and icon-only buttons
8
+ * (`ActionBarIconButton`) based on the `type` discriminator in action items.
9
+ * @param {ActionBarProps} props - Props for ActionBar
10
+ * @example Static API
106
11
  * ```tsx
107
- * import { ActionBar, ActionBarAction, ActionBarRoot } from '@payfit/unity-components'
12
+ * import { ActionBar, ActionBarButton, ActionBarRoot } from '@payfit/unity-components'
108
13
  *
109
- * // Static API with ActionBarAction components
14
+ * // Static API with ActionBarButton components
110
15
  * function StaticExample() {
111
16
  * return (
112
17
  * <ActionBarRoot>
113
- * <ActionBar id="table-actions" selectionCount={2} onClearSelection={handleClear}>
114
- * <ActionBarAction onPress={handleArchive}>Archive</ActionBarAction>
115
- * <ActionBarAction variant="primary" onPress={handleDelete}>Delete</ActionBarAction>
18
+ * <ActionBar id="toolbar">
19
+ * <ActionBarButton onPress={handleArchive}>Archive</ActionBarButton>
20
+ * <ActionBarButton variant="primary" onPress={handleDelete}>Delete</ActionBarButton>
116
21
  * </ActionBar>
117
22
  * </ActionBarRoot>
118
23
  * )
119
24
  * }
120
- *
25
+ * ```
26
+ * @example Static API with prefix content
27
+ * ```tsx
28
+ * // Static API with prefixContent
29
+ * function WithPrefixContent() {
30
+ * return (
31
+ * <ActionBarRoot>
32
+ * <ActionBar
33
+ * id="table-actions"
34
+ * prefixContent={<SelectionInfo count={2} onClear={handleClear} />}
35
+ * >
36
+ * <ActionBarButton onPress={handleArchive}>Archive</ActionBarButton>
37
+ * <ActionBarButton variant="primary" onPress={handleDelete}>Delete</ActionBarButton>
38
+ * </ActionBar>
39
+ * </ActionBarRoot>
40
+ * )
41
+ * }
42
+ * ```
43
+ * @example Dynamic API
44
+ * ```tsx
121
45
  * // Dynamic API with actions array and render function
122
46
  * function DynamicExample() {
123
47
  * const actions = [
124
- * { id: 'archive', onPress: handleArchive, label: 'Archive' },
125
- * { id: 'delete', onPress: handleDelete, variant: 'primary', label: 'Delete' }
48
+ * { id: 'archive', label: 'Archive', meta: { onPress: handleArchive } },
49
+ * { id: 'delete', label: 'Delete', variant: 'primary', meta: { onPress: handleDelete } },
50
+ * { id: 'settings', label: 'Settings', type: 'icon-button', meta: { icon: 'GearOutlined', onPress: handleSettings } },
126
51
  * ]
127
52
  *
128
53
  * return (
129
54
  * <ActionBarRoot>
130
- * <ActionBar id="table-actions" selectionCount={2} onClearSelection={handleClear} actions={actions}>
131
- * {(action, index) => (
132
- * <ActionBarAction key={action.id} {...action}>
133
- * {action.label}
134
- * </ActionBarAction>
135
- * )}
55
+ * <ActionBar id="table-actions" actions={actions}>
56
+ * {(action) => {
57
+ * if (action.type === 'icon-button') {
58
+ * return (
59
+ * <ActionBarIconButton
60
+ * key={action.id}
61
+ * icon={action.meta.icon}
62
+ * label={action.label}
63
+ * variant={action.variant}
64
+ * onPress={action.meta.onPress}
65
+ * />
66
+ * )
67
+ * }
68
+ * return (
69
+ * <ActionBarButton key={action.id} variant={action.variant} {...action.meta}>
70
+ * {action.label}
71
+ * </ActionBarButton>
72
+ * )
73
+ * }}
136
74
  * </ActionBar>
137
75
  * </ActionBarRoot>
138
76
  * )
@@ -140,14 +78,17 @@ export type ActionBarProps = ActionBarStaticProps | ActionBarDynamicProps;
140
78
  * ```
141
79
  * @remarks
142
80
  * - Must be wrapped in ActionBarRoot for proper positioning
143
- * - Only renders when selectionCount > 0
144
- * - Static API: pass ActionBarAction components as children
81
+ * - Use `prefixContent` to render custom content on the left side (e.g., selection info)
82
+ * - Static API: pass ActionBarButton/ActionBarIconButton components as children
145
83
  * - Dynamic API: provide actions array and render function as children
84
+ * - Actions support `type: 'button'` (default) or `type: 'icon-button'` for icon-only buttons
85
+ * - All action-specific props (onPress, prefixIcon, icon, isDisabled, isLoading) go in the `meta` object
146
86
  * - Includes proper ARIA labels and live regions for accessibility
147
87
  * @see {@link ActionBarProps} for all available props
88
+ * @see {@link ActionBarActionItem} for action item structure
148
89
  * @see Source code in [Github](https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/action-bar)
149
90
  * @see Design specs [Figma](https://www.figma.com/design/poaMyU7abAgL9VRhx4ygyy/Unity-DS-%3E-Components-Library)
150
91
  * @see Design docs in [Payfit.design](https://www.payfit.design/)
151
92
  */
152
- declare const ActionBar: React.ForwardRefExoticComponent<ActionBarProps & React.RefAttributes<HTMLDivElement>>;
93
+ declare const ActionBar: import('react').ForwardRefExoticComponent<ActionBarProps & import('react').RefAttributes<HTMLDivElement>>;
153
94
  export { ActionBar };
@@ -1,161 +1,59 @@
1
- import { jsxs as n, jsx as t } from "react/jsx-runtime";
2
- import P, { forwardRef as T, useCallback as R, isValidElement as j } from "react";
3
- import { uyTv as z } from "@payfit/unity-themes";
4
- import { Toolbar as D, Group as y } from "react-aria-components";
5
- import { useIntl as S, FormattedMessage as l } from "react-intl";
6
- import { Button as _ } from "../button/Button.js";
7
- import { IconButton as E } from "../icon-button/IconButton.js";
8
- import { Icon as F } from "../icon/Icon.js";
9
- import { Menu as G } from "../menu/Menu.js";
10
- import { MenuContent as K } from "../menu/parts/MenuContent.js";
11
- import { MenuTrigger as L } from "../menu/parts/MenuTrigger.js";
12
- import { RawMenuItem as O } from "../menu/parts/RawMenuItem.js";
13
- import { ActionBarAction as U } from "./parts/ActionBarAction.js";
14
- const V = z({
15
- slots: {
16
- base: [
17
- "uy:bg-surface-inverted uy:text-content-inverted",
18
- "uy:rounded-100 uy:shadow-300",
19
- "uy:flex uy:items-center uy:gap-100 uy:md:gap-200 uy:py-50 uy:pl-50 uy:md:pl-200 uy:pr-50",
20
- "uy:transition-all uy:duration-200",
21
- "uy:max-w-full uy:min-w-0 uy:w-fit",
22
- // Ensure responsive behavior
23
- "uy:focus-visible:outline-2 uy:focus-visible:outline-solid uy:focus-visible:outline-offset-2 uy:focus-visible:outline-utility-focus-ring"
24
- ],
25
- selectionArea: ["uy:flex uy:items-center uy:gap-100"],
26
- actionArea: ["uy:flex uy:items-center uy:gap-100"],
27
- selectionCountText: [
28
- "uy:typography-body uy:whitespace-nowrap!",
29
- "uy:sr-only",
30
- "uy:md:not-sr-only"
31
- ]
32
- }
33
- }), q = T(
1
+ import { jsxs as e, jsx as i } from "react/jsx-runtime";
2
+ import { forwardRef as g } from "react";
3
+ import { Toolbar as y, Group as M } from "react-aria-components";
4
+ import { useIntl as x } from "react-intl";
5
+ import { actionBar as v } from "./ActionBar.variants.js";
6
+ import { useActionBarState as w } from "./hooks/use-action-bar-state.js";
7
+ import { ActionBarOverflowMenu as N } from "./parts/ActionBarOverflowMenu.js";
8
+ import { ActionBarPrefixArea as j } from "./parts/ActionBarPrefixArea.js";
9
+ const I = g(
34
10
  ({
35
- id: d,
36
- selectionCount: u,
37
- onClearSelection: f,
38
- children: r,
39
- actions: a,
40
- renderSelectionText: c,
41
- "aria-label": p,
42
- onFocus: b,
43
- onBlur: h,
44
- ...i
45
- }, v) => {
46
- const { base: g, selectionArea: x, selectionCountText: A, actionArea: M } = V(), m = S(), s = a !== void 0 && typeof r == "function", k = i["aria-keyshortcuts"] !== void 0, B = p ?? m.formatMessage({
11
+ id: n,
12
+ prefixContent: o,
13
+ children: s,
14
+ actions: l,
15
+ "aria-label": c,
16
+ onFocus: m,
17
+ onBlur: f,
18
+ forceExpandMobile: b = !1,
19
+ ...a
20
+ }, u) => {
21
+ const r = x(), { base: A, actionArea: d } = v({
22
+ hasPrefixContent: !!o
23
+ }), { renderActions: p, mobileOverflowActions: t, hasActions: h } = w({
24
+ actions: l,
25
+ children: s,
26
+ forceExpandMobile: b
27
+ }), B = c ?? r.formatMessage({
47
28
  id: "unity:component:action-bar:toolbar-label",
48
- defaultMessage: "Bulk actions toolbar"
49
- }), I = R(() => {
50
- if (s) {
51
- const e = r;
52
- return a.map((o, N) => e(o, N));
53
- }
54
- return r;
55
- }, [r, a, s]), w = !!r || "actions" in i && i.actions.length > 0, C = s ? a.filter((e) => e.variant !== "primary") : P.Children.map(r, (e) => {
56
- if (!j(e) || e.type !== U)
57
- return null;
58
- const o = e.props;
59
- return o.variant === "primary" ? null : {
60
- ...o,
61
- id: e.key ?? o.id,
62
- onPress: o.onPress,
63
- label: o.children,
64
- variant: o.variant,
65
- prefixIcon: o.prefixIcon
66
- };
67
- })?.filter(Boolean);
68
- return /* @__PURE__ */ n(
69
- D,
29
+ defaultMessage: "Actions toolbar"
30
+ });
31
+ return /* @__PURE__ */ e(
32
+ y,
70
33
  {
71
- ...i,
72
- id: d,
73
- ref: v,
74
- className: g(),
34
+ ...a,
35
+ id: n,
36
+ ref: u,
37
+ className: A(),
75
38
  "aria-label": B,
76
39
  orientation: "horizontal",
77
40
  tabIndex: -1,
78
- onFocus: b,
79
- onBlur: h,
41
+ onFocus: m,
42
+ onBlur: f,
80
43
  children: [
81
- /* @__PURE__ */ n(
82
- y,
83
- {
84
- className: x(),
85
- "aria-label": m.formatMessage({
86
- id: "unity:component:action-bar:group:label",
87
- defaultMessage: "Selection information"
88
- }),
89
- children: [
90
- /* @__PURE__ */ n(
91
- "div",
92
- {
93
- className: A(),
94
- role: "status",
95
- "aria-live": "polite",
96
- "aria-atomic": "true",
97
- children: [
98
- c ? c(u) : /* @__PURE__ */ t(
99
- l,
100
- {
101
- id: "unity:component:action-bar:selection-count-text",
102
- defaultMessage: "{selectionCount, plural, =0 {no items} one {item} other {items}} selected",
103
- values: { selectionCount: u }
104
- }
105
- ),
106
- k && /* @__PURE__ */ t("span", { className: "uy:sr-only", children: /* @__PURE__ */ t(
107
- l,
108
- {
109
- id: "unity:component:action-bar:key-shortcuts-text",
110
- defaultMessage: "Use {keyShortcuts} to focus the action bar",
111
- values: {
112
- keyShortcuts: i["aria-keyshortcuts"]
113
- }
114
- }
115
- ) })
116
- ]
117
- }
118
- ),
119
- /* @__PURE__ */ t(_, { color: "inverted", variant: "ghost", onPress: f, children: /* @__PURE__ */ t(
120
- l,
121
- {
122
- id: "unity:component:action-bar:clear-selection-button",
123
- defaultMessage: "Clear selection"
124
- }
125
- ) })
126
- ]
127
- }
128
- ),
129
- w && /* @__PURE__ */ n(
130
- y,
44
+ o && /* @__PURE__ */ i(j, { ariaKeyshortcuts: a["aria-keyshortcuts"], children: o }),
45
+ h && /* @__PURE__ */ e(
46
+ M,
131
47
  {
132
- className: M(),
48
+ className: d(),
133
49
  role: "group",
134
- "aria-label": "Available actions",
50
+ "aria-label": r.formatMessage({
51
+ id: "unity:component:action-bar:actions:label",
52
+ defaultMessage: "Available actions"
53
+ }),
135
54
  children: [
136
- I(),
137
- /* @__PURE__ */ t("div", { className: "uy:block uy:md:hidden", children: /* @__PURE__ */ n(G, { children: [
138
- /* @__PURE__ */ t(L, { asChild: !0, children: /* @__PURE__ */ t(
139
- E,
140
- {
141
- icon: "DotsThreeOutlined",
142
- label: "More actions",
143
- variant: "ghost",
144
- color: "inverted"
145
- }
146
- ) }),
147
- /* @__PURE__ */ t(K, { children: C.map((e) => /* @__PURE__ */ t(
148
- O,
149
- {
150
- onAction: () => {
151
- e.onPress?.({});
152
- },
153
- prefix: e.prefixIcon ? /* @__PURE__ */ t(F, { src: e.prefixIcon, size: 20 }) : void 0,
154
- children: e.label
155
- },
156
- e.id
157
- )) })
158
- ] }) })
55
+ p(),
56
+ t.length > 0 && /* @__PURE__ */ i(N, { actions: t })
159
57
  ]
160
58
  }
161
59
  )
@@ -164,8 +62,7 @@ const V = z({
164
62
  );
165
63
  }
166
64
  );
167
- q.displayName = "ActionBar";
65
+ I.displayName = "ActionBar";
168
66
  export {
169
- q as ActionBar,
170
- V as actionBar
67
+ I as ActionBar
171
68
  };
@@ -0,0 +1,116 @@
1
+ import { FocusEventHandler, ReactNode } from 'react';
2
+ import { ActionBarButtonProps } from './parts/ActionBarButton.js';
3
+ import { ActionBarIconButtonProps } from './parts/ActionBarIconButton.js';
4
+ /**
5
+ * Base interface for action items shared between button and icon-button types
6
+ */
7
+ export interface ActionBarActionItemBase {
8
+ /** The unique identifier for the action */
9
+ id: string;
10
+ /** The label for the action */
11
+ label: string;
12
+ /** The visual variant of the action */
13
+ variant?: 'primary' | 'secondary';
14
+ }
15
+ /**
16
+ * Meta props for button action type
17
+ */
18
+ export type ActionBarButtonMeta = Omit<ActionBarButtonProps, 'variant'>;
19
+ /**
20
+ * Meta props for icon-button action type
21
+ */
22
+ export type ActionBarIconButtonMeta = Omit<ActionBarIconButtonProps, 'variant' | 'label'>;
23
+ /**
24
+ * Action item for button type (default)
25
+ */
26
+ export interface ActionBarButtonActionItem extends ActionBarActionItemBase {
27
+ /** Type discriminator - defaults to 'button' if omitted */
28
+ type?: 'button';
29
+ /** Meta properties for the button */
30
+ meta?: ActionBarButtonMeta;
31
+ }
32
+ /**
33
+ * Action item for icon-button type
34
+ */
35
+ export interface ActionBarIconButtonActionItem extends ActionBarActionItemBase {
36
+ /** Type discriminator - required for icon-button */
37
+ type: 'icon-button';
38
+ /** Meta properties for the icon button (icon is required) */
39
+ meta: ActionBarIconButtonMeta;
40
+ }
41
+ /**
42
+ * Union type for action items supporting both button and icon-button types
43
+ * @example
44
+ * ```typescript
45
+ * // Button action (type can be omitted)
46
+ * const buttonAction: ActionBarActionItem = {
47
+ * id: 'archive',
48
+ * label: 'Archive',
49
+ * variant: 'secondary',
50
+ * meta: {
51
+ * onPress: () => console.log('Archive'),
52
+ * prefixIcon: 'FileArchiveOutlined',
53
+ * }
54
+ * }
55
+ *
56
+ * // Icon-button action
57
+ * const iconButtonAction: ActionBarActionItem = {
58
+ * id: 'delete',
59
+ * label: 'Delete',
60
+ * type: 'icon-button',
61
+ * variant: 'primary',
62
+ * meta: {
63
+ * icon: 'TrashOutlined',
64
+ * onPress: () => console.log('Delete'),
65
+ * }
66
+ * }
67
+ * ```
68
+ */
69
+ export type ActionBarActionItem = ActionBarButtonActionItem | ActionBarIconButtonActionItem;
70
+ interface ActionBarBaseProps {
71
+ /** Unique identifier for the action bar (required for skip links integration) */
72
+ id?: string;
73
+ /**
74
+ * Optional content to render on the left side of the toolbar (e.g., selection info)
75
+ */
76
+ prefixContent?: ReactNode;
77
+ /** ARIA label for the toolbar */
78
+ 'aria-label'?: string;
79
+ /** ARIA keyshortcuts for the action bar */
80
+ 'aria-keyshortcuts'?: string;
81
+ /** Callback when the action bar is focused */
82
+ onFocus?: FocusEventHandler<HTMLDivElement>;
83
+ /** Callback when the action bar is blurred */
84
+ onBlur?: FocusEventHandler<HTMLDivElement>;
85
+ /**
86
+ * Force all actions to render in mobile view instead of collapsing them into dropdown menu
87
+ * @default false
88
+ */
89
+ forceExpandMobile?: boolean;
90
+ }
91
+ interface ActionBarStaticProps extends ActionBarBaseProps {
92
+ /** Static ActionBarButton components */
93
+ children?: ReactNode;
94
+ /** Actions prop is not allowed with static API */
95
+ actions?: never;
96
+ }
97
+ interface ActionBarDynamicProps extends ActionBarBaseProps {
98
+ /** Array of action items */
99
+ actions: ActionBarActionItem[];
100
+ /** Render function that receives action and index */
101
+ children: (action: ActionBarActionItem, index: number) => ReactNode;
102
+ }
103
+ /**
104
+ * Represents the props for an ActionBar component, which can be either static or dynamic.
105
+ *
106
+ * This type is a union of `ActionBarStaticProps` and `ActionBarDynamicProps`, allowing
107
+ * flexibility in specifying the props for the ActionBar depending on its behavior.
108
+ *
109
+ * Use `ActionBarStaticProps` when the ActionBar requires fixed, unchanging properties,
110
+ * and utilize `ActionBarDynamicProps` for scenarios where the properties need to be
111
+ * dynamic or state-dependent.
112
+ * @see {@link ActionBarStaticProps} for static API props
113
+ * @see {@link ActionBarDynamicProps} for dynamic API props
114
+ */
115
+ export type ActionBarProps = ActionBarStaticProps | ActionBarDynamicProps;
116
+ export type { ActionBarStaticProps, ActionBarDynamicProps, ActionBarBaseProps };
@@ -0,0 +1,31 @@
1
+ export declare const actionBar: import('tailwind-variants').TVReturnType<{
2
+ hasPrefixContent: {
3
+ true: {
4
+ base: string;
5
+ };
6
+ };
7
+ }, {
8
+ base: string[];
9
+ prefixArea: string[];
10
+ actionArea: string[];
11
+ }, undefined, {
12
+ hasPrefixContent: {
13
+ true: {
14
+ base: string;
15
+ };
16
+ };
17
+ }, {
18
+ base: string[];
19
+ prefixArea: string[];
20
+ actionArea: string[];
21
+ }, import('tailwind-variants').TVReturnType<{
22
+ hasPrefixContent: {
23
+ true: {
24
+ base: string;
25
+ };
26
+ };
27
+ }, {
28
+ base: string[];
29
+ prefixArea: string[];
30
+ actionArea: string[];
31
+ }, undefined, unknown, unknown, undefined>>;
@@ -0,0 +1,26 @@
1
+ import { uyTv as u } from "@payfit/unity-themes";
2
+ const t = u({
3
+ slots: {
4
+ base: [
5
+ "uy:bg-surface-inverted uy:text-content-inverted",
6
+ "uy:rounded-150 uy:md:rounded-100 uy:shadow-300",
7
+ "uy:flex uy:items-center uy:gap-200 uy:md:gap-200 uy:py-50 uy:pl-50 uy:pr-50",
8
+ "uy:transition-all uy:duration-200",
9
+ "uy:max-w-full uy:min-w-0 uy:w-fit",
10
+ // Ensure responsive behavior
11
+ "uy:focus-visible:outline-2 uy:focus-visible:outline-solid uy:focus-visible:outline-offset-2 uy:focus-visible:outline-utility-focus-ring"
12
+ ],
13
+ prefixArea: ["uy:flex uy:items-center uy:gap-100"],
14
+ actionArea: ["uy:flex uy:items-center uy:gap-100"]
15
+ },
16
+ variants: {
17
+ hasPrefixContent: {
18
+ true: {
19
+ base: "uy:pl-200"
20
+ }
21
+ }
22
+ }
23
+ });
24
+ export {
25
+ t as actionBar
26
+ };
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ import { ActionBarActionItem, ActionBarButtonActionItem } from '../ActionBar.types.js';
3
+ interface UseActionBarStateOptions {
4
+ actions?: ActionBarActionItem[];
5
+ children?: ReactNode | ((action: ActionBarActionItem, index: number) => ReactNode);
6
+ forceExpandMobile?: boolean;
7
+ }
8
+ interface UseActionBarStateResult {
9
+ /** Whether using dynamic API (actions array + render function) */
10
+ isDynamicApi: boolean;
11
+ /** Whether there are any actions to render */
12
+ hasActions: boolean;
13
+ /** Render function for visible actions */
14
+ renderActions: () => ReactNode;
15
+ /** Actions to show in mobile overflow menu */
16
+ mobileOverflowActions: ActionBarButtonActionItem[];
17
+ }
18
+ export declare const useActionBarState: ({ actions, children, forceExpandMobile, }: UseActionBarStateOptions) => UseActionBarStateResult;
19
+ export {};
@@ -0,0 +1,22 @@
1
+ import A, { useCallback as l, isValidElement as y, useMemo as c } from "react";
2
+ import { useBreakpointListener as k, isMobileBreakpoint as v } from "../../../hooks/use-breakpoint-listener.js";
3
+ import { extractMobileActionsFromArray as B, extractMobileActionsFromChildren as b } from "../utils/action-bar-helpers.js";
4
+ const _ = ({
5
+ actions: r,
6
+ children: t,
7
+ forceExpandMobile: o = !1
8
+ }) => {
9
+ const a = k(), i = v(a), e = r !== void 0 && typeof t == "function", m = e ? r.length > 0 : !!t, u = l(() => {
10
+ if (e) {
11
+ const n = t;
12
+ return (i && !o ? r.filter((s) => s.variant === "primary") : r).map((s, f) => n(s, f));
13
+ }
14
+ return i && !o ? A.Children.toArray(t).filter(
15
+ (n) => y(n) && n.props.variant === "primary"
16
+ ) : t;
17
+ }, [e, i, o, t, r]), p = c(() => o ? [] : e ? B(r) : b(t), [e, o, r, t]);
18
+ return { isDynamicApi: e, hasActions: m, renderActions: u, mobileOverflowActions: p };
19
+ };
20
+ export {
21
+ _ as useActionBarState
22
+ };