@ostack.tech/ui-kform 0.3.4 → 0.4.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.
@@ -1,11 +1,9 @@
1
- import { Path } from '@ostack.tech/kform';
2
1
  import { ErrorBoundary, TabContent } from '@ostack.tech/ui';
3
2
  import { ComponentPropsWithoutRef, ComponentPropsWithRef, ReactNode } from 'react';
4
3
  import { IssueMessagesByCode } from '../IssueMessages';
4
+ import { AnnexObject } from './Annexes.tsx';
5
5
  /** Properties of the annex component. */
6
- export interface AnnexProps extends Omit<ComponentPropsWithoutRef<typeof TabContent>, "value" | "children"> {
7
- /** Annex path. This should match the path of the annex provided to `Annexes`. */
8
- path?: string | Path;
6
+ export interface AnnexProps extends AnnexObject, Omit<ComponentPropsWithoutRef<typeof TabContent>, "value" | "title" | "children"> {
9
7
  /** Sets the annex as disabled. */
10
8
  disabled?: boolean;
11
9
  /** Sets the annex as read-only. */
@@ -0,0 +1,7 @@
1
+ import { ResolvedAnnexObject } from './AnnexesContext.ts';
2
+ /** Properties of the `AnnexRegistrar` component. */
3
+ export interface AnnexRegistrarProps extends ResolvedAnnexObject {
4
+ index?: number;
5
+ }
6
+ /** Component used to register a form annex. */
7
+ export declare function AnnexRegistrar({ path, title, subtitle, description, issuesPanelLabel, itemTitle, itemIssuesPanelLabel, index, documentTitle, }: AnnexRegistrarProps): null;
@@ -5,8 +5,11 @@ import { ComponentPropsWithoutRef, ReactNode } from 'react';
5
5
  export interface AnnexesProps extends Omit<ComponentPropsWithoutRef<typeof Tabs>, "defaultValue" | "value" | "onValueChange"> {
6
6
  /** Base path for all declared annexes. */
7
7
  path?: string | Path;
8
- /** List of all annexes. */
9
- annexes: AnnexObject[];
8
+ /**
9
+ * List of all annexes. When not provided, the list of annexes is obtained
10
+ * from the direct children `Annex` components.
11
+ */
12
+ annexes?: AnnexObject[];
10
13
  /** Default active annex. */
11
14
  defaultActiveAnnex?: string | Path;
12
15
  /** Controlled active annex. */
@@ -38,9 +41,9 @@ export interface AnnexObject<T = any> {
38
41
  * the elements of a collection should be counted as annexes. Otherwise, the
39
42
  * path may contain no other wildcards.
40
43
  */
41
- path: string | Path;
44
+ path?: string | Path;
42
45
  /** Annex's title. */
43
- title: ReactNode | ((value: T) => ReactNode);
46
+ title?: ReactNode | ((value: T) => ReactNode);
44
47
  /** Annex's subtitle. */
45
48
  subtitle?: ReactNode | ((value: T, index?: number) => ReactNode);
46
49
  /** Annex's description. */
@@ -0,0 +1,6 @@
1
+ import { ResolvedAnnexObject } from './AnnexesContext.ts';
2
+ /** Properties of the `RepetitiveAnnexRegistrar` component. */
3
+ export interface RepetitiveAnnexRegistrarProps extends ResolvedAnnexObject {
4
+ }
5
+ /** Component used to register a repetitive form annex. */
6
+ export declare function RepetitiveAnnexRegistrar({ path, maxAnnexes, ...annexProps }: RepetitiveAnnexRegistrarProps): import("react/jsx-runtime").JSX.Element[] | undefined;
@@ -1,3 +1,5 @@
1
1
  export * from './Annex.tsx';
2
2
  export * from './Annexes.tsx';
3
3
  export * from './AnnexesManager.tsx';
4
+ export { AnnexRegistrar } from './AnnexRegistrar.tsx';
5
+ export { RepetitiveAnnexRegistrar } from './RepetitiveAnnexRegistrar.tsx';
@@ -2,6 +2,7 @@ import { AbsolutePath, Path, Schema, SchemaKt } from '@ostack.tech/kform';
2
2
  import { Controller, FormOptions } from '@ostack.tech/kform-react';
3
3
  import { Responsive, Root } from '@ostack.tech/ui';
4
4
  import { ComponentPropsWithoutRef, ReactNode, Ref } from 'react';
5
+ import { OnActivePathChangeNavigationOptions } from '../../providers/ActivePathProvider';
5
6
  import { LocalizationObject } from '../../providers/LocalizationProvider';
6
7
  import { IssueMessagesByCode } from '../IssueMessages';
7
8
  /** Mode of displaying issue messages. */
@@ -83,6 +84,23 @@ export type FormAppProps<T = any> = Pick<ComponentPropsWithoutRef<typeof Root>,
83
84
  * @default false
84
85
  */
85
86
  displayIssueCodes?: boolean;
87
+ /**
88
+ * When provided, the form app's active path will be controlled by a URL
89
+ * search parameter with the provided name.
90
+ */
91
+ activePathSearchParam?: string;
92
+ /** Uncontrolled default active path to use. */
93
+ defaultActivePath?: string | Path;
94
+ /** Controlled active path to use. */
95
+ activePath?: string | Path;
96
+ /**
97
+ * Callback called whenever the active path changes.
98
+ *
99
+ * @param activePath New active path.
100
+ * @param options Navigation options to use when controlling the active path
101
+ * via the browser's URL.
102
+ */
103
+ onActivePathChange?: (activePath: AbsolutePath, options: OnActivePathChangeNavigationOptions) => void;
86
104
  /**
87
105
  * Function called when a form path is focused.
88
106
  *
@@ -201,6 +219,23 @@ export declare const FormApp: import('react').ForwardRefExoticComponent<Pick<Omi
201
219
  * @default false
202
220
  */
203
221
  displayIssueCodes?: boolean;
222
+ /**
223
+ * When provided, the form app's active path will be controlled by a URL
224
+ * search parameter with the provided name.
225
+ */
226
+ activePathSearchParam?: string;
227
+ /** Uncontrolled default active path to use. */
228
+ defaultActivePath?: string | Path;
229
+ /** Controlled active path to use. */
230
+ activePath?: string | Path;
231
+ /**
232
+ * Callback called whenever the active path changes.
233
+ *
234
+ * @param activePath New active path.
235
+ * @param options Navigation options to use when controlling the active path
236
+ * via the browser's URL.
237
+ */
238
+ onActivePathChange?: (activePath: AbsolutePath, options: OnActivePathChangeNavigationOptions) => void;
204
239
  /**
205
240
  * Function called when a form path is focused.
206
241
  *
@@ -22,7 +22,7 @@ export interface FormAppState<T> {
22
22
  leftSidebarWidth: number;
23
23
  bottomPanelHeight: number;
24
24
  startIssuesNavigation?: () => void;
25
- activePath: AbsolutePath;
25
+ latestInteraction: AbsolutePath;
26
26
  registeredControllers: [PathMultimap<Controller>];
27
27
  registeredIssueMessages: [
28
28
  PathMultimap<{
@@ -50,7 +50,7 @@ export interface FormAppActions {
50
50
  resetFocus: () => void;
51
51
  registerController: (path: AbsolutePath, controller?: Controller<any> | null) => (() => void) | void;
52
52
  isRegistered: (path: AbsolutePath) => boolean;
53
- setActivePath: (path: AbsolutePath) => void;
53
+ setLatestInteraction: (path: AbsolutePath) => void;
54
54
  registerIssueMessages: (basePath: AbsolutePath, issueMessages?: Record<string, IssueMessagesByCode>, priority?: number) => (() => void) | void;
55
55
  getRegisteredIssueMessage: (path: AbsolutePath, code: string) => IssueMessageValue | null;
56
56
  registerLabel: (path: AbsolutePath, label: ReactNode, priority?: number) => (() => void) | void;
@@ -118,8 +118,8 @@ export declare function useSetLeftSidebarWidth(): (width?: number) => void;
118
118
  */
119
119
  export declare function useSetBottomPanelHeight(): (height?: number) => void;
120
120
  /**
121
- * Returns the current active path of the form app and a function that can be
122
- * used to set it, ala `useState`.
121
+ * Returns the current issues panel path of the form app and a function that can
122
+ * be used to set it, ala `useState`.
123
123
  */
124
124
  export declare function useIssuesPanelPath(): [
125
125
  AbsolutePath | null,
@@ -136,10 +136,10 @@ export declare function useResetFocus(): FormAppActions["resetFocus"];
136
136
  export declare function useRegisterController(controller: Controller<any>): void;
137
137
  /** Hook to check whether there is a registered controller for the provided path. */
138
138
  export declare function useIsRegistered(path?: AbsolutePath | null): boolean;
139
- /** Hook exposing the active path. */
140
- export declare function useActivePath(): AbsolutePath;
141
- /** Hook exposing a function to set the active path. */
142
- export declare function useSetActivePath(): FormAppActions["setActivePath"];
139
+ /** Hook exposing the latest path that the user has interacted with. */
140
+ export declare function useLatestInteraction(): AbsolutePath;
141
+ /** Hook exposing a function to set the latest path the user has interacted with. */
142
+ export declare function useSetLatestInteraction(): FormAppActions["setLatestInteraction"];
143
143
  /** Hook used to register issue messages within the form app. */
144
144
  export declare function useRegisterIssueMessages(path: AbsolutePath | null | undefined, issueMessages?: Record<string, IssueMessagesByCode>, priority?: number): void;
145
145
  /** Hook used to get the issue message value for the provided path and code. */
@@ -159,7 +159,7 @@ export declare function useStartIssuesNavigation(): FormAppActions["startIssuesN
159
159
  /** Options available to the {@link useOnPathFocus} hook. */
160
160
  export interface UseOnFocusedPathChangeOptions {
161
161
  /**
162
- * Whether to run the callback immediately with the current active path.
162
+ * Whether to run the callback immediately with the current focused path.
163
163
  *
164
164
  * @default true
165
165
  */
@@ -1,15 +1,10 @@
1
- import { Path } from '@ostack.tech/kform';
2
1
  import { Container, ErrorBoundary, IconButton, Popover, PopoverContent, Stack } from '@ostack.tech/ui';
3
2
  import { ComponentPropsWithoutRef, ComponentPropsWithRef, ReactNode } from 'react';
4
3
  import { IssueMessages, IssueMessagesByCode } from '../IssueMessages';
5
4
  import { IssuesPopover } from '../IssuesPopover';
5
+ import { FormPageObject } from './FormPages.tsx';
6
6
  /** Properties of the form page component. */
7
- export interface FormPageProps extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
8
- /**
9
- * Form page path. This should match the path of the page provided to
10
- * `FormPages`.
11
- */
12
- path?: string | Path;
7
+ export interface FormPageProps extends FormPageObject, Omit<ComponentPropsWithoutRef<"div">, "title" | "children"> {
13
8
  /** Sets the form page as disabled. */
14
9
  disabled?: boolean;
15
10
  /** Sets the form page as read-only. */
@@ -0,0 +1,6 @@
1
+ import { ResolvedFormPageObject } from './FormPagesContext.ts';
2
+ /** Properties of the `FormPageRegistrar` component. */
3
+ export interface FormPageRegistrarProps extends ResolvedFormPageObject {
4
+ }
5
+ /** Component used to register a form page. */
6
+ export declare function FormPageRegistrar({ path, title, documentTitle, code, issuesPanelLabel, }: FormPageRegistrarProps): null;
@@ -4,8 +4,11 @@ import { ComponentPropsWithoutRef, ReactNode } from 'react';
4
4
  export interface FormPagesProps extends ComponentPropsWithoutRef<"div"> {
5
5
  /** Base path for all declared form pages. */
6
6
  path?: string | Path;
7
- /** List of all form pages. */
8
- pages: FormPageObject[];
7
+ /**
8
+ * List of all form pages. When not provided, the list of pages is obtained
9
+ * from the direct children `FormPage` components.
10
+ */
11
+ pages?: FormPageObject[];
9
12
  /** Default active form page. */
10
13
  defaultActivePage?: string | Path;
11
14
  /** Controlled active form page. */
@@ -23,7 +26,7 @@ export interface FormPageObject<T = any> {
23
26
  /** Form page path. */
24
27
  path?: string | Path;
25
28
  /** Form page's title */
26
- title: ReactNode | ((value: T) => ReactNode);
29
+ title?: ReactNode | ((value: T) => ReactNode);
27
30
  /**
28
31
  * Title of the form page as a string to display in the document's title.
29
32
  *
@@ -1,3 +1,4 @@
1
1
  export * from './FormPage.tsx';
2
+ export { FormPageRegistrar } from './FormPageRegistrar.tsx';
2
3
  export * from './FormPages.tsx';
3
4
  export * from './FormPagesNavigation.tsx';
@@ -0,0 +1,6 @@
1
+ import { ResolvedFormStepObject } from './FormStepperContext.ts';
2
+ /** Properties of the `FormStepRegistrar` component. */
3
+ export interface FormStepRegistrarProps extends ResolvedFormStepObject {
4
+ }
5
+ /** Component used to register a form step. */
6
+ export declare function FormStepRegistrar({ index, path, title, documentTitle, issuesPanelLabel, }: FormStepRegistrarProps): null;
@@ -45,7 +45,7 @@ export declare const FormStepperContext: import('react').Context<(Omit<import('z
45
45
  } | undefined): () => void;
46
46
  };
47
47
  }) | null>;
48
- /** Options used to create the form stepped context. */
48
+ /** Options used to create the form stepper context. */
49
49
  export interface UseCreateFormStepperContextOptions extends Pick<FormStepperProps, "defaultActiveStep" | "activeStep" | "onActiveStepChange" | "onStepValidation" | "skipStepValidationOnForwardNavigation" | "allowForwardNavigationOnError" | "preventFocusOnError"> {
50
50
  formManager: FormManager;
51
51
  basePath: AbsolutePath;
@@ -1,3 +1,4 @@
1
1
  export * from './FormStepContent.tsx';
2
2
  export * from './FormStepList.tsx';
3
3
  export * from './FormStepper.tsx';
4
+ export { FormStepRegistrar } from './FormStepRegistrar.tsx';
@@ -25,6 +25,7 @@ export * from './components/TableControl';
25
25
  export * from './components/TextControl';
26
26
  export * from './components/TopBar';
27
27
  export * from './components/ValidateAction';
28
+ export * from './providers/ActivePathProvider';
28
29
  export * from './providers/LocalizationProvider';
29
30
  export * from './providers/PrefixSuffixProvider';
30
31
  export * from './utils/displayStatusConversions.ts';
@@ -0,0 +1,10 @@
1
+ import { AbsolutePath } from '@ostack.tech/kform';
2
+ /** Value of the active path context. */
3
+ export interface ActivePathContextValue {
4
+ activePath: AbsolutePath;
5
+ onActivePathChange: (activePath: AbsolutePath | string | null) => void;
6
+ }
7
+ /** Active path context. */
8
+ export declare const ActivePathContext: import('react').Context<ActivePathContextValue | null>;
9
+ /** Hook providing access to the active path context. */
10
+ export declare function useActivePathContext(): ActivePathContextValue;
@@ -0,0 +1,28 @@
1
+ import { AbsolutePath, Path } from '@ostack.tech/kform';
2
+ import { ReactNode } from 'react';
3
+ /**
4
+ * Navigation options to use when controlling the active path via the browser's
5
+ * URL.
6
+ */
7
+ export interface OnActivePathChangeNavigationOptions {
8
+ /** Whether to replace the current history entry. */
9
+ replace: boolean;
10
+ }
11
+ /** Properties of the active path provider. */
12
+ export interface ActivePathProviderProps {
13
+ /** Uncontrolled default active path to use. */
14
+ defaultActivePath?: string | Path;
15
+ /** Controlled active path to use. */
16
+ activePath?: string | Path;
17
+ /**
18
+ * Callback called whenever the active path is changed.
19
+ *
20
+ * @param activePath New active path.
21
+ * @param options Navigation options to use when controlling the active path
22
+ * via the browser's URL.
23
+ */
24
+ onActivePathChange?: (activePath: AbsolutePath, options: OnActivePathChangeNavigationOptions) => void;
25
+ children?: ReactNode;
26
+ }
27
+ /** Provider which controls the active path in a section of a form. */
28
+ export declare function ActivePathProvider({ defaultActivePath, activePath: controlledActivePath, onActivePathChange, children, }: ActivePathProviderProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export * from './ActivePathContext.ts';
2
+ export * from './ActivePathProvider.tsx';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ostack.tech/ui-kform",
3
3
  "description": "Integration of ostack/UI with ostack/KForm.",
4
- "version": "0.3.4",
4
+ "version": "0.4.1",
5
5
  "homepage": "https://ui.ostack.tech/",
6
6
  "author": {
7
7
  "name": "Opensoft",
@@ -52,7 +52,7 @@
52
52
  "@fortawesome/free-solid-svg-icons": "^6.2.0 || ^7.0.0",
53
53
  "@ostack.tech/kform": "~0.31.0",
54
54
  "@ostack.tech/kform-react": "~0.31.0",
55
- "@ostack.tech/ui": "~0.3.4",
55
+ "@ostack.tech/ui": "~0.4.1",
56
56
  "@types/react": "^18.0.0 || ^19.0.0",
57
57
  "@types/react-dom": "^18.0.0 || ^19.0.0",
58
58
  "date-fns": "^4.1.0",