@payfit/unity-components 2.1.4 → 2.2.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 (32) hide show
  1. package/dist/esm/components/avatar/Avatar.context.d.ts +2 -1
  2. package/dist/esm/components/avatar/Avatar.context.js +13 -11
  3. package/dist/esm/components/avatar/Avatar.d.ts +126 -0
  4. package/dist/esm/components/avatar/Avatar.js +34 -20
  5. package/dist/esm/components/avatar/Avatar.variants.d.ts +39 -0
  6. package/dist/esm/components/avatar/Avatar.variants.js +22 -4
  7. package/dist/esm/components/avatar/parts/AvatarFallback.d.ts +52 -0
  8. package/dist/esm/components/avatar/parts/AvatarIcon.d.ts +31 -0
  9. package/dist/esm/components/avatar/parts/AvatarIcon.js +40 -0
  10. package/dist/esm/components/button/Button.js +8 -7
  11. package/dist/esm/components/inline-field-group/InlineFieldGroup.context.d.ts +23 -0
  12. package/dist/esm/components/inline-field-group/InlineFieldGroup.context.js +6 -0
  13. package/dist/esm/components/inline-field-group/InlineFieldGroup.d.ts +119 -0
  14. package/dist/esm/components/inline-field-group/InlineFieldGroup.js +185 -0
  15. package/dist/esm/components/inline-field-group/hooks/useInlineFieldGroupMode.d.ts +46 -0
  16. package/dist/esm/components/inline-field-group/hooks/useInlineFieldGroupMode.js +27 -0
  17. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupEditView.d.ts +64 -0
  18. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupEditView.js +56 -0
  19. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupHeader.d.ts +95 -0
  20. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupHeader.js +106 -0
  21. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupReadView.d.ts +56 -0
  22. package/dist/esm/components/inline-field-group/parts/InlineFieldGroupReadView.js +28 -0
  23. package/dist/esm/components/side-panel/parts/SidePanelFooter.js +19 -10
  24. package/dist/esm/hooks/tanstack-form-context.d.ts +1 -1
  25. package/dist/esm/hooks/use-tanstack-form.d.ts +32 -8
  26. package/dist/esm/hooks/use-tanstack-form.js +71 -48
  27. package/dist/esm/index.d.ts +1 -0
  28. package/dist/esm/index.js +445 -443
  29. package/i18n/en-GB.json +6 -0
  30. package/i18n/es-ES.json +6 -0
  31. package/i18n/fr-FR.json +6 -0
  32. package/package.json +21 -21
@@ -0,0 +1,119 @@
1
+ import { default as React, PropsWithChildren } from 'react';
2
+ import { InlineFieldGroupMode } from './InlineFieldGroup.context.js';
3
+ /**
4
+ * Imperative handle for InlineFieldGroup component.
5
+ * Provides methods for programmatic control when needed for advanced use cases.
6
+ */
7
+ export interface InlineFieldGroupHandle {
8
+ /**
9
+ * Focuses the first invalid field in the edit view.
10
+ * Useful for custom validation error handling.
11
+ */
12
+ focusFirstInvalidField: () => void;
13
+ /**
14
+ * Exits edit mode programmatically.
15
+ */
16
+ exitEditMode: () => void;
17
+ /**
18
+ * Enters edit mode programmatically.
19
+ */
20
+ enterEditMode: () => void;
21
+ }
22
+ export interface InlineFieldGroupProps extends PropsWithChildren {
23
+ /**
24
+ * Controlled mode value. When provided, the component operates in controlled mode.
25
+ */
26
+ mode?: InlineFieldGroupMode;
27
+ /**
28
+ * Default mode value for uncontrolled mode.
29
+ * @default 'read'
30
+ */
31
+ defaultMode?: InlineFieldGroupMode;
32
+ /**
33
+ * Callback fired when mode changes.
34
+ */
35
+ onModeChange?: (mode: InlineFieldGroupMode) => void;
36
+ /**
37
+ * Callback to intercept and potentially prevent mode changes.
38
+ * Return `false` to prevent the mode transition.
39
+ * Return `true` or `undefined` to allow the transition.
40
+ */
41
+ shouldModeChange?: (fromMode: InlineFieldGroupMode, toMode: InlineFieldGroupMode) => boolean | undefined;
42
+ /**
43
+ * Whether the component is in a loading state (e.g., during async save).
44
+ */
45
+ isLoading?: boolean;
46
+ /**
47
+ * Optional className for custom styling
48
+ */
49
+ className?: string;
50
+ /**
51
+ * Optional aria-label for the form element.
52
+ * If not provided, aria-labelledby will reference the header title.
53
+ */
54
+ 'aria-label'?: string;
55
+ /**
56
+ * Success message to announce when save succeeds.
57
+ * If not provided, no success announcement is made.
58
+ */
59
+ successMessage?: string;
60
+ /**
61
+ * Error message to announce when save or validation fails.
62
+ * If not provided, generic validation errors are announced.
63
+ */
64
+ errorMessage?: string;
65
+ }
66
+ /**
67
+ * InlineFieldGroup enables group-level inline editing with read/edit mode switching.
68
+ * It integrates with TanStack Form for validation and state management, providing
69
+ * a complete pattern for displaying data in read mode and editing it in edit mode.
70
+ * The component handles the full edit lifecycle: mode transitions, form submission,
71
+ * validation error handling, and accessibility announcements.
72
+ * @example
73
+ * ```tsx
74
+ * import { useTanstackUnityForm } from '@payfit/unity-components'
75
+ *
76
+ * function ContactForm() {
77
+ * const form = useTanstackUnityForm({
78
+ * defaultValues: { email: 'user@example.com', phone: '+1234567890' },
79
+ * onSubmit: async ({ value }) => {
80
+ * await saveContact(value)
81
+ * }
82
+ * })
83
+ *
84
+ * return (
85
+ * <form.AppForm>
86
+ * <form.InlineFieldGroup successMessage="Contact saved!">
87
+ * <form.InlineFieldGroupHeader title="Contact Information" />
88
+ * <form.InlineFieldGroupReadView>
89
+ * <DefinitionList>
90
+ * <DefinitionItem term="Email" description={form.state.values.email} />
91
+ * </DefinitionList>
92
+ * </form.InlineFieldGroupReadView>
93
+ * <form.InlineFieldGroupEditView legend="Edit contact">
94
+ * <form.AppField name="email">
95
+ * {field => <field.TextField label="Email" />}
96
+ * </form.AppField>
97
+ * </form.InlineFieldGroupEditView>
98
+ * </form.InlineFieldGroup>
99
+ * </form.AppForm>
100
+ * )
101
+ * }
102
+ * ```
103
+ * @remarks
104
+ * - The component automatically exits edit mode on successful form submission
105
+ * - Press Escape to cancel editing and reset form values
106
+ * - Focus moves to the first form field when entering edit mode
107
+ * - Focus returns to the edit button when exiting edit mode
108
+ * - Focus is retained under a scope when in edit mode, to prevent users for leaving unfinished changes
109
+ * - Use `shouldModeChange` to intercept and conditionally prevent mode transitions
110
+ * - Use `successMessage` and `errorMessage` for accessible announcements via live regions
111
+ * @see {@link InlineFieldGroupProps} for all available props
112
+ * @see {@link InlineFieldGroupHandle} for imperative handle methods
113
+ * @see {@link InlineFieldGroupHeader} for the header component with action buttons
114
+ * @see {@link InlineFieldGroupReadView} for read mode content
115
+ * @see {@link InlineFieldGroupEditView} for edit mode form fields
116
+ * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/inline-field-group GitHub}
117
+ * @see Developer docs in {@link https://unity-components.payfit.io/?path=/docs/forms-reference-inlinefieldgroup--docs unity-components.payfit.io}
118
+ */
119
+ export declare const InlineFieldGroup: React.ForwardRefExoticComponent<InlineFieldGroupProps & React.RefAttributes<InlineFieldGroupHandle>>;
@@ -0,0 +1,185 @@
1
+ import { jsx as x, jsxs as z } from "react/jsx-runtime";
2
+ import { forwardRef as J, useRef as l, useState as V, useEffect as r, useCallback as P, useImperativeHandle as Q, useMemo as W } from "react";
3
+ import { uyTv as X } from "@payfit/unity-themes";
4
+ import { useStore as Y } from "@tanstack/react-form";
5
+ import { useId as Z, useKeyboard as L, FocusScope as ee } from "react-aria";
6
+ import { useIntl as te } from "react-intl";
7
+ import { useFormContext as ie } from "../../hooks/tanstack-form-context.js";
8
+ import { useInlineFieldGroupMode as re } from "./hooks/useInlineFieldGroupMode.js";
9
+ import { InlineFieldGroupContext as oe } from "./InlineFieldGroup.context.js";
10
+ const se = X({
11
+ slots: {
12
+ form: "uy:flex uy:flex-col uy:gap-300"
13
+ }
14
+ }), D = (a) => {
15
+ if (!a.current) return;
16
+ const c = a.current.querySelector(
17
+ '[aria-invalid="true"]'
18
+ );
19
+ c && c.focus();
20
+ }, k = 5e3, ne = J(
21
+ ({
22
+ children: a,
23
+ mode: c,
24
+ defaultMode: j,
25
+ onModeChange: q,
26
+ shouldModeChange: m,
27
+ isLoading: N,
28
+ className: K,
29
+ "aria-label": _,
30
+ successMessage: g,
31
+ errorMessage: d
32
+ }, O) => {
33
+ const s = Z(), A = `unity-InlineFieldGroup-${s}__header`, C = `unity-InlineFieldGroup-${s}__edit-view`, E = l(null), n = l(null), M = l(!0), [G, R] = V(""), [h, f] = V(""), p = te(), u = ie(), { mode: t, enterEditMode: b, exitEditMode: o } = re({
34
+ mode: c,
35
+ defaultMode: j,
36
+ onModeChange: q,
37
+ shouldModeChange: m
38
+ }), { isSubmitting: i, isValid: v, isSubmitSuccessful: S, submissionAttempts: y } = Y(u.store, (e) => ({
39
+ isSubmitting: e.isSubmitting,
40
+ isValid: e.isValid,
41
+ isSubmitSuccessful: e.isSubmitSuccessful,
42
+ submissionAttempts: e.submissionAttempts
43
+ })), F = l(i), T = l(y);
44
+ r(() => {
45
+ i && !F.current && (R(""), f(""));
46
+ }, [i]), r(() => {
47
+ if (y > T.current && !v) {
48
+ const I = d ?? p.formatMessage({
49
+ id: "unity:component:inline-field-group:validation-error",
50
+ defaultMessage: "Please fix the errors before saving."
51
+ });
52
+ f(I), D(n);
53
+ }
54
+ }, [y, v, d, p]), r(() => {
55
+ F.current && !i && S && (g && R(g), o());
56
+ }, [i, S, g, o]), r(() => {
57
+ if (F.current && !i && !S && v) {
58
+ const I = d ?? p.formatMessage({
59
+ id: "unity:component:inline-field-group:save-error",
60
+ defaultMessage: "An error occurred while saving. Please try again."
61
+ });
62
+ f(I);
63
+ }
64
+ }, [i, S, v, d, p]), r(() => {
65
+ F.current = i, T.current = y;
66
+ });
67
+ const $ = P(
68
+ (e) => {
69
+ e.preventDefault(), e.stopPropagation(), u.handleSubmit();
70
+ },
71
+ [u]
72
+ ), w = P(() => {
73
+ m !== void 0 && !m(t, "read") || (u.reset(), o());
74
+ }, [u, t, o, m]);
75
+ Q(
76
+ O,
77
+ () => ({
78
+ focusFirstInvalidField: () => {
79
+ D(n);
80
+ },
81
+ exitEditMode: o,
82
+ enterEditMode: b
83
+ }),
84
+ [o, b]
85
+ ), r(() => {
86
+ if (M.current) {
87
+ M.current = !1;
88
+ return;
89
+ }
90
+ if (t === "edit") {
91
+ if (n.current) {
92
+ const e = n.current.querySelectorAll(
93
+ 'input, select, textarea, [tabindex]:not([tabindex="-1"])'
94
+ );
95
+ e.length > 0 && e[0].focus();
96
+ }
97
+ } else
98
+ E.current && E.current.focus();
99
+ }, [t]);
100
+ const { keyboardProps: B } = L({
101
+ onKeyDown: (e) => {
102
+ e.key === "Escape" && t === "edit" && (e.preventDefault(), w());
103
+ }
104
+ });
105
+ r(() => {
106
+ if (G) {
107
+ const e = setTimeout(() => {
108
+ R("");
109
+ }, k);
110
+ return () => {
111
+ clearTimeout(e);
112
+ };
113
+ }
114
+ }, [G]), r(() => {
115
+ if (h) {
116
+ const e = setTimeout(() => {
117
+ f("");
118
+ }, k);
119
+ return () => {
120
+ clearTimeout(e);
121
+ };
122
+ }
123
+ }, [h]);
124
+ const H = W(
125
+ () => ({
126
+ mode: t,
127
+ enterEditMode: b,
128
+ exitEditMode: w,
129
+ groupId: s,
130
+ headerId: A,
131
+ editViewId: C,
132
+ isLoading: N,
133
+ editButtonRef: E,
134
+ editViewRef: n
135
+ }),
136
+ [
137
+ t,
138
+ b,
139
+ w,
140
+ s,
141
+ A,
142
+ C,
143
+ N
144
+ ]
145
+ ), { form: U } = se();
146
+ return /* @__PURE__ */ x(oe.Provider, { value: H, children: /* @__PURE__ */ x(
147
+ "form",
148
+ {
149
+ ...B,
150
+ id: s,
151
+ className: U({ className: K }),
152
+ onSubmit: $,
153
+ "aria-label": _,
154
+ "aria-labelledby": _ ? void 0 : A,
155
+ children: /* @__PURE__ */ z(ee, { contain: t === "edit", children: [
156
+ a,
157
+ /* @__PURE__ */ x(
158
+ "div",
159
+ {
160
+ role: "status",
161
+ "aria-live": "polite",
162
+ "aria-atomic": "true",
163
+ className: "uy:sr-only",
164
+ children: G
165
+ }
166
+ ),
167
+ /* @__PURE__ */ x(
168
+ "div",
169
+ {
170
+ role: "alert",
171
+ "aria-live": "assertive",
172
+ "aria-atomic": "true",
173
+ className: "uy:sr-only",
174
+ children: h
175
+ }
176
+ )
177
+ ] })
178
+ }
179
+ ) });
180
+ }
181
+ );
182
+ ne.displayName = "InlineFieldGroup";
183
+ export {
184
+ ne as InlineFieldGroup
185
+ };
@@ -0,0 +1,46 @@
1
+ import { InlineFieldGroupMode } from '../InlineFieldGroup.context.js';
2
+ export interface UseInlineFieldGroupModeProps {
3
+ /**
4
+ * Controlled mode value. When provided, the component operates in controlled mode.
5
+ */
6
+ mode?: InlineFieldGroupMode;
7
+ /**
8
+ * Default mode value for uncontrolled mode.
9
+ * @default 'read'
10
+ */
11
+ defaultMode?: InlineFieldGroupMode;
12
+ /**
13
+ * Callback fired when mode changes.
14
+ */
15
+ onModeChange?: (mode: InlineFieldGroupMode) => void;
16
+ /**
17
+ * Callback to intercept and potentially prevent mode changes.
18
+ * Return `false` to prevent the mode transition.
19
+ * Return `true` or `undefined` to allow the transition.
20
+ */
21
+ shouldModeChange?: (fromMode: InlineFieldGroupMode, toMode: InlineFieldGroupMode) => boolean | undefined;
22
+ }
23
+ export interface UseInlineFieldGroupModeReturn {
24
+ /** Current mode value */
25
+ mode: InlineFieldGroupMode;
26
+ /** Switch to edit mode */
27
+ enterEditMode: () => void;
28
+ /** Exit edit mode (return to read mode) */
29
+ exitEditMode: () => void;
30
+ /** Check if component is in controlled mode */
31
+ isControlled: boolean;
32
+ }
33
+ /**
34
+ * Hook to manage the mode state (read/edit) for InlineFieldGroup.
35
+ * Supports both controlled and uncontrolled modes, following the pattern
36
+ * established by NavGroup.tsx
37
+ * @param props - Configuration for the mode hook
38
+ * @param props.mode - Controlled mode value. When provided, the component operates in controlled mode.
39
+ * @param props.defaultMode - Default mode value for uncontrolled mode.
40
+ * @param props.onModeChange - Callback fired when mode changes.
41
+ * @param props.shouldModeChange - Callback to intercept and potentially prevent mode changes.
42
+ * Return `false` to prevent the mode transition.
43
+ * Return `true` or `undefined` to allow the transition.
44
+ * @returns Mode state and handlers
45
+ */
46
+ export declare function useInlineFieldGroupMode({ mode: controlledMode, defaultMode, onModeChange, shouldModeChange, }: UseInlineFieldGroupModeProps): UseInlineFieldGroupModeReturn;
@@ -0,0 +1,27 @@
1
+ import { useState as m, useCallback as i } from "react";
2
+ function x({
3
+ mode: d,
4
+ defaultMode: c = "read",
5
+ onModeChange: s,
6
+ shouldModeChange: o
7
+ }) {
8
+ const [l, u] = m(c), t = d !== void 0, n = t ? d : l, e = i(
9
+ (r) => {
10
+ o && o(n, r) === !1 || (t || u(r), s?.(r));
11
+ },
12
+ [t, n, s, o]
13
+ ), a = i(() => {
14
+ e("edit");
15
+ }, [e]), f = i(() => {
16
+ e("read");
17
+ }, [e]);
18
+ return {
19
+ mode: n,
20
+ enterEditMode: a,
21
+ exitEditMode: f,
22
+ isControlled: t
23
+ };
24
+ }
25
+ export {
26
+ x as useInlineFieldGroupMode
27
+ };
@@ -0,0 +1,64 @@
1
+ import { PropsWithChildren, ReactNode } from 'react';
2
+ export interface InlineFieldGroupEditViewProps extends PropsWithChildren {
3
+ /**
4
+ * Optional className for custom styling
5
+ */
6
+ className?: string;
7
+ /**
8
+ * Legend text for the fieldset. Should describe the group of fields.
9
+ * This is required for accessibility but will be visually hidden.
10
+ */
11
+ legend?: ReactNode;
12
+ }
13
+ /**
14
+ * InlineFieldGroupEditView displays form fields only when the parent InlineFieldGroup is in edit mode.
15
+ * Wrap form field components in this component to show them when editing.
16
+ * The component uses a semantic `<fieldset>` with a visually hidden `<legend>` for accessibility.
17
+ * It automatically disables all fields during loading states and hides content in read mode.
18
+ * @example Basic usage with form fields
19
+ * ```tsx
20
+ * import { useTanstackUnityForm } from '@payfit/unity-components'
21
+ *
22
+ * function Example() {
23
+ * const form = useTanstackUnityForm({
24
+ * defaultValues: { email: 'john@example.com', phone: '+33123456789' }
25
+ * })
26
+ *
27
+ * return (
28
+ * <form.AppForm>
29
+ * <form.InlineFieldGroup>
30
+ * <form.InlineFieldGroupHeader title="Contact" />
31
+ * <form.InlineFieldGroupReadView>
32
+ * <DefinitionList>
33
+ * <DefinitionItem term="Email" description={form.state.values.email} />
34
+ * </DefinitionList>
35
+ * </form.InlineFieldGroupReadView>
36
+ * <form.InlineFieldGroupEditView legend="Edit contact information">
37
+ * <form.AppField name="email">
38
+ * {field => <field.TextField label="Email" isRequired />}
39
+ * </form.AppField>
40
+ * <form.AppField name="phone">
41
+ * {field => <field.PhoneNumberField label="Phone" />}
42
+ * </form.AppField>
43
+ * </form.InlineFieldGroupEditView>
44
+ * </form.InlineFieldGroup>
45
+ * </form.AppForm>
46
+ * )
47
+ * }
48
+ * ```
49
+ * @remarks
50
+ * - Must be used as a child of InlineFieldGroup
51
+ * - Set the `legend` prop to describe the group of fields for screen readers
52
+ * - The fieldset is disabled automatically when the parent's `isLoading` prop is true
53
+ * - Uses `aria-busy` to indicate loading state to assistive technologies
54
+ * - Content remains in the DOM but is hidden with `hidden` and `inert` attributes in read mode
55
+ * @see {@link InlineFieldGroupEditViewProps} for all available props
56
+ * @see {@link InlineFieldGroup} for the parent container component
57
+ * @see {@link InlineFieldGroupReadView} for the corresponding read mode component
58
+ * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/inline-field-group GitHub}
59
+ * @see Developer docs in {@link https://unity-components.payfit.io/?path=/docs/forms-reference-inlinefieldgroup--docs unity-components.payfit.io}
60
+ */
61
+ export declare function InlineFieldGroupEditView({ children, className, legend, }: InlineFieldGroupEditViewProps): import("react/jsx-runtime").JSX.Element;
62
+ export declare namespace InlineFieldGroupEditView {
63
+ var displayName: string;
64
+ }
@@ -0,0 +1,56 @@
1
+ import { jsxs as h, jsx as e } from "react/jsx-runtime";
2
+ import { useContext as g } from "react";
3
+ import { uyTv as w } from "@payfit/unity-themes";
4
+ import { useIntl as x } from "react-intl";
5
+ import { Button as v } from "../../button/Button.js";
6
+ import { InlineFieldGroupContext as I } from "../InlineFieldGroup.context.js";
7
+ const N = w({
8
+ slots: {
9
+ fieldset: "uy:border-0 uy:p-0 uy:m-0",
10
+ legend: "uy:sr-only",
11
+ fieldsContainer: "uy:flex uy:flex-col uy:gap-250",
12
+ hiddenButtons: "uy:sr-only"
13
+ }
14
+ });
15
+ function b({
16
+ children: d,
17
+ className: s,
18
+ legend: o
19
+ }) {
20
+ const l = x(), t = g(I);
21
+ if (!t)
22
+ throw new Error(
23
+ "InlineFieldGroupEditView must be used within InlineFieldGroup"
24
+ );
25
+ const { mode: r, editViewId: a, isLoading: n, editViewRef: u } = t, i = r === "edit", {
26
+ fieldset: m,
27
+ legend: f,
28
+ fieldsContainer: c,
29
+ hiddenButtons: p
30
+ } = N(), y = l.formatMessage({
31
+ id: "unity:component:inline-field-group:save",
32
+ defaultMessage: "Save"
33
+ });
34
+ return /* @__PURE__ */ h(
35
+ "fieldset",
36
+ {
37
+ ref: u,
38
+ id: a,
39
+ className: m({ className: s }),
40
+ disabled: n,
41
+ hidden: !i,
42
+ "aria-hidden": !i,
43
+ "aria-busy": n,
44
+ ...!i && { inert: "" },
45
+ children: [
46
+ /* @__PURE__ */ e("legend", { className: f(), children: o }),
47
+ /* @__PURE__ */ e("div", { className: c(), children: d }),
48
+ /* @__PURE__ */ e("div", { className: p(), children: /* @__PURE__ */ e(v, { type: "submit", variant: "primary", children: y }) })
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ b.displayName = "InlineFieldGroupEditView";
54
+ export {
55
+ b as InlineFieldGroupEditView
56
+ };
@@ -0,0 +1,95 @@
1
+ import { ReactNode } from 'react';
2
+ export interface InlineFieldGroupHeaderProps {
3
+ /**
4
+ * The title to display in the header.
5
+ * This will be used for aria-labelledby on the form element.
6
+ */
7
+ title: ReactNode;
8
+ /**
9
+ * Custom label for the edit button.
10
+ * @default "Edit" (translated)
11
+ */
12
+ editLabel?: string;
13
+ /**
14
+ * Custom label for the save button.
15
+ * @default "Save" (translated)
16
+ */
17
+ saveLabel?: string;
18
+ /**
19
+ * Custom label for the cancel button.
20
+ * @default "Cancel" (translated)
21
+ */
22
+ cancelLabel?: string;
23
+ /**
24
+ * Additional custom actions to render alongside the default buttons.
25
+ * These will be displayed between the title and the edit/save/cancel buttons.
26
+ */
27
+ customActions?: ReactNode;
28
+ /**
29
+ * Optional callback fired when the edit button is clicked.
30
+ * This is called before entering edit mode and is useful for analytics or side effects.
31
+ */
32
+ onEditPress?: () => void;
33
+ /**
34
+ * Optional callback fired when the save button is clicked.
35
+ * This is called before form submission and is useful for analytics or side effects.
36
+ * Note: Form submission is handled via the form's onSubmit configuration.
37
+ */
38
+ onSavePress?: () => void;
39
+ /**
40
+ * Optional callback fired when the cancel button is clicked.
41
+ * This is called before canceling and is useful for analytics or side effects.
42
+ * The form will be reset and edit mode exited automatically.
43
+ */
44
+ onCancelPress?: () => void;
45
+ }
46
+ /**
47
+ * InlineFieldGroupHeader renders the title and contextual action buttons for an InlineFieldGroup.
48
+ * It automatically switches between Edit button (read mode) and Save/Cancel buttons (edit mode)
49
+ * based on the parent InlineFieldGroup's current mode.
50
+ * The Save button integrates with TanStack Form and remains disabled until the form has changes.
51
+ * Cancel resets the form and returns to read mode.
52
+ * @example Basic usage
53
+ * ```tsx
54
+ * import { useTanstackUnityForm } from '@payfit/unity-components'
55
+ *
56
+ * function Example() {
57
+ * const form = useTanstackUnityForm({ defaultValues: { name: 'John' } })
58
+ *
59
+ * return (
60
+ * <form.AppForm>
61
+ * <form.InlineFieldGroup>
62
+ * <form.InlineFieldGroupHeader title="Contact Information" />
63
+ * <form.InlineFieldGroupReadView>...</form.InlineFieldGroupReadView>
64
+ * <form.InlineFieldGroupEditView legend="Edit">...</form.InlineFieldGroupEditView>
65
+ * </form.InlineFieldGroup>
66
+ * </form.AppForm>
67
+ * )
68
+ * }
69
+ * ```
70
+ * @example Custom button labels and actions
71
+ * ```tsx
72
+ * <form.InlineFieldGroupHeader
73
+ * title="Contact Information"
74
+ * editLabel="Modify"
75
+ * saveLabel="Confirm"
76
+ * cancelLabel="Discard"
77
+ * customActions={<Button onPress={handleDelete}>Delete</Button>}
78
+ * onSavePress={() => trackAnalytics('save_clicked')}
79
+ * />
80
+ * ```
81
+ * @remarks
82
+ * - Must be used as a child of InlineFieldGroup
83
+ * - The title serves as the accessible label for the form via `aria-labelledby`
84
+ * - The Edit button uses `aria-expanded` and `aria-controls` for accessibility
85
+ * - Use `customActions` to add buttons that appear in both read and edit modes
86
+ * - Use `onEditPress`, `onSavePress`, `onCancelPress` for analytics or side effects
87
+ * @see {@link InlineFieldGroupHeaderProps} for all available props
88
+ * @see {@link InlineFieldGroup} for the parent container component
89
+ * @see Source code in {@link https://github.com/PayFit/hr-apps/tree/master/libs/shared/unity/components/src/components/inline-field-group GitHub}
90
+ * @see Developer docs in {@link https://unity-components.payfit.io/?path=/docs/forms-reference-inlinefieldgroup--docs unity-components.payfit.io}
91
+ */
92
+ export declare function InlineFieldGroupHeader({ title, editLabel, saveLabel, cancelLabel, customActions, onEditPress, onSavePress, onCancelPress, }: InlineFieldGroupHeaderProps): import("react/jsx-runtime").JSX.Element;
93
+ export declare namespace InlineFieldGroupHeader {
94
+ var displayName: string;
95
+ }