@ostack.tech/ui-kform 0.1.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 (144) hide show
  1. package/README.md +3 -0
  2. package/dist/ostack-ui-kform.cjs +7534 -0
  3. package/dist/ostack-ui-kform.cjs.map +1 -0
  4. package/dist/ostack-ui-kform.css +858 -0
  5. package/dist/ostack-ui-kform.css.map +1 -0
  6. package/dist/ostack-ui-kform.js +7518 -0
  7. package/dist/ostack-ui-kform.js.map +1 -0
  8. package/dist/types/components/Annexes/Annex.d.ts +46 -0
  9. package/dist/types/components/Annexes/AnnexTab.d.ts +5 -0
  10. package/dist/types/components/Annexes/Annexes.d.ts +95 -0
  11. package/dist/types/components/Annexes/AnnexesContext.d.ts +87 -0
  12. package/dist/types/components/Annexes/AnnexesManager.d.ts +47 -0
  13. package/dist/types/components/Annexes/AnnexesMenu.d.ts +10 -0
  14. package/dist/types/components/Annexes/AnnexesTabList.d.ts +8 -0
  15. package/dist/types/components/Annexes/index.d.ts +3 -0
  16. package/dist/types/components/CheckboxControl/CheckboxControl.d.ts +48 -0
  17. package/dist/types/components/CheckboxControl/index.d.ts +1 -0
  18. package/dist/types/components/CheckboxGroupControl/CheckboxGroupControl.d.ts +63 -0
  19. package/dist/types/components/CheckboxGroupControl/index.d.ts +1 -0
  20. package/dist/types/components/ControlField/ControlField.d.ts +50 -0
  21. package/dist/types/components/ControlField/ControlFieldContext.d.ts +33 -0
  22. package/dist/types/components/ControlField/index.d.ts +2 -0
  23. package/dist/types/components/DateControl/DateControl.d.ts +45 -0
  24. package/dist/types/components/DateControl/index.d.ts +1 -0
  25. package/dist/types/components/DateRangeControl/DateRangeControl.d.ts +79 -0
  26. package/dist/types/components/DateRangeControl/index.d.ts +1 -0
  27. package/dist/types/components/FileControl/FileControl.d.ts +68 -0
  28. package/dist/types/components/FileControl/index.d.ts +1 -0
  29. package/dist/types/components/FormApp/FormApp.d.ts +210 -0
  30. package/dist/types/components/FormApp/FormAppContext.d.ts +181 -0
  31. package/dist/types/components/FormApp/FormAppIssueMessages.d.ts +45 -0
  32. package/dist/types/components/FormApp/FormAppStatus.d.ts +23 -0
  33. package/dist/types/components/FormApp/index.d.ts +4 -0
  34. package/dist/types/components/FormPages/FormPage.d.ts +86 -0
  35. package/dist/types/components/FormPages/FormPageHeader.d.ts +7 -0
  36. package/dist/types/components/FormPages/FormPageSidebarItem.d.ts +6 -0
  37. package/dist/types/components/FormPages/FormPages.d.ts +40 -0
  38. package/dist/types/components/FormPages/FormPagesContext.d.ts +67 -0
  39. package/dist/types/components/FormPages/FormPagesNavigation.d.ts +12 -0
  40. package/dist/types/components/FormPages/FormPagesSelect.d.ts +7 -0
  41. package/dist/types/components/FormPages/FormPagesSelectOption.d.ts +6 -0
  42. package/dist/types/components/FormPages/FormPagesSidebar.d.ts +6 -0
  43. package/dist/types/components/FormPages/index.d.ts +3 -0
  44. package/dist/types/components/FormStepper/FormStep.d.ts +8 -0
  45. package/dist/types/components/FormStepper/FormStepContent.d.ts +20 -0
  46. package/dist/types/components/FormStepper/FormStepList.d.ts +7 -0
  47. package/dist/types/components/FormStepper/FormStepper.d.ts +71 -0
  48. package/dist/types/components/FormStepper/FormStepperContext.d.ts +65 -0
  49. package/dist/types/components/FormStepper/index.d.ts +3 -0
  50. package/dist/types/components/IssueAlert/IssueAlert.d.ts +13 -0
  51. package/dist/types/components/IssueAlert/index.d.ts +1 -0
  52. package/dist/types/components/IssueMessage/IssueMessage.d.ts +14 -0
  53. package/dist/types/components/IssueMessage/index.d.ts +1 -0
  54. package/dist/types/components/IssueMessages/IssueMessages.d.ts +70 -0
  55. package/dist/types/components/IssueMessages/index.d.ts +1 -0
  56. package/dist/types/components/IssuesPanel/IssuesPanel.d.ts +106 -0
  57. package/dist/types/components/IssuesPanel/IssuesPanelControls.d.ts +19 -0
  58. package/dist/types/components/IssuesPanel/IssuesPanelMessagesCard.d.ts +13 -0
  59. package/dist/types/components/IssuesPanel/IssuesPanelSummaryCard.d.ts +9 -0
  60. package/dist/types/components/IssuesPanel/index.d.ts +1 -0
  61. package/dist/types/components/IssuesPopover/IssuesPopover.d.ts +15 -0
  62. package/dist/types/components/IssuesPopover/index.d.ts +1 -0
  63. package/dist/types/components/LoadAction/LoadAction.d.ts +22 -0
  64. package/dist/types/components/LoadAction/index.d.ts +1 -0
  65. package/dist/types/components/NumericControl/NumericControl.d.ts +45 -0
  66. package/dist/types/components/NumericControl/index.d.ts +1 -0
  67. package/dist/types/components/PathLink/PathLink.d.ts +16 -0
  68. package/dist/types/components/PathLink/index.d.ts +1 -0
  69. package/dist/types/components/RadioGroupControl/RadioGroupControl.d.ts +56 -0
  70. package/dist/types/components/RadioGroupControl/index.d.ts +1 -0
  71. package/dist/types/components/SaveAction/SaveAction.d.ts +51 -0
  72. package/dist/types/components/SaveAction/index.d.ts +1 -0
  73. package/dist/types/components/SelectControl/SelectControl.d.ts +48 -0
  74. package/dist/types/components/SelectControl/index.d.ts +1 -0
  75. package/dist/types/components/SelectMultipleControl/SelectMultipleControl.d.ts +55 -0
  76. package/dist/types/components/SelectMultipleControl/index.d.ts +1 -0
  77. package/dist/types/components/SubmitAction/SubmitAction.d.ts +94 -0
  78. package/dist/types/components/SubmitAction/index.d.ts +1 -0
  79. package/dist/types/components/TableControl/TableControl.d.ts +64 -0
  80. package/dist/types/components/TableControl/TableControlAddRowTrigger.d.ts +25 -0
  81. package/dist/types/components/TableControl/TableControlApi.d.ts +25 -0
  82. package/dist/types/components/TableControl/TableControlCell.d.ts +7 -0
  83. package/dist/types/components/TableControl/TableControlColumn.d.ts +58 -0
  84. package/dist/types/components/TableControl/TableControlContent.d.ts +7 -0
  85. package/dist/types/components/TableControl/TableControlContext.d.ts +26 -0
  86. package/dist/types/components/TableControl/TableControlPagination.d.ts +2 -0
  87. package/dist/types/components/TableControl/TableControlRemoveRowTrigger.d.ts +61 -0
  88. package/dist/types/components/TableControl/TableControlRow.d.ts +7 -0
  89. package/dist/types/components/TableControl/TableControlRowsPerPage.d.ts +2 -0
  90. package/dist/types/components/TableControl/index.d.ts +8 -0
  91. package/dist/types/components/TextControl/TextControl.d.ts +66 -0
  92. package/dist/types/components/TextControl/index.d.ts +1 -0
  93. package/dist/types/components/TopBar/TopBar.d.ts +6 -0
  94. package/dist/types/components/TopBar/TopBarActions.d.ts +7 -0
  95. package/dist/types/components/TopBar/index.d.ts +2 -0
  96. package/dist/types/components/ValidateAction/ValidateAction.d.ts +21 -0
  97. package/dist/types/components/ValidateAction/index.d.ts +1 -0
  98. package/dist/types/index.d.ts +36 -0
  99. package/dist/types/locale/LocalizationObject.d.ts +34 -0
  100. package/dist/types/locale/defaultLocale.d.ts +3 -0
  101. package/dist/types/locale/en-GB.d.ts +3 -0
  102. package/dist/types/locale/en-US.d.ts +3 -0
  103. package/dist/types/locale/en.d.ts +3 -0
  104. package/dist/types/locale/fr-FR.d.ts +3 -0
  105. package/dist/types/locale/index.d.ts +6 -0
  106. package/dist/types/locale/pt-PT.d.ts +3 -0
  107. package/dist/types/providers/LocalizationProvider/LocalizationContext.d.ts +6 -0
  108. package/dist/types/providers/LocalizationProvider/LocalizationProvider.d.ts +10 -0
  109. package/dist/types/providers/LocalizationProvider/index.d.ts +3 -0
  110. package/dist/types/providers/LocalizationProvider/useLocale.d.ts +3 -0
  111. package/dist/types/providers/PrefixSuffixProvider/PrefixSuffixContext.d.ts +5 -0
  112. package/dist/types/providers/PrefixSuffixProvider/PrefixSuffixProvider.d.ts +9 -0
  113. package/dist/types/providers/PrefixSuffixProvider/index.d.ts +3 -0
  114. package/dist/types/providers/PrefixSuffixProvider/usePrefix.d.ts +6 -0
  115. package/dist/types/utils/dateRestrictions.d.ts +6 -0
  116. package/dist/types/utils/displayStatusConversions.d.ts +6 -0
  117. package/dist/types/utils/mostSpecificPath.d.ts +13 -0
  118. package/dist/types/utils/options.d.ts +18 -0
  119. package/dist/types/utils/pathSpecificity.d.ts +18 -0
  120. package/dist/types/utils/selectionTransformations.d.ts +32 -0
  121. package/dist/types/utils/useControlAutofocus.d.ts +32 -0
  122. package/dist/types/utils/useControlIssues.d.ts +27 -0
  123. package/dist/types/utils/useEqualityFn.d.ts +1 -0
  124. package/dist/types/utils/useFormLoader.d.ts +83 -0
  125. package/dist/types/utils/useFormSaver.d.ts +96 -0
  126. package/dist/types/utils/useFormValidator.d.ts +28 -0
  127. package/dist/types/utils/useRegisterControl.d.ts +24 -0
  128. package/dist/types/utils/useReportValidationFailures.d.ts +5 -0
  129. package/dist/types/utils/useTemporalStringTransformer.d.ts +21 -0
  130. package/package.json +70 -0
  131. package/scss/_utils.scss +6 -0
  132. package/scss/components/Annexes/_Annexes-variables.scss +17 -0
  133. package/scss/components/Annexes/_Annexes.scss +234 -0
  134. package/scss/components/FileControl/_FileControl.scss +52 -0
  135. package/scss/components/FormApp/_FormApp.scss +67 -0
  136. package/scss/components/FormPages/_FormPages-variables.scss +62 -0
  137. package/scss/components/FormPages/_FormPages.scss +288 -0
  138. package/scss/components/IssueMessages/_IssueMessages.scss +13 -0
  139. package/scss/components/IssuesPanel/_IssuesPanel-variables.scss +82 -0
  140. package/scss/components/IssuesPanel/_IssuesPanel.scss +196 -0
  141. package/scss/components/TableControl/_TableControl.scss +21 -0
  142. package/scss/components/TopBar/_TopBar.scss +52 -0
  143. package/scss/index.scss +11 -0
  144. package/scss/scss/_base-variables.scss +5 -0
@@ -0,0 +1,68 @@
1
+ import { type File as KFormFile, type Path } from "@ostack.tech/kform";
2
+ import { type FileInputController, type FileInputOptions } from "@ostack.tech/kform-react";
3
+ import { Input } from "@ostack.tech/ui";
4
+ import * as React from "react";
5
+ import { type IssueMessages, type IssueMessagesByCode } from "../IssueMessages";
6
+ /**
7
+ * File control's interaction with the selected file:
8
+ *
9
+ * - `view`: A button is added which opens a dialog to view and optionally
10
+ * download the file. A fallback alert is displayed when the file cannot be
11
+ * viewed.
12
+ * - `download`: A button is added to download the file. Useful if you know that
13
+ * the accepted file types aren't viewable in the browser.
14
+ * - `none`: No interaction with the selected file is added.
15
+ */
16
+ export type FileControlFileInteraction = "view" | "download" | "none";
17
+ /** Properties of the file control component. */
18
+ export interface FileControlProps<T extends KFormFile | null = KFormFile | null> extends Omit<FileInputOptions<T, FileList, React.ComponentRef<typeof Input>>, "enabled" | "formatFromFileList" | "parseToFileList">, Omit<React.ComponentPropsWithoutRef<typeof Input>, "type" | "multiple" | "defaultValue" | "value" | "onValueChange" | "status" | "align"> {
19
+ /** Path to the value. */
20
+ path?: string | Path;
21
+ /**
22
+ * Issue messages of this control.
23
+ *
24
+ * Mapping from an issue's code to its message.
25
+ */
26
+ issueMessages?: IssueMessagesByCode;
27
+ /**
28
+ * Label to use in the issues panel when displaying issues associated with
29
+ * this field.
30
+ *
31
+ * This label has priority over the field's `ControlLabel`.
32
+ */
33
+ issuesPanelLabel?: React.ReactNode;
34
+ /**
35
+ * Whether to display the issues associated with this control.
36
+ *
37
+ * @default true
38
+ */
39
+ displayIssues?: boolean;
40
+ /**
41
+ * Whether to prevent the auto-focusing behaviour that causes this control to
42
+ * be focused when the form app's `focus` is called with this control's path.
43
+ *
44
+ * Preventing this behaviour is useful when multiple controls for the same
45
+ * path are rendered at once, and only one of them should be focused.
46
+ *
47
+ * @default false
48
+ */
49
+ preventAutoFocus?: boolean;
50
+ /** Reference to the control's API. */
51
+ apiRef?: React.Ref<FileInputController<T, FileList, React.ComponentRef<typeof Input>> | undefined>;
52
+ /**
53
+ * Type of interaction with the selected file.
54
+ *
55
+ * @default view
56
+ */
57
+ fileInteraction?: FileControlFileInteraction;
58
+ /** Label of the button used to open the file viewer. */
59
+ viewFileButtonLabel?: React.ReactNode;
60
+ /** Label of the button used to download the file. */
61
+ downloadFileButtonLabel?: React.ReactNode;
62
+ /** Text displayed when the file cannot be viewed. */
63
+ fallbackText?: React.ReactNode;
64
+ /** Properties to pass to the `IssueMessages` component. */
65
+ issueMessagesProps?: Omit<React.ComponentPropsWithRef<typeof IssueMessages>, "path" | "issues" | "messages" | "unwrapped">;
66
+ }
67
+ /** File control component supporting (possibly nullable) file schemas. */
68
+ export declare const FileControl: React.ForwardRefExoticComponent<FileControlProps<KFormFile | null> & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1 @@
1
+ export * from "./FileControl.tsx";
@@ -0,0 +1,210 @@
1
+ import { AbsolutePath, type Path, type Schema, type SchemaKt } from "@ostack.tech/kform";
2
+ import { type Controller, type FormOptions } from "@ostack.tech/kform-react";
3
+ import { type Responsive, Root } from "@ostack.tech/ui";
4
+ import * as React from "react";
5
+ import { type LocalizationObject } from "../../locale/LocalizationObject.ts";
6
+ import { type IssueMessagesByCode } from "../IssueMessages";
7
+ /** Mode of displaying issue messages. */
8
+ export type IssuesDisplayMode = "inline" | "panel";
9
+ /** Properties of the form app component. */
10
+ export type FormAppProps<T = any> = Pick<React.ComponentPropsWithoutRef<typeof Root>, "enableErrorReporting" | "reportError" | "errorReportingUrl" | "errorReportingMethod" | "encodeErrorReport" | "encodedErrorReportMimeType" | "errorReportingOptions" | "baseDocumentTitle" | "documentTitleBaseSeparator" | "documentTitleBreadcrumbsSeparator" | "portalsContainer" | "tooltipsDelayDuration" | "tooltipsSkipDelayDuration" | "disableTooltipsHoverableContent" | "toastsLabel" | "toastsDuration" | "toastsSwipeDirection" | "toastsSwipeThreshold" | "toastViewportHotkey" | "toastViewportLabel" | "toastViewportProps" | "errorBoundaryProps"> & FormOptions<T> & Omit<React.ComponentPropsWithoutRef<"form">, "onSubmit" | "onReset"> & {
11
+ /** Schema of the form. */
12
+ schema: Schema<T> | SchemaKt;
13
+ /**
14
+ * Label to use in the issues panel when displaying issues associated with
15
+ * the form app.
16
+ */
17
+ issuesPanelLabel?: React.ReactNode;
18
+ /** Whether to disable the whole form. */
19
+ disabled?: boolean;
20
+ /** Whether to set the whole form as read-only. */
21
+ readOnly?: boolean;
22
+ /**
23
+ * Custom suffix to add to the ostack/UI's prefix when prefixing all
24
+ * component classes, styles, _etc._
25
+ *
26
+ * This prefix-suffix should match the `$prefix-suffix` SCSS variable.
27
+ */
28
+ prefixSuffix?: string;
29
+ /**
30
+ * Form app locale.
31
+ *
32
+ * @default defaultLocale
33
+ */
34
+ locale?: LocalizationObject;
35
+ /**
36
+ * Mapping of issue messages from the path of the field with issues to the
37
+ * issue messages of said field (which are themselves grouped by their
38
+ * code).
39
+ *
40
+ * Provided paths may contain wildcards, which will have a lower priority
41
+ * when matched against.
42
+ *
43
+ * These messages are used by the `IssueMessages` component.
44
+ *
45
+ * **Note:** Changes to `issueMessages` are handled correctly, but are not
46
+ * efficient. Please make sure that the identity of the provided value
47
+ * doesn't change at every render.
48
+ *
49
+ * Example value:
50
+ *
51
+ * ```tsx
52
+ * {
53
+ * "/**": {
54
+ * "valueMissing": "Field is required."
55
+ * },
56
+ * "/my/field": {
57
+ * "valueMissing": "My field cannot be left empty!",
58
+ * "someOtherError": "Text of the other error."
59
+ * }
60
+ * }
61
+ * ```
62
+ */
63
+ issueMessages?: Record<string, IssueMessagesByCode>;
64
+ /**
65
+ * Mode of displaying issues:
66
+ *
67
+ * - `inline` mode dispays issue messages near the component containing the
68
+ * issues. In this mode the bottom issues panel only functions as an aid
69
+ * for navigating issues.
70
+ * - `panel` mode displays issue messages within the bottom issues panel.
71
+ *
72
+ * @default inline
73
+ */
74
+ issuesDisplayMode?: IssuesDisplayMode;
75
+ /**
76
+ * Global setting which specifies whether issue codes should be added to
77
+ * each issue message.
78
+ *
79
+ * @default false
80
+ */
81
+ displayIssueCodes?: boolean;
82
+ /**
83
+ * Function called when a form path is focused.
84
+ *
85
+ * @param path Focused path.
86
+ */
87
+ onPathFocus?: (path: AbsolutePath) => void;
88
+ /**
89
+ * Minimum height of the form app. Values should **not** be percentages.
90
+ *
91
+ * @default "100dvh"
92
+ */
93
+ minHeight?: Responsive<number | string>;
94
+ /** Reference to the form app's API. */
95
+ apiRef?: React.Ref<FormAppApi<T> | undefined>;
96
+ };
97
+ /** Imperative form app API. */
98
+ export type FormAppApi<T = unknown> = Controller<T> & {
99
+ /**
100
+ * Focuses the form element at the provided path.
101
+ *
102
+ * @param path Path of element to focus.
103
+ */
104
+ focus: (path: string | Path) => void;
105
+ /**
106
+ * Starts issues navigation (when an `IssuesPanel` component exists within).
107
+ *
108
+ * @param options Options used when starting issues validation.
109
+ */
110
+ startIssuesNavigation: (options: {
111
+ validate?: boolean;
112
+ setTouched?: boolean;
113
+ }) => PromiseLike<void>;
114
+ };
115
+ /**
116
+ * Root component of a form application.
117
+ *
118
+ * This component automatically renders the ostack/UI's `Root` component when
119
+ * not rendered inside of one, in which case it accepts properties that would
120
+ * otherwise be passed to the ostack/UI `Root` component. In this scenario, the
121
+ * ostack/UI's `locale` is automatically provided to the ostack/UI `Root`
122
+ * component from the provided `FormApp` `locale`.
123
+ */
124
+ export declare const FormApp: React.ForwardRefExoticComponent<Pick<Omit<import("@ostack.tech/ui").RootProps & React.RefAttributes<HTMLDivElement>, "ref">, "reportError" | "errorReportingUrl" | "errorReportingMethod" | "encodeErrorReport" | "encodedErrorReportMimeType" | "errorReportingOptions" | "baseDocumentTitle" | "enableErrorReporting" | "documentTitleBaseSeparator" | "documentTitleBreadcrumbsSeparator" | "portalsContainer" | "tooltipsDelayDuration" | "tooltipsSkipDelayDuration" | "disableTooltipsHoverableContent" | "toastsLabel" | "toastsDuration" | "toastsSwipeDirection" | "toastsSwipeThreshold" | "toastViewportHotkey" | "toastViewportLabel" | "toastViewportProps" | "errorBoundaryProps"> & Omit<import("@ostack.tech/kform-react").ControllerOptions<any, import("@ostack.tech/kform-react").FormControllerState<any>>, "formManager"> & import("@ostack.tech/kform-react").FormOwnOptions<any, unknown> & Omit<Omit<React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "ref">, "onReset" | "onSubmit"> & {
125
+ /** Schema of the form. */
126
+ schema: SchemaKt | Schema<any>;
127
+ /**
128
+ * Label to use in the issues panel when displaying issues associated with
129
+ * the form app.
130
+ */
131
+ issuesPanelLabel?: React.ReactNode;
132
+ /** Whether to disable the whole form. */
133
+ disabled?: boolean;
134
+ /** Whether to set the whole form as read-only. */
135
+ readOnly?: boolean;
136
+ /**
137
+ * Custom suffix to add to the ostack/UI's prefix when prefixing all
138
+ * component classes, styles, _etc._
139
+ *
140
+ * This prefix-suffix should match the `$prefix-suffix` SCSS variable.
141
+ */
142
+ prefixSuffix?: string;
143
+ /**
144
+ * Form app locale.
145
+ *
146
+ * @default defaultLocale
147
+ */
148
+ locale?: LocalizationObject;
149
+ /**
150
+ * Mapping of issue messages from the path of the field with issues to the
151
+ * issue messages of said field (which are themselves grouped by their
152
+ * code).
153
+ *
154
+ * Provided paths may contain wildcards, which will have a lower priority
155
+ * when matched against.
156
+ *
157
+ * These messages are used by the `IssueMessages` component.
158
+ *
159
+ * **Note:** Changes to `issueMessages` are handled correctly, but are not
160
+ * efficient. Please make sure that the identity of the provided value
161
+ * doesn't change at every render.
162
+ *
163
+ * Example value:
164
+ *
165
+ * ```tsx
166
+ * {
167
+ * "/**": {
168
+ * "valueMissing": "Field is required."
169
+ * },
170
+ * "/my/field": {
171
+ * "valueMissing": "My field cannot be left empty!",
172
+ * "someOtherError": "Text of the other error."
173
+ * }
174
+ * }
175
+ * ```
176
+ */
177
+ issueMessages?: Record<string, IssueMessagesByCode>;
178
+ /**
179
+ * Mode of displaying issues:
180
+ *
181
+ * - `inline` mode dispays issue messages near the component containing the
182
+ * issues. In this mode the bottom issues panel only functions as an aid
183
+ * for navigating issues.
184
+ * - `panel` mode displays issue messages within the bottom issues panel.
185
+ *
186
+ * @default inline
187
+ */
188
+ issuesDisplayMode?: IssuesDisplayMode;
189
+ /**
190
+ * Global setting which specifies whether issue codes should be added to
191
+ * each issue message.
192
+ *
193
+ * @default false
194
+ */
195
+ displayIssueCodes?: boolean;
196
+ /**
197
+ * Function called when a form path is focused.
198
+ *
199
+ * @param path Focused path.
200
+ */
201
+ onPathFocus?: (path: AbsolutePath) => void;
202
+ /**
203
+ * Minimum height of the form app. Values should **not** be percentages.
204
+ *
205
+ * @default "100dvh"
206
+ */
207
+ minHeight?: Responsive<number | string>;
208
+ /** Reference to the form app's API. */
209
+ apiRef?: React.Ref<FormAppApi<any> | undefined> | undefined;
210
+ } & React.RefAttributes<HTMLFormElement>>;
@@ -0,0 +1,181 @@
1
+ import { AbsolutePath, type Path, PathMultimap, type PathMultimapEntryId } from "@ostack.tech/kform";
2
+ import { type Controller } from "@ostack.tech/kform-react";
3
+ import * as React from "react";
4
+ import { type IssueMessagesByCode, type IssueMessageValue } from "../IssueMessages";
5
+ import { type IssuesDisplayMode } from "./FormApp.tsx";
6
+ /** Value of the form app context. */
7
+ export interface FormAppContextValue<T = unknown> {
8
+ disabled: boolean;
9
+ readOnly: boolean;
10
+ issuesDisplayMode: IssuesDisplayMode;
11
+ displayIssueCodes: boolean;
12
+ formAppElement: HTMLFormElement | null;
13
+ store: FormAppStore<T>;
14
+ }
15
+ /** State of the form app. */
16
+ export interface FormAppState<T> {
17
+ controller: Controller<T>;
18
+ focusedPath: AbsolutePath | null;
19
+ focusCounter: number;
20
+ issuesPanelPath: AbsolutePath | null;
21
+ topBarHeight: number;
22
+ leftSidebarWidth: number;
23
+ bottomPanelHeight: number;
24
+ startIssuesNavigation?: () => void;
25
+ activePath: AbsolutePath;
26
+ registeredControllers: [PathMultimap<Controller>];
27
+ registeredIssueMessages: [
28
+ PathMultimap<{
29
+ messages: IssueMessagesByCode;
30
+ priority: number;
31
+ }>
32
+ ];
33
+ deferredIssueMessageRemovalEntryIds: PathMultimapEntryId[];
34
+ registeredLabels: [
35
+ PathMultimap<{
36
+ label: React.ReactNode;
37
+ priority: number;
38
+ }>
39
+ ];
40
+ deferredLabelRemovalEntryIds: PathMultimapEntryId[];
41
+ actions: FormAppActions;
42
+ }
43
+ /** Item of a breadcrumb. */
44
+ export interface BreadcrumbItem {
45
+ path: AbsolutePath;
46
+ label: React.ReactNode;
47
+ }
48
+ /** Actions of the form app. */
49
+ export interface FormAppActions {
50
+ setIssuesPanelPath: (path: AbsolutePath | null) => void;
51
+ focus: (path: string | Path) => void;
52
+ resetFocus: () => void;
53
+ registerController: (path: AbsolutePath, controller?: Controller<any> | null) => (() => void) | void;
54
+ isRegistered: (path: AbsolutePath) => boolean;
55
+ setActivePath: (path: AbsolutePath) => void;
56
+ registerIssueMessages: (basePath: AbsolutePath, issueMessages?: Record<string, IssueMessagesByCode>, priority?: number) => (() => void) | void;
57
+ getRegisteredIssueMessage: (path: AbsolutePath, code: string) => IssueMessageValue | null;
58
+ registerLabel: (path: AbsolutePath, label: React.ReactNode, priority?: number) => (() => void) | void;
59
+ getRegisteredLabel: (path: AbsolutePath) => React.ReactNode;
60
+ getActiveIssuesPanelBreadcrumb: () => BreadcrumbItem[] | null;
61
+ startIssuesNavigation: (options?: {
62
+ validate?: boolean;
63
+ setTouched?: boolean;
64
+ }) => PromiseLike<void>;
65
+ }
66
+ /** Form app store. */
67
+ export type FormAppStore<T> = ReturnType<typeof useCreateFormAppContext<T>>["store"];
68
+ /** Form app context. */
69
+ export declare const FormAppContext: React.Context<FormAppContextValue<unknown> | null>;
70
+ /** Options used to create the data table context value. */
71
+ export interface UseCreateFormAppContextOptions<T> extends Omit<FormAppContextValue<T>, "store"> {
72
+ controller: Controller<T>;
73
+ onPathFocus?: (path: AbsolutePath) => void;
74
+ }
75
+ /** Hook which creates the form app context. */
76
+ export declare function useCreateFormAppContext<T>({ controller, disabled, readOnly, issuesDisplayMode, displayIssueCodes, formAppElement, onPathFocus, }: UseCreateFormAppContextOptions<T>): {
77
+ disabled: boolean;
78
+ readOnly: boolean;
79
+ issuesDisplayMode: IssuesDisplayMode;
80
+ displayIssueCodes: boolean;
81
+ formAppElement: HTMLFormElement | null;
82
+ store: Omit<import("zustand").StoreApi<FormAppState<T>>, "subscribe"> & {
83
+ subscribe: {
84
+ (listener: (selectedState: FormAppState<T>, previousSelectedState: FormAppState<T>) => void): () => void;
85
+ <U>(selector: (state: FormAppState<T>) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
86
+ equalityFn?: ((a: U, b: U) => boolean) | undefined;
87
+ fireImmediately?: boolean;
88
+ } | undefined): () => void;
89
+ };
90
+ };
91
+ };
92
+ /** Returns the context of the form app. */
93
+ export declare function useFormAppContext<T = unknown>(): FormAppContextValue<T>;
94
+ /** Returns a boolean representing whether the form is disabled. */
95
+ export declare function useFormIsDisabled(): boolean;
96
+ /** Returns a boolean representing whether the form is read-only. */
97
+ export declare function useFormIsReadOnly(): boolean;
98
+ /** Returns the form app's display mode for issue messages. */
99
+ export declare function useIssuesDisplayMode(): IssuesDisplayMode;
100
+ /**
101
+ * Returns whether issue codes should be displayed (by default) within issue
102
+ * messages.
103
+ */
104
+ export declare function useDisplayIssueCodesInIssueMessages(): boolean;
105
+ /** Hook providing access to the form app's HTML form element. */
106
+ export declare function useFormAppElement(): HTMLFormElement;
107
+ /**
108
+ * Hook exposing a function that can be used to specify the height of the form
109
+ * app's top bar.
110
+ */
111
+ export declare function useSetTopBarHeight(): (height?: number) => void;
112
+ /**
113
+ * Hook exposing a function that can be used to specify the width of the form
114
+ * app's left panel.
115
+ */
116
+ export declare function useSetLeftSidebarWidth(): (width?: number) => void;
117
+ /**
118
+ * Hook exposing a function that can be used to specify the height of the form
119
+ * app's bottom panel.
120
+ */
121
+ export declare function useSetBottomPanelHeight(): (height?: number) => void;
122
+ /**
123
+ * Returns the current active path of the form app and a function that can be
124
+ * used to set it, ala React.useState.
125
+ */
126
+ export declare function useIssuesPanelPath(): [
127
+ AbsolutePath | null,
128
+ FormAppActions["setIssuesPanelPath"]
129
+ ];
130
+ /** Hook exposing a function that can be used to focus a path within a form app. */
131
+ export declare function useFocus(): FormAppActions["focus"];
132
+ /** Hook exposing a function that can be used to reset the focus. */
133
+ export declare function useResetFocus(): FormAppActions["resetFocus"];
134
+ /**
135
+ * Hook used to register a controller within the form app. This makes the form
136
+ * app aware that a controller of a certain path is currently being rendered.
137
+ */
138
+ export declare function useRegisterController(controller: Controller<any>): void;
139
+ /** Hook to check whether there is a registered controller for the provided path. */
140
+ export declare function useIsRegistered(path?: AbsolutePath | null): boolean;
141
+ /** Hook exposing the active path. */
142
+ export declare function useActivePath(): AbsolutePath;
143
+ /** Hook exposing a function to set the active path. */
144
+ export declare function useSetActivePath(): FormAppActions["setActivePath"];
145
+ /** Hook used to register issue messages within the form app. */
146
+ export declare function useRegisterIssueMessages(path: AbsolutePath | null | undefined, issueMessages?: Record<string, IssueMessagesByCode>, priority?: number): void;
147
+ /** Hook used to get the issue message value for the provided path and code. */
148
+ export declare function useRegisteredIssueMessage(path: AbsolutePath | null | undefined, code: string): IssueMessageValue | null;
149
+ /** Hook used to register a label within the form app. */
150
+ export declare function useRegisterLabel(path: AbsolutePath | null | undefined, label: React.ReactNode, priority?: number): void;
151
+ /**
152
+ * Hook used to get the label parts associated with the active issues panel
153
+ * path.
154
+ */
155
+ export declare function useActiveIssuesPanelBreadcrumb(): BreadcrumbItem[] | null;
156
+ /**
157
+ * Hook exposing a function that can be used to start navigating through the
158
+ * form app's issues.
159
+ */
160
+ export declare function useStartIssuesNavigation(): FormAppActions["startIssuesNavigation"];
161
+ /** Options available to the {@link useOnPathFocus} hook. */
162
+ export interface UseOnFocusedPathChangeOptions {
163
+ /**
164
+ * Whether to run the callback immediately with the current active path.
165
+ *
166
+ * @default true
167
+ */
168
+ fireImmediately?: boolean;
169
+ }
170
+ /**
171
+ * Hook used to run a given function whenever the form app's focused path
172
+ * changes.
173
+ *
174
+ * @param cb Function to run when the focused path changes. This function should
175
+ * hopefully not change on every render (i.e., it should be memoised via
176
+ * `useCallback` or be defined externally).
177
+ * @param options Hook options.
178
+ */
179
+ export declare function useOnPathFocus(cb: (focusedPath: AbsolutePath) => void, { fireImmediately }?: UseOnFocusedPathChangeOptions): void;
180
+ /** Hook used to set the function which starts issue navigation. */
181
+ export declare function useSetStartIssuesNavigation(fn: () => void): void;
@@ -0,0 +1,45 @@
1
+ import { type Path } from "@ostack.tech/kform";
2
+ import type * as React from "react";
3
+ import { type IssueMessagesByCode } from "../IssueMessages";
4
+ /** Properties of the form app issue messages component. */
5
+ export interface FormAppIssueMessagesProps {
6
+ /** Base path for the paths used in `messages`. */
7
+ path?: string | Path;
8
+ /**
9
+ * Mapping of issue messages from the path of the field with issues to the
10
+ * issue messages of said field (which are themselves grouped by their code).
11
+ *
12
+ * Provided paths may contain wildcards, which will have a lower priority when
13
+ * matched against.
14
+ *
15
+ * These messages are used by the `IssueMessages` and `IssuesPanel`
16
+ * components.
17
+ *
18
+ * Example value:
19
+ *
20
+ * ```tsx
21
+ * {
22
+ * "/**": {
23
+ * "valueMissing": "Field is required."
24
+ * },
25
+ * "/my/field": {
26
+ * "valueMissing": "My field cannot be left empty!",
27
+ * "someOtherError": "Text of the other error."
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ issueMessages?: Record<string, IssueMessagesByCode>;
33
+ /**
34
+ * Priority to use when registering issue messages.
35
+ *
36
+ * When multiple issue messages are associated with the same path, then the
37
+ * one registered with the highest priority "wins".
38
+ *
39
+ * @default 0
40
+ */
41
+ priority?: number;
42
+ children: React.ReactNode;
43
+ }
44
+ /** Component used to register new issue messages within the form app. */
45
+ export declare function FormAppIssueMessages({ path, issueMessages, priority, children, }: FormAppIssueMessagesProps): React.ReactNode;
@@ -0,0 +1,23 @@
1
+ import * as React from "react";
2
+ /** Properties of the form app status component. */
3
+ export interface FormAppStatusProps {
4
+ /**
5
+ * Whether to mark the form app as disabled for children of this component.
6
+ *
7
+ * This property has no effect when set to `false`.
8
+ *
9
+ * @default false
10
+ */
11
+ disabled?: boolean;
12
+ /**
13
+ * Whether to mark the form app as read-only for children of this component.
14
+ *
15
+ * This property has no effect when set to `false`.
16
+ *
17
+ * @default false
18
+ */
19
+ readOnly?: boolean;
20
+ children: React.ReactNode;
21
+ }
22
+ /** Component used to apply a different form app status to part of the form. */
23
+ export declare function FormAppStatus({ disabled, readOnly, children, }: FormAppStatusProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export * from "./FormApp.tsx";
2
+ export { useActiveIssuesPanelBreadcrumb, useDisplayIssueCodesInIssueMessages, useFocus, useFormAppElement, useFormIsDisabled, useFormIsReadOnly, useIsRegistered, useIssuesDisplayMode, useOnPathFocus, useRegisterController, useRegisteredIssueMessage, useRegisterIssueMessages, useRegisterLabel, useSetBottomPanelHeight, useSetLeftSidebarWidth, useSetTopBarHeight, useStartIssuesNavigation, } from "./FormAppContext.ts";
3
+ export * from "./FormAppIssueMessages.tsx";
4
+ export * from "./FormAppStatus.tsx";
@@ -0,0 +1,86 @@
1
+ import { type Path } from "@ostack.tech/kform";
2
+ import { Container, ErrorBoundary, type IconButton, type Popover, type PopoverContent, type Stack } from "@ostack.tech/ui";
3
+ import * as React from "react";
4
+ import { type IssueMessages, type IssueMessagesByCode } from "../IssueMessages";
5
+ import { type IssuesPopover } from "../IssuesPopover";
6
+ /** Properties of the form page component. */
7
+ export interface FormPageProps extends Omit<React.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;
13
+ /** Sets the form page as disabled. */
14
+ disabled?: boolean;
15
+ /** Sets the form page as read-only. */
16
+ readOnly?: boolean;
17
+ /** Form page helper text, displayed as a popover triggered by an icon button. */
18
+ helperText?: React.ReactNode;
19
+ /**
20
+ * Mapping of issue messages from the path of the field with issues to the
21
+ * issue messages of said field (which are themselves grouped by their code).
22
+ *
23
+ * Provided paths are relative to the form page's path and may contain
24
+ * wildcards, which will have a lower priority when matched against.
25
+ *
26
+ * These messages are used by the `IssueMessages` component.
27
+ *
28
+ * **Note:** Changes to `issueMessages` are handled correctly, but are not
29
+ * efficient. Please make sure that the identity of the provided value doesn't
30
+ * change at every render.
31
+ *
32
+ * Example value:
33
+ *
34
+ * ```tsx
35
+ * {
36
+ * "**": {
37
+ * "valueMissing": "Field is required."
38
+ * },
39
+ * "field": {
40
+ * "valueMissing": "My field cannot be left empty!",
41
+ * "someOtherError": "Text of the other error."
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ issueMessages?: Record<string, IssueMessagesByCode>;
47
+ /**
48
+ * Issue messages of the form page itself.
49
+ *
50
+ * These messages can also be provided via the `issueMessages` property using
51
+ * a path of "`.`".
52
+ */
53
+ ownIssueMessages?: IssueMessagesByCode;
54
+ /** Properties to pass to the header element. */
55
+ headerProps?: React.ComponentPropsWithRef<"div">;
56
+ /** Label of the helper button announced to assistive technologies. */
57
+ helperButtonLabel?: string;
58
+ /** Properties to pass to the code element. */
59
+ codeProps?: React.ComponentPropsWithRef<"div">;
60
+ /** Properties to pass to the title element. */
61
+ titleProps?: React.ComponentPropsWithRef<"h2">;
62
+ /**
63
+ * Properties to pass to the element containing the popover components in the
64
+ * header.
65
+ */
66
+ headerPopoverContainerProps?: React.ComponentPropsWithRef<typeof Stack>;
67
+ /** Properties to pass to the form page's issues popover component. */
68
+ issuesPopoverProps?: React.ComponentPropsWithRef<typeof IssuesPopover>;
69
+ /** Properties to pass to the form page's issue messages component. */
70
+ issueMessagesProps?: Omit<React.ComponentPropsWithRef<typeof IssueMessages>, "messages">;
71
+ /** Properties to pass to the content element. */
72
+ contentProps?: React.ComponentPropsWithRef<"div">;
73
+ /** Properties to pass to the container component. */
74
+ containerProps?: React.ComponentPropsWithRef<typeof Container>;
75
+ /** Properties to pass to the `ErrorBoundary` component. */
76
+ errorBoundaryProps?: React.ComponentPropsWithRef<typeof ErrorBoundary>;
77
+ /** Properties to pass to the helper button component. */
78
+ helperButtonProps?: Omit<React.ComponentPropsWithRef<typeof IconButton>, "icon">;
79
+ /** Properties to pass to the helper popover component. */
80
+ helperPopoverProps?: React.ComponentPropsWithRef<typeof Popover>;
81
+ /** Properties to pass to the helper popover content component. */
82
+ helperPopoverContentProps?: React.ComponentPropsWithRef<typeof PopoverContent>;
83
+ children?: React.ReactNode;
84
+ }
85
+ /** Form page component. */
86
+ export declare const FormPage: React.ForwardRefExoticComponent<FormPageProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import { type FormPageProps } from "./FormPage.tsx";
3
+ /** Properties of the form page header. */
4
+ export interface FormPageHeaderProps extends React.ComponentPropsWithoutRef<"div">, Pick<FormPageProps, "helperText" | "helperButtonLabel" | "ownIssueMessages" | "codeProps" | "titleProps" | "headerPopoverContainerProps" | "issuesPopoverProps" | "issueMessagesProps" | "helperButtonProps" | "helperPopoverProps" | "helperPopoverContentProps"> {
5
+ }
6
+ /** Form page header. */
7
+ export declare const FormPageHeader: React.ForwardRefExoticComponent<FormPageHeaderProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,6 @@
1
+ import { type AbsolutePath } from "@ostack.tech/kform";
2
+ interface FormPageSidebarItemProps {
3
+ path: AbsolutePath;
4
+ }
5
+ export declare function FormPageSidebarItem({ path }: FormPageSidebarItemProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};