@okta/odyssey-react-mui 1.22.0 → 1.23.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 (230) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/@types/i18next.d.js.map +1 -1
  3. package/dist/Autocomplete.js +30 -0
  4. package/dist/Autocomplete.js.map +1 -1
  5. package/dist/Callout.js +12 -24
  6. package/dist/Callout.js.map +1 -1
  7. package/dist/DataTable/useScrollIndication.js +7 -3
  8. package/dist/DataTable/useScrollIndication.js.map +1 -1
  9. package/dist/FileUploader/FileUploadIllustration.js.map +1 -0
  10. package/dist/FileUploader/FileUploadPreview.js.map +1 -0
  11. package/dist/{labs/FileUpload.js → FileUploader/FileUploader.js} +6 -5
  12. package/dist/FileUploader/FileUploader.js.map +1 -0
  13. package/dist/FileUploader/index.js +13 -0
  14. package/dist/FileUploader/index.js.map +1 -0
  15. package/dist/OdysseyProvider.js +4 -0
  16. package/dist/OdysseyProvider.js.map +1 -1
  17. package/dist/Radio.js +2 -2
  18. package/dist/Radio.js.map +1 -1
  19. package/dist/Select.js +36 -0
  20. package/dist/Select.js.map +1 -1
  21. package/dist/{labs/Switch.js → Switch.js} +7 -7
  22. package/dist/Switch.js.map +1 -0
  23. package/dist/Tabs.js +7 -9
  24. package/dist/Tabs.js.map +1 -1
  25. package/dist/Tag.js +102 -4
  26. package/dist/Tag.js.map +1 -1
  27. package/dist/TextField.js +16 -39
  28. package/dist/TextField.js.map +1 -1
  29. package/dist/Toast.js +2 -2
  30. package/dist/Toast.js.map +1 -1
  31. package/dist/createShadowDomElements.js +1 -0
  32. package/dist/createShadowDomElements.js.map +1 -1
  33. package/dist/i18n.js +1 -1
  34. package/dist/i18n.js.map +1 -1
  35. package/dist/index.js +2 -1
  36. package/dist/index.js.map +1 -1
  37. package/dist/index.scss +92 -4
  38. package/dist/labs/DataView/DataView.js +64 -25
  39. package/dist/labs/DataView/DataView.js.map +1 -1
  40. package/dist/labs/DataView/TableLayoutContent.js +17 -3
  41. package/dist/labs/DataView/TableLayoutContent.js.map +1 -1
  42. package/dist/labs/DataView/componentTypes.js.map +1 -1
  43. package/dist/labs/DateField.js +2 -0
  44. package/dist/labs/DateField.js.map +1 -1
  45. package/dist/labs/DatePicker.js +5 -1
  46. package/dist/labs/DatePicker.js.map +1 -1
  47. package/dist/labs/SideNav/OktaLogo.js +36 -0
  48. package/dist/labs/SideNav/OktaLogo.js.map +1 -0
  49. package/dist/labs/SideNav/SideNav.js +125 -36
  50. package/dist/labs/SideNav/SideNav.js.map +1 -1
  51. package/dist/labs/SideNav/SideNavHeader.js +33 -10
  52. package/dist/labs/SideNav/SideNavHeader.js.map +1 -1
  53. package/dist/labs/SideNav/types.js.map +1 -1
  54. package/dist/labs/TopNav.js +2 -1
  55. package/dist/labs/TopNav.js.map +1 -1
  56. package/dist/labs/index.js +0 -2
  57. package/dist/labs/index.js.map +1 -1
  58. package/dist/labs/useDateFieldsTranslations.js +1 -1
  59. package/dist/labs/useDateFieldsTranslations.js.map +1 -1
  60. package/dist/properties/ts/odyssey-react-mui.js +3 -1
  61. package/dist/properties/ts/odyssey-react-mui.js.map +1 -1
  62. package/dist/src/Autocomplete.d.ts +30 -0
  63. package/dist/src/Autocomplete.d.ts.map +1 -1
  64. package/dist/src/Callout.d.ts +11 -23
  65. package/dist/src/Callout.d.ts.map +1 -1
  66. package/dist/src/DataTable/useScrollIndication.d.ts.map +1 -1
  67. package/dist/src/FileUploader/FileUploadIllustration.d.ts.map +1 -0
  68. package/dist/src/{labs → FileUploader}/FileUploadPreview.d.ts +2 -2
  69. package/dist/src/FileUploader/FileUploadPreview.d.ts.map +1 -0
  70. package/dist/src/{labs/FileUpload.d.ts → FileUploader/FileUploader.d.ts} +5 -4
  71. package/dist/src/FileUploader/FileUploader.d.ts.map +1 -0
  72. package/dist/src/FileUploader/index.d.ts +13 -0
  73. package/dist/src/FileUploader/index.d.ts.map +1 -0
  74. package/dist/src/NativeSelect.d.ts +1 -1
  75. package/dist/src/OdysseyProvider.d.ts.map +1 -1
  76. package/dist/src/OdysseyTranslationProvider.d.ts +1 -1
  77. package/dist/src/OdysseyTranslationProvider.d.ts.map +1 -1
  78. package/dist/src/PasswordField.d.ts +1 -1
  79. package/dist/src/SearchField.d.ts +1 -1
  80. package/dist/src/Select.d.ts +36 -0
  81. package/dist/src/Select.d.ts.map +1 -1
  82. package/dist/src/{labs/Switch.d.ts → Switch.d.ts} +3 -3
  83. package/dist/src/Switch.d.ts.map +1 -0
  84. package/dist/src/Tabs.d.ts +6 -8
  85. package/dist/src/Tabs.d.ts.map +1 -1
  86. package/dist/src/Tag.d.ts +7 -1
  87. package/dist/src/Tag.d.ts.map +1 -1
  88. package/dist/src/TextField.d.ts +17 -40
  89. package/dist/src/TextField.d.ts.map +1 -1
  90. package/dist/src/createShadowDomElements.d.ts.map +1 -1
  91. package/dist/src/i18n.d.ts +2 -2
  92. package/dist/src/i18n.d.ts.map +1 -1
  93. package/dist/src/index.d.ts +2 -1
  94. package/dist/src/index.d.ts.map +1 -1
  95. package/dist/src/labs/DataView/DataView.d.ts +1 -1
  96. package/dist/src/labs/DataView/DataView.d.ts.map +1 -1
  97. package/dist/src/labs/DataView/TableLayoutContent.d.ts +2 -1
  98. package/dist/src/labs/DataView/TableLayoutContent.d.ts.map +1 -1
  99. package/dist/src/labs/DataView/componentTypes.d.ts +10 -0
  100. package/dist/src/labs/DataView/componentTypes.d.ts.map +1 -1
  101. package/dist/src/labs/DateField.d.ts +2 -2
  102. package/dist/src/labs/DateField.d.ts.map +1 -1
  103. package/dist/src/labs/DatePicker.d.ts +2 -2
  104. package/dist/src/labs/DatePicker.d.ts.map +1 -1
  105. package/dist/{test-selectors/odysseyTestSelectors.js → src/labs/SideNav/OktaLogo.d.ts} +3 -9
  106. package/dist/src/labs/SideNav/OktaLogo.d.ts.map +1 -0
  107. package/dist/src/labs/SideNav/SideNav.d.ts +2 -1
  108. package/dist/src/labs/SideNav/SideNav.d.ts.map +1 -1
  109. package/dist/src/labs/SideNav/SideNavHeader.d.ts +1 -1
  110. package/dist/src/labs/SideNav/SideNavHeader.d.ts.map +1 -1
  111. package/dist/src/labs/SideNav/types.d.ts +28 -5
  112. package/dist/src/labs/SideNav/types.d.ts.map +1 -1
  113. package/dist/src/labs/TopNav.d.ts +1 -0
  114. package/dist/src/labs/TopNav.d.ts.map +1 -1
  115. package/dist/src/labs/index.d.ts +0 -2
  116. package/dist/src/labs/index.d.ts.map +1 -1
  117. package/dist/src/properties/ts/odyssey-react-mui.d.ts +2 -0
  118. package/dist/src/properties/ts/odyssey-react-mui.d.ts.map +1 -1
  119. package/dist/src/test-selectors/getByQuerySelector.d.ts +148 -0
  120. package/dist/src/test-selectors/getByQuerySelector.d.ts.map +1 -0
  121. package/{src/test-selectors/odysseyTestSelectors.ts → dist/src/test-selectors/getComputedAccessibleErrorMessageText.d.ts} +3 -11
  122. package/dist/src/test-selectors/getComputedAccessibleErrorMessageText.d.ts.map +1 -0
  123. package/dist/src/test-selectors/{featureTestSelector.d.ts → getComputedAccessibleText.d.ts} +11 -19
  124. package/dist/src/test-selectors/getComputedAccessibleText.d.ts.map +1 -0
  125. package/dist/src/test-selectors/index.d.ts +2 -2
  126. package/dist/src/test-selectors/index.d.ts.map +1 -1
  127. package/dist/src/test-selectors/interpolateString.d.ts +15 -0
  128. package/dist/src/test-selectors/interpolateString.d.ts.map +1 -0
  129. package/dist/src/test-selectors/linkedHtmlSelectors.d.ts +24 -0
  130. package/dist/src/test-selectors/linkedHtmlSelectors.d.ts.map +1 -0
  131. package/dist/src/test-selectors/queryOdysseySelector.d.ts +5755 -0
  132. package/dist/src/test-selectors/queryOdysseySelector.d.ts.map +1 -0
  133. package/dist/src/test-selectors/querySelector.d.ts +59 -3613
  134. package/dist/src/test-selectors/querySelector.d.ts.map +1 -1
  135. package/dist/src/test-selectors/sanityChecks.d.ts +18 -0
  136. package/dist/src/test-selectors/sanityChecks.d.ts.map +1 -0
  137. package/dist/src/test-selectors/testSelector.d.ts +46 -0
  138. package/dist/src/test-selectors/testSelector.d.ts.map +1 -0
  139. package/dist/src/theme/components.d.ts.map +1 -1
  140. package/dist/test-selectors/getByQuerySelector.js +64 -0
  141. package/dist/test-selectors/getByQuerySelector.js.map +1 -0
  142. package/dist/test-selectors/getComputedAccessibleErrorMessageText.js +25 -0
  143. package/dist/test-selectors/getComputedAccessibleErrorMessageText.js.map +1 -0
  144. package/dist/test-selectors/getComputedAccessibleText.js +24 -0
  145. package/dist/test-selectors/getComputedAccessibleText.js.map +1 -0
  146. package/dist/test-selectors/index.js +2 -2
  147. package/dist/test-selectors/index.js.map +1 -1
  148. package/{src/test-selectors/featureTestSelector.ts → dist/test-selectors/interpolateString.js} +11 -27
  149. package/dist/test-selectors/interpolateString.js.map +1 -0
  150. package/dist/test-selectors/linkedHtmlSelectors.js +34 -0
  151. package/dist/test-selectors/linkedHtmlSelectors.js.map +1 -0
  152. package/dist/test-selectors/queryOdysseySelector.js +26 -0
  153. package/dist/test-selectors/queryOdysseySelector.js.map +1 -0
  154. package/dist/test-selectors/querySelector.js +82 -58
  155. package/dist/test-selectors/querySelector.js.map +1 -1
  156. package/dist/test-selectors/sanityChecks.js +33 -0
  157. package/dist/test-selectors/sanityChecks.js.map +1 -0
  158. package/dist/test-selectors/testSelector.js +2 -0
  159. package/dist/test-selectors/testSelector.js.map +1 -0
  160. package/dist/test-selectors/testSelectors.json +1 -1
  161. package/dist/theme/components.js +0 -1
  162. package/dist/theme/components.js.map +1 -1
  163. package/dist/tsconfig.production.tsbuildinfo +1 -1
  164. package/dist/tsconfig.tsbuildinfo +1 -1
  165. package/jest.setup.js +3 -0
  166. package/package.json +5 -4
  167. package/scripts/generateTestSelectorsJson.ts +1 -1
  168. package/src/@types/i18next.d.ts +1 -1
  169. package/src/Autocomplete.tsx +32 -0
  170. package/src/Callout.tsx +13 -25
  171. package/src/DataTable/useScrollIndication.tsx +9 -2
  172. package/src/{labs → FileUploader}/FileUploadPreview.tsx +3 -3
  173. package/src/{labs/FileUpload.tsx → FileUploader/FileUploader.tsx} +7 -6
  174. package/src/FileUploader/index.ts +13 -0
  175. package/src/OdysseyCacheProvider.test.tsx +1 -0
  176. package/src/OdysseyProvider.tsx +6 -1
  177. package/src/Radio.tsx +2 -2
  178. package/src/Select.tsx +38 -0
  179. package/src/{labs/Switch.tsx → Switch.tsx} +10 -10
  180. package/src/Tabs.tsx +8 -10
  181. package/src/Tag.tsx +134 -3
  182. package/src/TextField.tsx +18 -41
  183. package/src/Toast.tsx +1 -1
  184. package/src/createShadowDomElements.ts +3 -0
  185. package/src/i18n.ts +3 -3
  186. package/src/index.ts +6 -1
  187. package/src/labs/DataView/DataView.test.tsx +158 -0
  188. package/src/labs/DataView/DataView.tsx +98 -50
  189. package/src/labs/DataView/TableLayoutContent.tsx +28 -1
  190. package/src/labs/DataView/componentTypes.ts +13 -0
  191. package/src/labs/DateField.tsx +3 -0
  192. package/src/labs/DatePicker.tsx +12 -1
  193. package/src/labs/SideNav/OktaLogo.tsx +39 -0
  194. package/src/labs/SideNav/SideNav.tsx +187 -51
  195. package/src/labs/SideNav/SideNavHeader.tsx +30 -7
  196. package/src/labs/SideNav/types.ts +32 -5
  197. package/src/labs/TopNav.tsx +3 -1
  198. package/src/labs/index.ts +0 -3
  199. package/src/labs/useDateFieldsTranslations.ts +1 -1
  200. package/src/properties/odyssey-react-mui.properties +2 -1
  201. package/src/properties/ts/odyssey-react-mui.ts +1 -1
  202. package/src/test-selectors/getByQuerySelector.ts +176 -0
  203. package/src/test-selectors/getComputedAccessibleErrorMessageText.ts +52 -0
  204. package/src/test-selectors/getComputedAccessibleText.ts +36 -0
  205. package/src/test-selectors/index.ts +2 -2
  206. package/src/test-selectors/interpolateString.ts +41 -0
  207. package/src/test-selectors/linkedHtmlSelectors.ts +73 -0
  208. package/src/test-selectors/queryOdysseySelector.ts +36 -0
  209. package/src/test-selectors/querySelector.ts +221 -170
  210. package/src/test-selectors/sanityChecks.ts +53 -0
  211. package/src/test-selectors/testSelector.ts +143 -0
  212. package/src/theme/components.tsx +0 -2
  213. package/dist/labs/FileUpload.js.map +0 -1
  214. package/dist/labs/FileUploadIllustration.js.map +0 -1
  215. package/dist/labs/FileUploadPreview.js.map +0 -1
  216. package/dist/labs/Switch.js.map +0 -1
  217. package/dist/src/labs/FileUpload.d.ts.map +0 -1
  218. package/dist/src/labs/FileUploadIllustration.d.ts.map +0 -1
  219. package/dist/src/labs/FileUploadPreview.d.ts.map +0 -1
  220. package/dist/src/labs/Switch.d.ts.map +0 -1
  221. package/dist/src/test-selectors/featureTestSelector.d.ts.map +0 -1
  222. package/dist/src/test-selectors/odysseyTestSelectors.d.ts +0 -120
  223. package/dist/src/test-selectors/odysseyTestSelectors.d.ts.map +0 -1
  224. package/dist/test-selectors/featureTestSelector.js +0 -2
  225. package/dist/test-selectors/featureTestSelector.js.map +0 -1
  226. package/dist/test-selectors/odysseyTestSelectors.js.map +0 -1
  227. /package/dist/{labs → FileUploader}/FileUploadIllustration.js +0 -0
  228. /package/dist/{labs → FileUploader}/FileUploadPreview.js +0 -0
  229. /package/dist/src/{labs → FileUploader}/FileUploadIllustration.d.ts +0 -0
  230. /package/src/{labs → FileUploader}/FileUploadIllustration.tsx +0 -0
@@ -11,188 +11,239 @@
11
11
  */
12
12
 
13
13
  import {
14
- queries,
15
- within,
16
- type BoundFunctions,
17
- type ByRoleOptions,
18
- type GetByText,
19
- GetByRole,
20
- } from "@testing-library/dom";
21
-
22
- import {
23
- type FeatureTestSelector,
14
+ type AccessibleTextSelector,
15
+ type AriaRole,
16
+ type ElementChildSelector,
24
17
  type TestSelector,
25
- } from "./featureTestSelector";
26
- import { odysseyTestSelectors } from "./odysseyTestSelectors";
27
-
28
- export const interpolateString = (
29
- string: string,
30
- values: Record<string, string | RegExp>,
31
- ) => {
32
- const interpolatedString = eval(`
33
- ${Object.entries(values)
34
- .map(
35
- ([key, value]) =>
36
- `const ${key} = ${
37
- typeof value === "string" ? JSON.stringify(value) : value
38
- };`,
39
- )
40
- .join("")}
41
-
42
- \`${string}\`
43
- `) as string;
44
-
45
- if (/^\/*(.+)\/$/.test(interpolatedString)) {
46
- return eval(interpolatedString) as RegExp;
47
- }
18
+ type ElementSelector,
19
+ } from "./testSelector";
20
+ import { getComputedAccessibleText } from "./getComputedAccessibleText";
21
+ import {
22
+ getByRoleQuerySelector,
23
+ getByTextQuerySelector,
24
+ type QueryMethod,
25
+ } from "./getByQuerySelector";
26
+ import { getControlledElement } from "./linkedHtmlSelectors";
27
+ import { ElementError } from "./sanityChecks";
48
28
 
49
- return interpolatedString;
50
- };
29
+ export type InnerQuerySelectorProps<
30
+ LocalTestSelector extends TestSelector,
31
+ LocalQueryMethod extends QueryMethod,
32
+ > = {
33
+ /**
34
+ * Testing Library method used to query elements.
35
+ */
36
+ queryMethod?: LocalQueryMethod;
37
+ } & (LocalTestSelector extends ElementSelector
38
+ ? LocalTestSelector["elementSelector"] extends {
39
+ role: infer Role;
40
+ }
41
+ ? Role extends AriaRole[]
42
+ ? {
43
+ /**
44
+ * Role is used when you have an optional `role`; otherwise, it'd baked into the metadata.
45
+ */
46
+ role: Role[number];
47
+ }
48
+ : object
49
+ : object
50
+ : object) &
51
+ (LocalTestSelector extends ElementSelector
52
+ ? {
53
+ /**
54
+ * Helps narrow down HTML selection to the correct element.
55
+ */
56
+ options: Record<
57
+ keyof LocalTestSelector["elementSelector"]["options"],
58
+ string | RegExp
59
+ >;
60
+ }
61
+ : object);
51
62
 
52
- const getByQuerySelector = ({
53
- canvas,
54
- method,
55
- options,
63
+ export const captureElement = <
64
+ LocalTestSelector extends TestSelector,
65
+ QuerySelectorOptions extends Record<string, string | RegExp>,
66
+ LocalQueryMethod extends QueryMethod = "get",
67
+ >({
68
+ containerElement,
69
+ queryMethod,
70
+ querySelectorOptions,
56
71
  role,
57
- text,
72
+ testSelector,
58
73
  }: {
59
- canvas: BoundFunctions<typeof queries>;
60
- method: "ByRole" | "ByLabelText" | "ByPlaceholderText" | "ByText";
61
- options?: ByRoleOptions;
62
- role?: Parameters<GetByRole>[1];
63
- text?: Parameters<GetByText>[1];
74
+ containerElement: HTMLElement;
75
+ queryMethod: LocalQueryMethod;
76
+ querySelectorOptions?: QuerySelectorOptions;
77
+ role?: AriaRole;
78
+ testSelector: LocalTestSelector;
64
79
  }) => {
65
- if (method === "ByRole") {
66
- return canvas.getByRole(
67
- // TODO: These should eventually reference `query` as the function identifier.
68
- role!,
69
- options,
70
- );
71
- } else if (method === "ByLabelText") {
72
- return canvas.getByLabelText(
73
- // These should eventually reference `query` as the function identifier.
74
- text!, // TODO: Use TypeScript `Infer` to ensure `label` is required when it's `ByLabelText`.
75
- options,
76
- );
77
- } else if (method === "ByPlaceholderText") {
78
- return canvas.getByPlaceholderText(
79
- // These should eventually reference `query` as the function identifier.
80
- text!, // TODO: Use TypeScript `Infer` to ensure `label` is required when it's `ByLabelText`.
81
- options,
82
- );
83
- } else if (method === "ByText") {
84
- return canvas.getByText(
85
- // These should eventually reference `query` as the function identifier.
86
- text!, // TODO: Use TypeScript `Infer` to ensure `description` is required when it's `ByLabelText`.
87
- options,
88
- );
80
+ if ("elementSelector" in testSelector && querySelectorOptions) {
81
+ const sharedProps = {
82
+ element: containerElement,
83
+ queryMethod,
84
+ queryOptions: Object.fromEntries(
85
+ Object.entries(testSelector.elementSelector.options).map(
86
+ ([testSelectorOptionKey, testingLibraryOptionKey]) => [
87
+ testingLibraryOptionKey,
88
+ querySelectorOptions[testSelectorOptionKey],
89
+ ],
90
+ ),
91
+ ),
92
+ };
93
+
94
+ if (testSelector.elementSelector.method === "ByRole") {
95
+ return getByRoleQuerySelector({
96
+ ...sharedProps,
97
+ role:
98
+ Array.isArray(testSelector.elementSelector.role) || role
99
+ ? role || ""
100
+ : testSelector.elementSelector.role,
101
+ });
102
+ }
103
+
104
+ return getByTextQuerySelector({
105
+ ...sharedProps,
106
+ selectionMethod: testSelector.elementSelector.method,
107
+ text: testSelector.elementSelector.text,
108
+ });
109
+ } else if (
110
+ "isControlledElement" in testSelector &&
111
+ testSelector.isControlledElement
112
+ ) {
113
+ try {
114
+ return getControlledElement({ element: containerElement });
115
+ } catch (error) {
116
+ if (queryMethod === "query") {
117
+ return null;
118
+ }
119
+
120
+ throw error;
121
+ }
89
122
  }
90
123
 
91
124
  return null;
92
125
  };
93
126
 
94
- export const querySelector = <TestSelectors extends FeatureTestSelector>({
95
- canvas,
96
- templateArgs: templateArgsProp,
97
- testSelectors,
98
- }: {
99
- /**
100
- * Testing Library canvas. This is usually `screen`, but Storybook uses `within(canvas)`.
101
- */
102
- canvas: BoundFunctions<typeof queries>;
103
- templateArgs?: TestSelectors extends TestSelector
104
- ? Record<
105
- TestSelectors["selector"]["templateVariableNames"][number],
127
+ export const querySelector =
128
+ <LocalTestSelector extends TestSelector>(
129
+ /**
130
+ * Selectors object including children and accessible text selections.
131
+ */
132
+ testSelector: LocalTestSelector,
133
+ ) =>
134
+ <LocalQueryMethod extends QueryMethod = "get">(
135
+ props: {
136
+ /**
137
+ * Refers to Testing Library's canvas. This is usually `screen`, but Storybook uses `within(canvas)`.
138
+ */
139
+ element: HTMLElement;
140
+ } & InnerQuerySelectorProps<LocalTestSelector, LocalQueryMethod>,
141
+ ) => {
142
+ const { element: containerElement, queryMethod } = props;
143
+
144
+ const capturedElement = captureElement({
145
+ containerElement,
146
+ queryMethod: queryMethod || ("get" as const),
147
+ querySelectorOptions: "options" in props ? props.options : undefined,
148
+ role: "role" in props ? (props.role as AriaRole) : undefined,
149
+ testSelector,
150
+ });
151
+
152
+ const getAccessibleText = <
153
+ LabelName extends LocalTestSelector extends AccessibleTextSelector
154
+ ? keyof LocalTestSelector["accessibleText"]
155
+ : never,
156
+ >(
157
+ labelName: LabelName,
158
+ ) => {
159
+ if (!capturedElement) {
160
+ throw new ElementError(
161
+ "No child HTML element available",
162
+ containerElement,
163
+ );
164
+ }
165
+
166
+ if (!("accessibleText" in testSelector)) {
167
+ throw new Error("Missing `accessibleText` in `TestSelector`");
168
+ }
169
+
170
+ return getComputedAccessibleText({
171
+ element: capturedElement,
172
+ type: testSelector.accessibleText[labelName],
173
+ });
174
+ };
175
+
176
+ const selectChild = <
177
+ ChildName extends LocalTestSelector extends ElementChildSelector
178
+ ? keyof LocalTestSelector["children"]
179
+ : keyof ElementChildSelector,
180
+ ChildQueryMethod extends QueryMethod = "get",
181
+ >(
182
+ childProps: {
183
+ name: ChildName;
184
+ } & InnerQuerySelectorProps<
185
+ LocalTestSelector extends ElementChildSelector
186
+ ? LocalTestSelector["children"][ChildName]
187
+ : TestSelector,
188
+ ChildQueryMethod
189
+ >,
190
+ ) => {
191
+ if (!capturedElement) {
192
+ throw new ElementError(
193
+ "No child HTML element available",
194
+ containerElement,
195
+ );
196
+ }
197
+
198
+ if (!("children" in testSelector)) {
199
+ throw new Error("Missing `children` in `TestSelector`");
200
+ }
201
+
202
+ type Options = Record<
203
+ LocalTestSelector extends ElementChildSelector
204
+ ? LocalTestSelector["children"][ChildName] extends ElementSelector
205
+ ? keyof LocalTestSelector["children"][ChildName]["elementSelector"]["options"]
206
+ : never
207
+ : never,
106
208
  string | RegExp
107
- >
108
- : never;
109
- testSelectors: TestSelectors;
110
- }) => {
111
- const element =
112
- "selector" in testSelectors
113
- ? getByQuerySelector({
114
- canvas,
115
- method: testSelectors.selector.method,
116
- options:
117
- templateArgsProp && testSelectors.selector.options
118
- ? Object.fromEntries(
119
- Object.entries(testSelectors.selector.options).map(
120
- ([key, value]) => [
121
- key,
122
- interpolateString(value, templateArgsProp),
123
- ],
124
- ),
125
- )
126
- : testSelectors.selector.options,
127
- ...(testSelectors.selector.method === "ByRole"
209
+ >;
210
+
211
+ return querySelector(
212
+ testSelector.children[
213
+ childProps.name
214
+ ] as LocalTestSelector extends ElementChildSelector
215
+ ? LocalTestSelector["children"][ChildName]
216
+ : TestSelector,
217
+ )(
218
+ // @ts-expect-error: Type '{ role?: AriaRole | undefined; options?: Record<LocalTestSelector extends ElementChildSelector ? LocalTestSelector["children"][ChildName] extends TestSelector ? keyof LocalTestSelector["children"][ChildName]["selector"]["options"] : string : string, string | RegExp> | undefined; element: HTMLElement...' is not assignable to type '(LocalTestSelector extends ElementChildSelector ? LocalTestSelector["children"][ChildName] : TestSelector) extends { ...; } ? Role extends AriaRole[] ? { ...; } : object : object'.ts(2345)
219
+ // `as testSelector.children[ChildName]` narrows the props down enough that TypeScript errors here. We're passing the correct information, but it doesn't know that, and it's difficult to fix this. -Kevin Ghadyani
220
+ {
221
+ element: capturedElement,
222
+ queryMethod: childProps.queryMethod,
223
+ ...("options" in childProps && childProps.options
128
224
  ? {
129
- role: templateArgsProp
130
- ? (interpolateString(
131
- testSelectors.selector?.role,
132
- templateArgsProp,
133
- ) as string)
134
- : testSelectors.selector?.role,
225
+ options: childProps.options as Options,
135
226
  }
136
- : {
137
- text: templateArgsProp
138
- ? interpolateString(
139
- testSelectors.selector?.text,
140
- templateArgsProp,
141
- )
142
- : testSelectors.selector?.text,
143
- }),
144
- })
145
- : null;
146
-
147
- const select =
148
- "feature" in testSelectors
149
- ? <FeatureName extends keyof (typeof testSelectors)["feature"]>(
150
- featureName: FeatureName,
151
- templateArgs?: (typeof testSelectors)["feature"][FeatureName] extends TestSelector
152
- ? Record<
153
- (typeof testSelectors)["feature"][FeatureName]["selector"]["templateVariableNames"][number],
154
- string | RegExp
155
- >
156
- : never,
157
- ) =>
158
- querySelector({
159
- canvas: element ? within(element) : canvas,
160
- templateArgs,
161
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
162
- // @ts-expect-error: Type 'FeatureName' cannot be used to index type 'Record<string, FeatureTestSelector>'.ts(2536)
163
- testSelectors: testSelectors.feature[featureName],
164
- })
165
- : null;
166
-
167
- return {
168
- element,
169
- select,
170
- };
171
- };
227
+ : {}),
228
+ ...("role" in childProps && childProps.role
229
+ ? {
230
+ role: childProps.role as AriaRole,
231
+ }
232
+ : {}),
233
+ },
234
+ );
235
+ };
172
236
 
173
- export const queryOdysseySelector = <
174
- ComponentName extends keyof typeof odysseyTestSelectors,
175
- >({
176
- canvas,
177
- componentName,
178
- templateArgs,
179
- }: {
180
- canvas: Parameters<
181
- typeof querySelector<(typeof odysseyTestSelectors)[ComponentName]>
182
- >[0]["canvas"];
183
- /**
184
- * Name of the component you want to select within.
185
- */
186
- componentName: ComponentName;
187
- /**
188
- * String or RegExp values required for this selector.
189
- */
190
- templateArgs?: Parameters<
191
- typeof querySelector<(typeof odysseyTestSelectors)[ComponentName]>
192
- >[0]["templateArgs"];
193
- }) =>
194
- querySelector({
195
- canvas,
196
- templateArgs,
197
- testSelectors: odysseyTestSelectors[componentName],
198
- });
237
+ return {
238
+ element: capturedElement as LocalQueryMethod extends "get"
239
+ ? HTMLElement
240
+ : HTMLElement | null,
241
+ getAccessibleText:
242
+ getAccessibleText as LocalTestSelector extends AccessibleTextSelector
243
+ ? typeof getAccessibleText
244
+ : never,
245
+ selectChild: selectChild as LocalTestSelector extends ElementChildSelector
246
+ ? typeof selectChild
247
+ : never,
248
+ };
249
+ };
@@ -0,0 +1,53 @@
1
+ /*!
2
+ * Copyright (c) 2024-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ // Code modified from: https://github.com/testing-library/jest-dom/blob/main/src/utils.js
14
+
15
+ export class ElementError extends Error {
16
+ constructor(message: string, element: HTMLElement) {
17
+ super(message);
18
+
19
+ this.name = "ElementError";
20
+
21
+ console.error("ElementError", element);
22
+ }
23
+ }
24
+
25
+ export const normalizeText = (text: string) => {
26
+ return text.replace(/\s+/g, " ").trim();
27
+ };
28
+
29
+ export const getWindow = (htmlElement: HTMLElement) => {
30
+ if (
31
+ !htmlElement ||
32
+ !htmlElement.ownerDocument ||
33
+ !htmlElement.ownerDocument.defaultView
34
+ ) {
35
+ throw new ElementError("Expected element to have a `window`", htmlElement);
36
+ }
37
+
38
+ return htmlElement.ownerDocument.defaultView!;
39
+ };
40
+
41
+ export const validateHtmlElement = (htmlElement: HTMLElement) => {
42
+ const window = getWindow(htmlElement);
43
+
44
+ if (
45
+ !(htmlElement instanceof window.SVGElement) &&
46
+ !(htmlElement instanceof window.HTMLElement)
47
+ ) {
48
+ throw new ElementError(
49
+ "Expected element to be an HTMLElement or an SVGElement",
50
+ htmlElement,
51
+ );
52
+ }
53
+ };
@@ -0,0 +1,143 @@
1
+ /*!
2
+ * Copyright (c) 2024-present, Okta, Inc. and/or its affiliates. All rights reserved.
3
+ * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4
+ *
5
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6
+ * Unless required by applicable law or agreed to in writing, software
7
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ *
10
+ * See the License for the specific language governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {
14
+ type ByRoleOptions,
15
+ type SelectorMatcherOptions,
16
+ } from "@testing-library/dom";
17
+
18
+ import {
19
+ type RoleSelectorMethod,
20
+ type TextSelectorMethod,
21
+ } from "./getByQuerySelector";
22
+
23
+ /**
24
+ * We can't use React's `AriaRole` because it allows any string value. We want to be very specific. This is otherwise copied straight from React's code.
25
+ * @see https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts#L2815
26
+ */
27
+ export type AriaRole =
28
+ | "alert"
29
+ | "alertdialog"
30
+ | "application"
31
+ | "article"
32
+ | "banner"
33
+ | "button"
34
+ | "cell"
35
+ | "checkbox"
36
+ | "columnheader"
37
+ | "combobox"
38
+ | "complementary"
39
+ | "contentinfo"
40
+ | "definition"
41
+ | "dialog"
42
+ | "directory"
43
+ | "document"
44
+ | "feed"
45
+ | "figure"
46
+ | "form"
47
+ | "grid"
48
+ | "gridcell"
49
+ | "group"
50
+ | "heading"
51
+ | "img"
52
+ | "link"
53
+ | "list"
54
+ | "listbox"
55
+ | "listitem"
56
+ | "log"
57
+ | "main"
58
+ | "marquee"
59
+ | "math"
60
+ | "menu"
61
+ | "menubar"
62
+ | "menuitem"
63
+ | "menuitemcheckbox"
64
+ | "menuitemradio"
65
+ | "navigation"
66
+ | "none"
67
+ | "note"
68
+ | "option"
69
+ | "presentation"
70
+ | "progressbar"
71
+ | "radio"
72
+ | "radiogroup"
73
+ | "region"
74
+ | "row"
75
+ | "rowgroup"
76
+ | "rowheader"
77
+ | "scrollbar"
78
+ | "search"
79
+ | "searchbox"
80
+ | "separator"
81
+ | "slider"
82
+ | "spinbutton"
83
+ | "status"
84
+ | "switch"
85
+ | "tab"
86
+ | "table"
87
+ | "tablist"
88
+ | "tabpanel"
89
+ | "term"
90
+ | "textbox"
91
+ | "timer"
92
+ | "toolbar"
93
+ | "tooltip"
94
+ | "tree"
95
+ | "treegrid"
96
+ | "treeitem";
97
+
98
+ export type ControlledElementSelector = { isControlledElement?: true };
99
+
100
+ export type RoleSelectorOptions = {
101
+ method: RoleSelectorMethod;
102
+ options: Record<string, keyof ByRoleOptions>;
103
+ role: AriaRole | AriaRole[];
104
+ // | "UNKNOWN" // This should be a `Symbol`, but it can't because this is ultimately going to be JSON stringified. This type will allow passing a custom role if the component allows it: `Box`.
105
+ };
106
+
107
+ export type TextSelectorOptions = {
108
+ method: TextSelectorMethod;
109
+ options: Record<string, keyof SelectorMatcherOptions>;
110
+ text: string;
111
+ };
112
+
113
+ export type ElementSelectorValue = RoleSelectorOptions | TextSelectorOptions;
114
+
115
+ export type ElementSelector = {
116
+ elementSelector: ElementSelectorValue;
117
+ };
118
+
119
+ export type ElementChildSelectorValue = Record<
120
+ string,
121
+ TestSelector & ControlledElementSelector
122
+ >;
123
+
124
+ export type ElementChildSelector = {
125
+ children: ElementChildSelectorValue;
126
+ };
127
+
128
+ export type AccessibleTextSelectorValue =
129
+ | "description"
130
+ | "errorMessage"
131
+ | "label";
132
+
133
+ export type AccessibleTextSelector = {
134
+ /** An "accessible -> semantic" name mapping such as "`description` -> `hint`" where "description" equates to `"aria-description"`. */
135
+ accessibleText: Record<string, AccessibleTextSelectorValue>;
136
+ };
137
+
138
+ export type TestSelector =
139
+ | ElementChildSelector
140
+ | ElementSelector
141
+ | (ElementChildSelector & ElementSelector)
142
+ | (AccessibleTextSelector & ElementSelector)
143
+ | (ElementChildSelector & AccessibleTextSelector & ElementSelector);
@@ -253,7 +253,6 @@ export const components = ({
253
253
  justifyContent: "center",
254
254
  alignItems: "center",
255
255
  borderRadius: 0,
256
- border: 0,
257
256
 
258
257
  ...(ownerState.onClose !== undefined && {
259
258
  paddingInline: odysseyTokens.Spacing6,
@@ -989,7 +988,6 @@ export const components = ({
989
988
  },
990
989
  },
991
990
  },
992
-
993
991
  MuiChip: {
994
992
  defaultProps: {
995
993
  deleteIcon: <CloseCircleFilledIcon />,
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileUpload.js","names":["memo","useCallback","useEffect","useRef","useState","styled","useTranslation","Button","UploadIcon","Field","FileUploadPreview","FileUploadIllustration","useOdysseyDesignTokens","Support","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","fileUploadTypes","fileUploadVariants","BaseInputWrapper","div","position","alignSelf","input","width","height","opacity","InputContainer","display","alignItems","justifyContent","borderStyle","hasError","odysseyDesignTokens","padding","Spacing6","Spacing3","border","PaletteDangerMain","HueNeutral300","borderRadius","BorderRadiusMain","transition","TransitionTimingMain","borderColor","HueNeutral700","FocusOutlineColorPrimary","boxShadow","outline","FocusOutlineWidthMain","FocusOutlineStyle","outlineOffset","FocusOutlineOffsetTight","backgroundColor","HueNeutral50","BorderColorDisabled","color","TypographyColorDisabled","ButtonAndInfoContainer","flexDirection","CenterAlignedSupportText","textAlign","FileUpload","acceptedFileTypes","errorMessage","id","isDisabled","isFullWidth","isOptional","hint","HintLinkComponent","label","onChange","type","variant","t","inputRef","filesToUpload","setFilesToUpload","updateFilesToUpload","event","files","target","length","mergedFiles","value","triggerFileInputClick","current","click","removeFileFromFilesToUploadList","name","deletedFileFilteredOut","filter","file","renderFileInput","ariaDescribedBy","errorMessageElementId","labelElementId","acceptedFileTypesAsString","join","Input","accept","disabled","multiple","ref","title","children","onClick","startIcon","Boolean","fieldType","hasVisibleLabel","renderFieldComponent","fileNames","map","onFileRemove","MemoizedFileUpload","displayName"],"sources":["../../src/labs/FileUpload.tsx"],"sourcesContent":["/*!\n * Copyright (c) 2022-present, Okta, Inc. and/or its affiliates. All rights reserved.\n * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the \"License.\")\n *\n * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\n * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n *\n * See the License for the specific language governing permissions and limitations under the License.\n */\n\nimport {\n memo,\n ChangeEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport styled from \"@emotion/styled\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { Button } from \"../Button\";\nimport { UploadIcon } from \"../icons.generated\";\nimport { Field, RenderFieldComponentProps } from \"../Field\";\nimport { FieldComponentProps } from \"../FieldComponentProps\";\nimport { FileUploadPreview } from \"./FileUploadPreview\";\nimport { FileUploadIllustration } from \"./FileUploadIllustration\";\nimport {\n useOdysseyDesignTokens,\n DesignTokens,\n} from \"../OdysseyDesignTokensContext\";\nimport { Support } from \"../Typography\";\n\nexport const fileUploadTypes = [\"single\", \"multiple\"] as const;\nexport const fileUploadVariants = [\n \"button\",\n \"dragAndDrop\",\n \"dragAndDropWithIcon\",\n] as const;\n\nconst BaseInputWrapper = styled.div({\n position: \"relative\",\n alignSelf: \"flex-start\",\n\n input: {\n position: \"absolute\",\n width: \"100%\",\n height: \"100%\",\n opacity: 0,\n },\n});\n\nconst InputContainer = styled(BaseInputWrapper)<{\n odysseyDesignTokens: DesignTokens;\n hasError: boolean;\n}>(\n {\n display: \"flex\",\n alignSelf: \"unset\",\n alignItems: \"center\",\n justifyContent: \"center\",\n\n \"&:has(input:focus)\": {\n borderStyle: \"solid\",\n },\n },\n ({ hasError, odysseyDesignTokens }) => ({\n padding: `${odysseyDesignTokens.Spacing6} ${odysseyDesignTokens.Spacing3}`,\n border: hasError\n ? `1px solid ${odysseyDesignTokens.PaletteDangerMain}`\n : `1px dashed ${odysseyDesignTokens.HueNeutral300}`,\n borderRadius: odysseyDesignTokens.BorderRadiusMain,\n transition: `border-color ${odysseyDesignTokens.TransitionTimingMain}, box-shadow ${odysseyDesignTokens.TransitionTimingMain}`,\n\n \"&:hover\": {\n borderColor: odysseyDesignTokens.HueNeutral700,\n },\n\n \"&:has(input:focus)\": {\n borderColor: odysseyDesignTokens.FocusOutlineColorPrimary,\n boxShadow: `0 0 0 1px ${odysseyDesignTokens.FocusOutlineColorPrimary}`,\n outline: `${odysseyDesignTokens.FocusOutlineWidthMain} ${odysseyDesignTokens.FocusOutlineStyle} transparent`,\n outlineOffset: odysseyDesignTokens.FocusOutlineOffsetTight,\n },\n\n \"&:has(input:disabled)\": {\n backgroundColor: odysseyDesignTokens.HueNeutral50,\n border: `1px solid ${odysseyDesignTokens.BorderColorDisabled}`,\n color: odysseyDesignTokens.TypographyColorDisabled,\n\n \"&:hover\": {\n borderColor: odysseyDesignTokens.BorderColorDisabled,\n },\n },\n }),\n);\n\nconst ButtonAndInfoContainer = styled.div({\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n});\n\nconst CenterAlignedSupportText = styled.div({\n textAlign: \"center\",\n});\n\nexport type FileUploadProps = {\n /**\n * an array of file types the user is able to upload. @see https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept#unique_file_type_specifiers for examples\n */\n acceptedFileTypes?: string[];\n /**\n * The label for the `input` element.\n */\n label: string;\n /**\n * Function that is called when the list of ifles to upload is changed\n */\n onChange: (files: File[]) => void;\n /**\n * Either `single` or `multiple`. If `multiple`, multiple files can be uploaded\n */\n type?: (typeof fileUploadTypes)[number];\n /**\n * Either `button`, `dragAndDrop` or `dragAndDropWithIcon`. Will determine how component appears visually\n */\n variant: (typeof fileUploadVariants)[number];\n} & Pick<\n FieldComponentProps,\n | \"errorMessage\"\n | \"hint\"\n | \"HintLinkComponent\"\n | \"id\"\n | \"isDisabled\"\n | \"isFullWidth\"\n | \"isOptional\"\n>;\n\nconst FileUpload = ({\n acceptedFileTypes,\n errorMessage,\n id,\n isDisabled = false,\n isFullWidth,\n isOptional,\n hint,\n HintLinkComponent,\n label,\n onChange,\n type,\n variant,\n}: FileUploadProps) => {\n const odysseyDesignTokens = useOdysseyDesignTokens();\n const { t } = useTranslation();\n const inputRef = useRef<HTMLInputElement>(null);\n const [filesToUpload, setFilesToUpload] = useState<File[]>([]);\n\n useEffect(() => {\n onChange(filesToUpload);\n }, [filesToUpload, onChange]);\n\n const updateFilesToUpload = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n const { files } = event.target;\n\n if (files && files.length > 0) {\n const mergedFiles =\n type === \"multiple\"\n ? [...filesToUpload, ...files]\n : ([...files] satisfies File[] as File[]);\n\n setFilesToUpload(mergedFiles);\n }\n\n // reset input value to allow re-upload of a file with the same name\n event.target.value = \"\";\n },\n [type, filesToUpload],\n );\n\n const triggerFileInputClick = useCallback(() => {\n inputRef.current?.click();\n }, [inputRef]);\n\n const removeFileFromFilesToUploadList = useCallback<(name: string) => void>(\n (name) => {\n const deletedFileFilteredOut = filesToUpload.filter(\n (file) => file.name !== name,\n );\n setFilesToUpload(deletedFileFilteredOut);\n },\n [filesToUpload],\n );\n\n const renderFileInput = useCallback(\n ({\n ariaDescribedBy,\n errorMessageElementId,\n id,\n labelElementId,\n }: RenderFieldComponentProps) => {\n const acceptedFileTypesAsString = acceptedFileTypes?.join(\",\");\n\n const Input = () => (\n <input\n accept={acceptedFileTypesAsString}\n aria-describedby={ariaDescribedBy}\n aria-errormessage={errorMessageElementId}\n aria-labelledby={labelElementId}\n disabled={isDisabled}\n id={id}\n multiple={type === \"multiple\"}\n onChange={updateFilesToUpload}\n ref={inputRef}\n title=\"\"\n type=\"file\"\n />\n );\n\n if (variant === \"button\") {\n return (\n <>\n <BaseInputWrapper>\n <Input />\n <Button\n isDisabled={isDisabled}\n label={t(\"fileupload.button.text\")}\n onClick={triggerFileInputClick}\n startIcon={<UploadIcon />}\n variant=\"secondary\"\n />\n </BaseInputWrapper>\n </>\n );\n }\n\n return (\n <>\n <InputContainer\n hasError={Boolean(errorMessage)}\n odysseyDesignTokens={odysseyDesignTokens}\n >\n <Input />\n <ButtonAndInfoContainer>\n {variant === \"dragAndDropWithIcon\" && <FileUploadIllustration />}\n <CenterAlignedSupportText>\n <Support color=\"textSecondary\">\n {t(\"fileupload.prompt.text\")}\n </Support>\n </CenterAlignedSupportText>\n <Button\n isDisabled={isDisabled}\n label={t(\"fileupload.button.text\")}\n onClick={triggerFileInputClick}\n startIcon={<UploadIcon />}\n variant=\"secondary\"\n />\n </ButtonAndInfoContainer>\n </InputContainer>\n </>\n );\n },\n [\n acceptedFileTypes,\n errorMessage,\n isDisabled,\n inputRef,\n odysseyDesignTokens,\n triggerFileInputClick,\n t,\n type,\n updateFilesToUpload,\n variant,\n ],\n );\n\n return (\n <>\n <Field\n errorMessage={errorMessage}\n fieldType=\"single\"\n hasVisibleLabel\n hint={hint}\n HintLinkComponent={HintLinkComponent}\n id={id}\n isDisabled={isDisabled}\n isFullWidth={isFullWidth && variant !== \"button\"}\n isOptional={isOptional}\n label={label}\n renderFieldComponent={renderFileInput}\n />\n {filesToUpload.length > 0 && (\n <FileUploadPreview\n fileNames={filesToUpload.map((file) => file.name)}\n onFileRemove={removeFileFromFilesToUploadList}\n isDisabled={isDisabled}\n />\n )}\n </>\n );\n};\n\nconst MemoizedFileUpload = memo(FileUpload);\nMemoizedFileUpload.displayName = \"FileUpload\";\n\nexport { MemoizedFileUpload as FileUpload };\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SACEA,IAAI,EAEJC,WAAW,EACXC,SAAS,EACTC,MAAM,EACNC,QAAQ,QACH,OAAO;AACd,OAAOC,MAAM,MAAM,iBAAiB;AACpC,SAASC,cAAc,QAAQ,eAAe;AAAC,SAEtCC,MAAM;AAAA,SACNC,UAAU;AAAA,SACVC,KAAK;AAAA,SAELC,iBAAiB;AAAA,SACjBC,sBAAsB;AAAA,SAE7BC,sBAAsB;AAAA,SAGfC,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAAA,SAAAC,IAAA,IAAAC,KAAA;AAAA,SAAAC,QAAA,IAAAC,SAAA;AAEhB,OAAO,MAAMC,eAAe,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAU;AAC9D,OAAO,MAAMC,kBAAkB,GAAG,CAChC,QAAQ,EACR,aAAa,EACb,qBAAqB,CACb;AAEV,MAAMC,gBAAgB,GAAGjB,MAAM,CAACkB,GAAG,CAAC;EAClCC,QAAQ,EAAE,UAAU;EACpBC,SAAS,EAAE,YAAY;EAEvBC,KAAK,EAAE;IACLF,QAAQ,EAAE,UAAU;IACpBG,KAAK,EAAE,MAAM;IACbC,MAAM,EAAE,MAAM;IACdC,OAAO,EAAE;EACX;AACF,CAAC,CAAC;AAEF,MAAMC,cAAc,GAAGzB,MAAM,CAACiB,gBAAgB,CAAC,CAI7C;EACES,OAAO,EAAE,MAAM;EACfN,SAAS,EAAE,OAAO;EAClBO,UAAU,EAAE,QAAQ;EACpBC,cAAc,EAAE,QAAQ;EAExB,oBAAoB,EAAE;IACpBC,WAAW,EAAE;EACf;AACF,CAAC,EACD,CAAC;EAAEC,QAAQ;EAAEC;AAAoB,CAAC,MAAM;EACtCC,OAAO,EAAG,GAAED,mBAAmB,CAACE,QAAS,IAAGF,mBAAmB,CAACG,QAAS,EAAC;EAC1EC,MAAM,EAAEL,QAAQ,GACX,aAAYC,mBAAmB,CAACK,iBAAkB,EAAC,GACnD,cAAaL,mBAAmB,CAACM,aAAc,EAAC;EACrDC,YAAY,EAAEP,mBAAmB,CAACQ,gBAAgB;EAClDC,UAAU,EAAG,gBAAeT,mBAAmB,CAACU,oBAAqB,gBAAeV,mBAAmB,CAACU,oBAAqB,EAAC;EAE9H,SAAS,EAAE;IACTC,WAAW,EAAEX,mBAAmB,CAACY;EACnC,CAAC;EAED,oBAAoB,EAAE;IACpBD,WAAW,EAAEX,mBAAmB,CAACa,wBAAwB;IACzDC,SAAS,EAAG,aAAYd,mBAAmB,CAACa,wBAAyB,EAAC;IACtEE,OAAO,EAAG,GAAEf,mBAAmB,CAACgB,qBAAsB,IAAGhB,mBAAmB,CAACiB,iBAAkB,cAAa;IAC5GC,aAAa,EAAElB,mBAAmB,CAACmB;EACrC,CAAC;EAED,uBAAuB,EAAE;IACvBC,eAAe,EAAEpB,mBAAmB,CAACqB,YAAY;IACjDjB,MAAM,EAAG,aAAYJ,mBAAmB,CAACsB,mBAAoB,EAAC;IAC9DC,KAAK,EAAEvB,mBAAmB,CAACwB,uBAAuB;IAElD,SAAS,EAAE;MACTb,WAAW,EAAEX,mBAAmB,CAACsB;IACnC;EACF;AACF,CAAC,CACH,CAAC;AAED,MAAMG,sBAAsB,GAAGxD,MAAM,CAACkB,GAAG,CAAC;EACxCQ,OAAO,EAAE,MAAM;EACf+B,aAAa,EAAE,QAAQ;EACvB9B,UAAU,EAAE,QAAQ;EACpBC,cAAc,EAAE;AAClB,CAAC,CAAC;AAEF,MAAM8B,wBAAwB,GAAG1D,MAAM,CAACkB,GAAG,CAAC;EAC1CyC,SAAS,EAAE;AACb,CAAC,CAAC;AAkCF,MAAMC,UAAU,GAAGA,CAAC;EAClBC,iBAAiB;EACjBC,YAAY;EACZC,EAAE;EACFC,UAAU,GAAG,KAAK;EAClBC,WAAW;EACXC,UAAU;EACVC,IAAI;EACJC,iBAAiB;EACjBC,KAAK;EACLC,QAAQ;EACRC,IAAI;EACJC;AACe,CAAC,KAAK;EACrB,MAAMzC,mBAAmB,GAAGxB,sBAAsB,CAAC,CAAC;EACpD,MAAM;IAAEkE;EAAE,CAAC,GAAGxE,cAAc,CAAC,CAAC;EAC9B,MAAMyE,QAAQ,GAAG5E,MAAM,CAAmB,IAAI,CAAC;EAC/C,MAAM,CAAC6E,aAAa,EAAEC,gBAAgB,CAAC,GAAG7E,QAAQ,CAAS,EAAE,CAAC;EAE9DF,SAAS,CAAC,MAAM;IACdyE,QAAQ,CAACK,aAAa,CAAC;EACzB,CAAC,EAAE,CAACA,aAAa,EAAEL,QAAQ,CAAC,CAAC;EAE7B,MAAMO,mBAAmB,GAAGjF,WAAW,CACpCkF,KAAoC,IAAK;IACxC,MAAM;MAAEC;IAAM,CAAC,GAAGD,KAAK,CAACE,MAAM;IAE9B,IAAID,KAAK,IAAIA,KAAK,CAACE,MAAM,GAAG,CAAC,EAAE;MAC7B,MAAMC,WAAW,GACfX,IAAI,KAAK,UAAU,GACf,CAAC,GAAGI,aAAa,EAAE,GAAGI,KAAK,CAAC,GAC3B,CAAC,GAAGA,KAAK,CAA6B;MAE7CH,gBAAgB,CAACM,WAAW,CAAC;IAC/B;IAGAJ,KAAK,CAACE,MAAM,CAACG,KAAK,GAAG,EAAE;EACzB,CAAC,EACD,CAACZ,IAAI,EAAEI,aAAa,CACtB,CAAC;EAED,MAAMS,qBAAqB,GAAGxF,WAAW,CAAC,MAAM;IAC9C8E,QAAQ,CAACW,OAAO,EAAEC,KAAK,CAAC,CAAC;EAC3B,CAAC,EAAE,CAACZ,QAAQ,CAAC,CAAC;EAEd,MAAMa,+BAA+B,GAAG3F,WAAW,CAChD4F,IAAI,IAAK;IACR,MAAMC,sBAAsB,GAAGd,aAAa,CAACe,MAAM,CAChDC,IAAI,IAAKA,IAAI,CAACH,IAAI,KAAKA,IAC1B,CAAC;IACDZ,gBAAgB,CAACa,sBAAsB,CAAC;EAC1C,CAAC,EACD,CAACd,aAAa,CAChB,CAAC;EAED,MAAMiB,eAAe,GAAGhG,WAAW,CACjC,CAAC;IACCiG,eAAe;IACfC,qBAAqB;IACrB/B,EAAE;IACFgC;EACyB,CAAC,KAAK;IAC/B,MAAMC,yBAAyB,GAAGnC,iBAAiB,EAAEoC,IAAI,CAAC,GAAG,CAAC;IAE9D,MAAMC,KAAK,GAAGA,CAAA,KACZxF,IAAA;MACEyF,MAAM,EAAEH,yBAA0B;MAClC,oBAAkBH,eAAgB;MAClC,qBAAmBC,qBAAsB;MACzC,mBAAiBC,cAAe;MAChCK,QAAQ,EAAEpC,UAAW;MACrBD,EAAE,EAAEA,EAAG;MACPsC,QAAQ,EAAE9B,IAAI,KAAK,UAAW;MAC9BD,QAAQ,EAAEO,mBAAoB;MAC9ByB,GAAG,EAAE5B,QAAS;MACd6B,KAAK,EAAC,EAAE;MACRhC,IAAI,EAAC;IAAM,CACZ,CACF;IAED,IAAIC,OAAO,KAAK,QAAQ,EAAE;MACxB,OACE9D,IAAA,CAAAI,SAAA;QAAA0F,QAAA,EACE5F,KAAA,CAACK,gBAAgB;UAAAuF,QAAA,GACf9F,IAAA,CAACwF,KAAK,IAAE,CAAC,EACTxF,IAAA,CAACR,MAAM;YACL8D,UAAU,EAAEA,UAAW;YACvBK,KAAK,EAAEI,CAAC,CAAC,wBAAwB,CAAE;YACnCgC,OAAO,EAAErB,qBAAsB;YAC/BsB,SAAS,EAAEhG,IAAA,CAACP,UAAU,IAAE,CAAE;YAC1BqE,OAAO,EAAC;UAAW,CACpB,CAAC;QAAA,CACc;MAAC,CACnB,CAAC;IAEP;IAEA,OACE9D,IAAA,CAAAI,SAAA;MAAA0F,QAAA,EACE5F,KAAA,CAACa,cAAc;QACbK,QAAQ,EAAE6E,OAAO,CAAC7C,YAAY,CAAE;QAChC/B,mBAAmB,EAAEA,mBAAoB;QAAAyE,QAAA,GAEzC9F,IAAA,CAACwF,KAAK,IAAE,CAAC,EACTtF,KAAA,CAAC4C,sBAAsB;UAAAgD,QAAA,GACpBhC,OAAO,KAAK,qBAAqB,IAAI9D,IAAA,CAACJ,sBAAsB,IAAE,CAAC,EAChEI,IAAA,CAACgD,wBAAwB;YAAA8C,QAAA,EACvB9F,IAAA,CAACF,OAAO;cAAC8C,KAAK,EAAC,eAAe;cAAAkD,QAAA,EAC3B/B,CAAC,CAAC,wBAAwB;YAAC,CACrB;UAAC,CACc,CAAC,EAC3B/D,IAAA,CAACR,MAAM;YACL8D,UAAU,EAAEA,UAAW;YACvBK,KAAK,EAAEI,CAAC,CAAC,wBAAwB,CAAE;YACnCgC,OAAO,EAAErB,qBAAsB;YAC/BsB,SAAS,EAAEhG,IAAA,CAACP,UAAU,IAAE,CAAE;YAC1BqE,OAAO,EAAC;UAAW,CACpB,CAAC;QAAA,CACoB,CAAC;MAAA,CACX;IAAC,CACjB,CAAC;EAEP,CAAC,EACD,CACEX,iBAAiB,EACjBC,YAAY,EACZE,UAAU,EACVU,QAAQ,EACR3C,mBAAmB,EACnBqD,qBAAqB,EACrBX,CAAC,EACDF,IAAI,EACJM,mBAAmB,EACnBL,OAAO,CAEX,CAAC;EAED,OACE5D,KAAA,CAAAE,SAAA;IAAA0F,QAAA,GACE9F,IAAA,CAACN,KAAK;MACJ0D,YAAY,EAAEA,YAAa;MAC3B8C,SAAS,EAAC,QAAQ;MAClBC,eAAe;MACf1C,IAAI,EAAEA,IAAK;MACXC,iBAAiB,EAAEA,iBAAkB;MACrCL,EAAE,EAAEA,EAAG;MACPC,UAAU,EAAEA,UAAW;MACvBC,WAAW,EAAEA,WAAW,IAAIO,OAAO,KAAK,QAAS;MACjDN,UAAU,EAAEA,UAAW;MACvBG,KAAK,EAAEA,KAAM;MACbyC,oBAAoB,EAAElB;IAAgB,CACvC,CAAC,EACDjB,aAAa,CAACM,MAAM,GAAG,CAAC,IACvBvE,IAAA,CAACL,iBAAiB;MAChB0G,SAAS,EAAEpC,aAAa,CAACqC,GAAG,CAAErB,IAAI,IAAKA,IAAI,CAACH,IAAI,CAAE;MAClDyB,YAAY,EAAE1B,+BAAgC;MAC9CvB,UAAU,EAAEA;IAAW,CACxB,CACF;EAAA,CACD,CAAC;AAEP,CAAC;AAED,MAAMkD,kBAAkB,GAAGvH,IAAI,CAACiE,UAAU,CAAC;AAC3CsD,kBAAkB,CAACC,WAAW,GAAG,YAAY;AAE7C,SAASD,kBAAkB,IAAItD,UAAU"}