@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.
- package/dist/esm/components/action-bar/ActionBar.d.ts +61 -120
- package/dist/esm/components/action-bar/ActionBar.js +48 -151
- package/dist/esm/components/action-bar/ActionBar.types.d.ts +116 -0
- package/dist/esm/components/action-bar/ActionBar.variants.d.ts +31 -0
- package/dist/esm/components/action-bar/ActionBar.variants.js +26 -0
- package/dist/esm/components/action-bar/hooks/use-action-bar-state.d.ts +19 -0
- package/dist/esm/components/action-bar/hooks/use-action-bar-state.js +22 -0
- package/dist/esm/components/action-bar/parts/ActionBarButton.d.ts +58 -0
- package/dist/esm/components/action-bar/parts/ActionBarButton.js +35 -0
- package/dist/esm/components/action-bar/parts/ActionBarIconButton.d.ts +61 -0
- package/dist/esm/components/action-bar/parts/ActionBarIconButton.js +41 -0
- package/dist/esm/components/action-bar/parts/ActionBarOverflowMenu.d.ts +10 -0
- package/dist/esm/components/action-bar/parts/ActionBarOverflowMenu.js +45 -0
- package/dist/esm/components/action-bar/parts/ActionBarPrefixArea.d.ts +11 -0
- package/dist/esm/components/action-bar/parts/ActionBarPrefixArea.js +35 -0
- package/dist/esm/components/action-bar/parts/ActionBarRoot.d.ts +23 -0
- package/dist/esm/components/action-bar/parts/ActionBarRoot.js +23 -13
- package/dist/esm/components/action-bar/utils/action-bar-helpers.d.ts +14 -0
- package/dist/esm/components/action-bar/utils/action-bar-helpers.js +29 -0
- package/dist/esm/components/data-table/parts/DataTableBulkActions.d.ts +16 -6
- package/dist/esm/components/data-table/parts/DataTableBulkActions.js +122 -37
- package/dist/esm/components/icon-button/IconButton.d.ts +4 -0
- package/dist/esm/components/icon-button/IconButton.js +40 -31
- package/dist/esm/components/menu/parts/RawMenuItem.d.ts +2 -1
- package/dist/esm/components/menu/parts/RawMenuItem.js +14 -12
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +545 -543
- package/i18n/en-GB.json +2 -0
- package/i18n/es-ES.json +2 -0
- package/i18n/fr-FR.json +2 -0
- package/package.json +8 -8
- package/dist/esm/components/action-bar/parts/ActionBarAction.d.ts +0 -44
- package/dist/esm/components/action-bar/parts/ActionBarAction.js +0 -45
|
@@ -1,138 +1,76 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
105
|
-
*
|
|
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,
|
|
12
|
+
* import { ActionBar, ActionBarButton, ActionBarRoot } from '@payfit/unity-components'
|
|
108
13
|
*
|
|
109
|
-
* // Static API with
|
|
14
|
+
* // Static API with ActionBarButton components
|
|
110
15
|
* function StaticExample() {
|
|
111
16
|
* return (
|
|
112
17
|
* <ActionBarRoot>
|
|
113
|
-
* <ActionBar id="
|
|
114
|
-
* <
|
|
115
|
-
* <
|
|
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',
|
|
125
|
-
* { id: '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"
|
|
131
|
-
* {(action
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
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
|
-
* -
|
|
144
|
-
* - Static API: pass
|
|
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:
|
|
93
|
+
declare const ActionBar: import('react').ForwardRefExoticComponent<ActionBarProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
153
94
|
export { ActionBar };
|
|
@@ -1,161 +1,59 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
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:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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: "
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
...
|
|
72
|
-
id:
|
|
73
|
-
ref:
|
|
74
|
-
className:
|
|
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:
|
|
79
|
-
onBlur:
|
|
41
|
+
onFocus: m,
|
|
42
|
+
onBlur: f,
|
|
80
43
|
children: [
|
|
81
|
-
/* @__PURE__ */
|
|
82
|
-
|
|
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:
|
|
48
|
+
className: d(),
|
|
133
49
|
role: "group",
|
|
134
|
-
"aria-label":
|
|
50
|
+
"aria-label": r.formatMessage({
|
|
51
|
+
id: "unity:component:action-bar:actions:label",
|
|
52
|
+
defaultMessage: "Available actions"
|
|
53
|
+
}),
|
|
135
54
|
children: [
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
65
|
+
I.displayName = "ActionBar";
|
|
168
66
|
export {
|
|
169
|
-
|
|
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
|
+
};
|