@workos-inc/widgets 1.20.2-next.1792700156145 → 1.20.2

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 (202) hide show
  1. package/CHANGELOG.md +4 -10
  2. package/dist/cjs/admin-portal-audit-log-streaming.client.cjs +2 -1
  3. package/dist/cjs/admin-portal-audit-log-streaming.client.cjs.map +1 -1
  4. package/dist/cjs/admin-portal-domain-verification.client.cjs +3 -2
  5. package/dist/cjs/admin-portal-domain-verification.client.cjs.map +1 -1
  6. package/dist/cjs/admin-portal-sso-connection.client.cjs +2 -1
  7. package/dist/cjs/admin-portal-sso-connection.client.cjs.map +1 -1
  8. package/dist/cjs/api/api-provider.cjs +23 -1
  9. package/dist/cjs/api/api-provider.cjs.map +1 -1
  10. package/dist/cjs/api/api-provider.d.cts.map +1 -1
  11. package/dist/cjs/api/claims.cjs.map +1 -1
  12. package/dist/cjs/api/claims.d.cts +2 -1
  13. package/dist/cjs/api/claims.d.cts.map +1 -1
  14. package/dist/cjs/api/client-graphql/client.cjs +3 -2
  15. package/dist/cjs/api/client-graphql/client.cjs.map +1 -1
  16. package/dist/cjs/api/client-graphql/hooks.cjs +3 -20
  17. package/dist/cjs/api/client-graphql/hooks.cjs.map +1 -1
  18. package/dist/cjs/api/client-graphql/hooks.d.cts +3 -12
  19. package/dist/cjs/api/client-graphql/hooks.d.cts.map +1 -1
  20. package/dist/cjs/api/client-graphql/query-keys.cjs +25 -0
  21. package/dist/cjs/api/client-graphql/query-keys.cjs.map +1 -0
  22. package/dist/cjs/api/client-graphql/query-keys.d.cts +16 -0
  23. package/dist/cjs/api/client-graphql/query-keys.d.cts.map +1 -0
  24. package/dist/cjs/components/copy-text.cjs +1 -1
  25. package/dist/cjs/components/copy-text.cjs.map +1 -1
  26. package/dist/cjs/components/form.cjs +9 -13
  27. package/dist/cjs/components/form.cjs.map +1 -1
  28. package/dist/cjs/components/form.d.cts.map +1 -1
  29. package/dist/cjs/components/otp-input.cjs +1 -0
  30. package/dist/cjs/components/otp-input.cjs.map +1 -1
  31. package/dist/cjs/directory-sync.client.cjs +2 -1
  32. package/dist/cjs/directory-sync.client.cjs.map +1 -1
  33. package/dist/cjs/lib/api/api-key.cjs +4 -3
  34. package/dist/cjs/lib/api/api-key.cjs.map +1 -1
  35. package/dist/cjs/lib/api/me.cjs +2 -1
  36. package/dist/cjs/lib/api/me.cjs.map +1 -1
  37. package/dist/cjs/lib/api/pipes.cjs +7 -6
  38. package/dist/cjs/lib/api/pipes.cjs.map +1 -1
  39. package/dist/cjs/lib/api/user-api-key.cjs +3 -2
  40. package/dist/cjs/lib/api/user-api-key.cjs.map +1 -1
  41. package/dist/cjs/lib/i18n/intl-context.cjs.map +1 -1
  42. package/dist/cjs/lib/i18n/intl-context.d.cts +1 -0
  43. package/dist/cjs/lib/i18n/intl-context.d.cts.map +1 -1
  44. package/dist/cjs/lib/i18n/use-translation.cjs +2 -2
  45. package/dist/cjs/lib/i18n/use-translation.cjs.map +1 -1
  46. package/dist/cjs/lib/use-composed-event-handlers.cjs +15 -0
  47. package/dist/cjs/lib/use-composed-event-handlers.cjs.map +1 -0
  48. package/dist/cjs/lib/use-composed-event-handlers.d.cts +6 -0
  49. package/dist/cjs/lib/use-composed-event-handlers.d.cts.map +1 -0
  50. package/dist/cjs/lib/use-debounce.cjs +124 -116
  51. package/dist/cjs/lib/use-debounce.cjs.map +1 -1
  52. package/dist/cjs/lib/use-debounce.d.cts +53 -48
  53. package/dist/cjs/lib/use-debounce.d.cts.map +1 -1
  54. package/dist/cjs/lib/use-widgets-invalidator.cjs +3 -3
  55. package/dist/cjs/lib/use-widgets-invalidator.cjs.map +1 -1
  56. package/dist/cjs/lib/use-widgets-invalidator.d.cts.map +1 -1
  57. package/dist/cjs/lib/utils.cjs +0 -7
  58. package/dist/cjs/lib/utils.cjs.map +1 -1
  59. package/dist/cjs/lib/utils.d.cts +0 -3
  60. package/dist/cjs/lib/utils.d.cts.map +1 -1
  61. package/dist/cjs/organization-switcher.client.cjs +2 -1
  62. package/dist/cjs/organization-switcher.client.cjs.map +1 -1
  63. package/dist/cjs/pipes-admin.client.cjs +2 -1
  64. package/dist/cjs/pipes-admin.client.cjs.map +1 -1
  65. package/dist/cjs/pipes.client.cjs +2 -1
  66. package/dist/cjs/pipes.client.cjs.map +1 -1
  67. package/dist/cjs/user-security.client.cjs +2 -1
  68. package/dist/cjs/user-security.client.cjs.map +1 -1
  69. package/dist/cjs/user-sessions.client.cjs +2 -1
  70. package/dist/cjs/user-sessions.client.cjs.map +1 -1
  71. package/dist/cjs/widgets/api-keys/api-keys-search.cjs +1 -1
  72. package/dist/cjs/widgets/api-keys/api-keys-search.cjs.map +1 -1
  73. package/dist/cjs/widgets/api-keys/user-api-keys-search.cjs +1 -1
  74. package/dist/cjs/widgets/api-keys/user-api-keys-search.cjs.map +1 -1
  75. package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs +19 -5
  76. package/dist/cjs/widgets/organization-switcher/organization-switcher.cjs.map +1 -1
  77. package/dist/cjs/widgets/organization-switcher/organization-switcher.d.cts +2 -1
  78. package/dist/cjs/widgets/organization-switcher/organization-switcher.d.cts.map +1 -1
  79. package/dist/cjs/widgets/pipes/pipes.cjs +3 -2
  80. package/dist/cjs/widgets/pipes/pipes.cjs.map +1 -1
  81. package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs +2 -1
  82. package/dist/cjs/widgets/user-sessions/logout-all-sessions-dialog.cjs.map +1 -1
  83. package/dist/cjs/widgets/user-sessions/logout-dialog.cjs +2 -1
  84. package/dist/cjs/widgets/user-sessions/logout-dialog.cjs.map +1 -1
  85. package/dist/cjs/widgets/users-management/invite-user-dialog.cjs +5 -6
  86. package/dist/cjs/widgets/users-management/invite-user-dialog.cjs.map +1 -1
  87. package/dist/cjs/widgets/users-management/users-management-utils.cjs +4 -3
  88. package/dist/cjs/widgets/users-management/users-management-utils.cjs.map +1 -1
  89. package/dist/cjs/widgets/users-management/users-management.cjs.map +1 -1
  90. package/dist/cjs/widgets/users-management/users-search.cjs +1 -1
  91. package/dist/cjs/widgets/users-management/users-search.cjs.map +1 -1
  92. package/dist/esm/admin-portal-audit-log-streaming.client.js +2 -1
  93. package/dist/esm/admin-portal-audit-log-streaming.client.js.map +1 -1
  94. package/dist/esm/admin-portal-domain-verification.client.js +2 -1
  95. package/dist/esm/admin-portal-domain-verification.client.js.map +1 -1
  96. package/dist/esm/admin-portal-sso-connection.client.js +2 -1
  97. package/dist/esm/admin-portal-sso-connection.client.js.map +1 -1
  98. package/dist/esm/api/api-provider.d.ts.map +1 -1
  99. package/dist/esm/api/api-provider.js +23 -1
  100. package/dist/esm/api/api-provider.js.map +1 -1
  101. package/dist/esm/api/claims.d.ts +2 -1
  102. package/dist/esm/api/claims.d.ts.map +1 -1
  103. package/dist/esm/api/claims.js.map +1 -1
  104. package/dist/esm/api/client-graphql/client.js +3 -2
  105. package/dist/esm/api/client-graphql/client.js.map +1 -1
  106. package/dist/esm/api/client-graphql/hooks.d.ts +3 -12
  107. package/dist/esm/api/client-graphql/hooks.d.ts.map +1 -1
  108. package/dist/esm/api/client-graphql/hooks.js +1 -18
  109. package/dist/esm/api/client-graphql/hooks.js.map +1 -1
  110. package/dist/esm/api/client-graphql/query-keys.d.ts +16 -0
  111. package/dist/esm/api/client-graphql/query-keys.d.ts.map +1 -0
  112. package/dist/esm/api/client-graphql/query-keys.js +23 -0
  113. package/dist/esm/api/client-graphql/query-keys.js.map +1 -0
  114. package/dist/esm/components/copy-text.js +1 -1
  115. package/dist/esm/components/copy-text.js.map +1 -1
  116. package/dist/esm/components/form.d.ts.map +1 -1
  117. package/dist/esm/components/form.js +9 -13
  118. package/dist/esm/components/form.js.map +1 -1
  119. package/dist/esm/components/otp-input.js +1 -0
  120. package/dist/esm/components/otp-input.js.map +1 -1
  121. package/dist/esm/directory-sync.client.js +2 -1
  122. package/dist/esm/directory-sync.client.js.map +1 -1
  123. package/dist/esm/lib/api/api-key.js +2 -1
  124. package/dist/esm/lib/api/api-key.js.map +1 -1
  125. package/dist/esm/lib/api/me.js +2 -1
  126. package/dist/esm/lib/api/me.js.map +1 -1
  127. package/dist/esm/lib/api/pipes.js +2 -1
  128. package/dist/esm/lib/api/pipes.js.map +1 -1
  129. package/dist/esm/lib/api/user-api-key.js +2 -1
  130. package/dist/esm/lib/api/user-api-key.js.map +1 -1
  131. package/dist/esm/lib/i18n/intl-context.d.ts +1 -0
  132. package/dist/esm/lib/i18n/intl-context.d.ts.map +1 -1
  133. package/dist/esm/lib/i18n/intl-context.js.map +1 -1
  134. package/dist/esm/lib/i18n/use-translation.js +2 -2
  135. package/dist/esm/lib/i18n/use-translation.js.map +1 -1
  136. package/dist/esm/lib/use-composed-event-handlers.d.ts +6 -0
  137. package/dist/esm/lib/use-composed-event-handlers.d.ts.map +1 -0
  138. package/dist/esm/lib/use-composed-event-handlers.js +12 -0
  139. package/dist/esm/lib/use-composed-event-handlers.js.map +1 -0
  140. package/dist/esm/lib/use-debounce.d.ts +53 -48
  141. package/dist/esm/lib/use-debounce.d.ts.map +1 -1
  142. package/dist/esm/lib/use-debounce.js +124 -116
  143. package/dist/esm/lib/use-debounce.js.map +1 -1
  144. package/dist/esm/lib/use-widgets-invalidator.d.ts.map +1 -1
  145. package/dist/esm/lib/use-widgets-invalidator.js +2 -2
  146. package/dist/esm/lib/use-widgets-invalidator.js.map +1 -1
  147. package/dist/esm/lib/utils.d.ts +0 -3
  148. package/dist/esm/lib/utils.d.ts.map +1 -1
  149. package/dist/esm/lib/utils.js +1 -7
  150. package/dist/esm/lib/utils.js.map +1 -1
  151. package/dist/esm/organization-switcher.client.js +2 -1
  152. package/dist/esm/organization-switcher.client.js.map +1 -1
  153. package/dist/esm/pipes-admin.client.js +2 -1
  154. package/dist/esm/pipes-admin.client.js.map +1 -1
  155. package/dist/esm/pipes.client.js +2 -1
  156. package/dist/esm/pipes.client.js.map +1 -1
  157. package/dist/esm/user-security.client.js +2 -1
  158. package/dist/esm/user-security.client.js.map +1 -1
  159. package/dist/esm/user-sessions.client.js +2 -1
  160. package/dist/esm/user-sessions.client.js.map +1 -1
  161. package/dist/esm/widgets/api-keys/api-keys-search.js +1 -1
  162. package/dist/esm/widgets/api-keys/api-keys-search.js.map +1 -1
  163. package/dist/esm/widgets/api-keys/user-api-keys-search.js +1 -1
  164. package/dist/esm/widgets/api-keys/user-api-keys-search.js.map +1 -1
  165. package/dist/esm/widgets/organization-switcher/organization-switcher.d.ts +2 -1
  166. package/dist/esm/widgets/organization-switcher/organization-switcher.d.ts.map +1 -1
  167. package/dist/esm/widgets/organization-switcher/organization-switcher.js +19 -5
  168. package/dist/esm/widgets/organization-switcher/organization-switcher.js.map +1 -1
  169. package/dist/esm/widgets/pipes/pipes.js +2 -1
  170. package/dist/esm/widgets/pipes/pipes.js.map +1 -1
  171. package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js +2 -1
  172. package/dist/esm/widgets/user-sessions/logout-all-sessions-dialog.js.map +1 -1
  173. package/dist/esm/widgets/user-sessions/logout-dialog.js +2 -1
  174. package/dist/esm/widgets/user-sessions/logout-dialog.js.map +1 -1
  175. package/dist/esm/widgets/users-management/invite-user-dialog.js +5 -6
  176. package/dist/esm/widgets/users-management/invite-user-dialog.js.map +1 -1
  177. package/dist/esm/widgets/users-management/users-management-utils.js +2 -1
  178. package/dist/esm/widgets/users-management/users-management-utils.js.map +1 -1
  179. package/dist/esm/widgets/users-management/users-management.js.map +1 -1
  180. package/dist/esm/widgets/users-management/users-search.js +1 -1
  181. package/dist/esm/widgets/users-management/users-search.js.map +1 -1
  182. package/package.json +1 -1
  183. package/src/api/api-provider.tsx +39 -1
  184. package/src/api/claims.ts +2 -1
  185. package/src/api/client-graphql/client.ts +8 -2
  186. package/src/api/client-graphql/hooks.ts +8 -27
  187. package/src/api/client-graphql/query-keys.ts +29 -0
  188. package/src/components/copy-text.tsx +1 -1
  189. package/src/components/form.tsx +33 -29
  190. package/src/components/otp-input.tsx +2 -0
  191. package/src/lib/i18n/intl-context.tsx +4 -0
  192. package/src/lib/i18n/use-translation.ts +1 -4
  193. package/src/lib/use-composed-event-handlers.ts +25 -0
  194. package/src/lib/use-debounce.ts +289 -237
  195. package/src/lib/use-widgets-invalidator.ts +0 -4
  196. package/src/lib/utils.ts +0 -12
  197. package/src/widgets/api-keys/api-keys-search.tsx +6 -3
  198. package/src/widgets/api-keys/user-api-keys-search.tsx +6 -3
  199. package/src/widgets/organization-switcher/organization-switcher.tsx +32 -8
  200. package/src/widgets/users-management/invite-user-dialog.tsx +9 -11
  201. package/src/widgets/users-management/users-management.tsx +1 -1
  202. package/src/widgets/users-management/users-search.tsx +6 -3
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { useComposedRefs } from "../lib/compose-refs.js";
3
- import { composeEventHandlers } from "../lib/utils.js";
3
+ import { useComposedEventHandlers } from "../lib/use-composed-event-handlers.js";
4
4
  import { Slot } from "@radix-ui/themes";
5
5
  import * as React from "react";
6
6
  import { jsx } from "react/jsx-runtime";
@@ -122,16 +122,16 @@ const Form = /* @__PURE__ */ React.forwardRef(function Form(props, forwardedRef)
122
122
  children: /* @__PURE__ */ jsx(Component, {
123
123
  ...rootProps,
124
124
  ref: composedFormRef,
125
- onInvalid: composeEventHandlers(props.onInvalid, (event) => {
125
+ onInvalid: useComposedEventHandlers(props.onInvalid, React.useCallback((event) => {
126
126
  const firstInvalidControl = getFirstInvalidControl(event.currentTarget);
127
127
  if (firstInvalidControl === event.target) firstInvalidControl.focus();
128
128
  event.preventDefault();
129
- }),
129
+ }, [])),
130
130
  onSubmit: (event) => {
131
131
  props.onSubmit?.(event);
132
132
  onClearServerErrors();
133
133
  },
134
- onReset: composeEventHandlers(props.onReset, onClearServerErrors)
134
+ onReset: useComposedEventHandlers(props.onReset, onClearServerErrors)
135
135
  })
136
136
  })
137
137
  });
@@ -202,7 +202,8 @@ const FormControl = /* @__PURE__ */ React.forwardRef(function FormControl(props,
202
202
  if (!id) throw new Error(`\`FormControl\` must be used within \`FormField\` or specify the \`id\` prop`);
203
203
  const customMatcherEntries = validationContext.getFieldCustomMatcherEntries(name);
204
204
  const { onFieldValidityChange, onFieldCustomErrorsChange, onFieldValiditionClear } = validationContext;
205
- const updateControlValidity = React.useCallback(async (control) => {
205
+ const updateControlValidity = React.useCallback(async (event) => {
206
+ const { currentTarget: control } = event;
206
207
  if (hasBuiltInError(control.validity)) {
207
208
  const controlValidity = validityStateToObject(control.validity);
208
209
  onFieldValidityChange(name, controlValidity);
@@ -245,7 +246,7 @@ const FormControl = /* @__PURE__ */ React.forwardRef(function FormControl(props,
245
246
  React.useEffect(() => {
246
247
  const control = ref.current;
247
248
  if (control) {
248
- const handleChange = () => updateControlValidity(control);
249
+ const handleChange = () => updateControlValidity({ currentTarget: control });
249
250
  control.addEventListener("change", handleChange);
250
251
  return () => control.removeEventListener("change", handleChange);
251
252
  }
@@ -283,13 +284,8 @@ const FormControl = /* @__PURE__ */ React.forwardRef(function FormControl(props,
283
284
  ref: composedRef,
284
285
  id,
285
286
  name,
286
- onInvalid: composeEventHandlers(props.onInvalid, (event) => {
287
- const control = event.currentTarget;
288
- updateControlValidity(control);
289
- }),
290
- onChange: composeEventHandlers(props.onChange, () => {
291
- resetControlValidity();
292
- })
287
+ onInvalid: useComposedEventHandlers(props.onInvalid, updateControlValidity),
288
+ onChange: useComposedEventHandlers(props.onChange, resetControlValidity)
293
289
  });
294
290
  });
295
291
  FormControl.displayName = "Form.Control";
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form.tsx"],"sourcesContent":["\"use client\";\nimport { Slot } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { composeEventHandlers } from \"../lib/utils.js\";\n\n/* -------------------------------------------------------------------------------------------------\n * Form\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidityMap = { [fieldName: string]: ValidityState | undefined };\ntype CustomMatcherEntriesMap = { [fieldName: string]: CustomMatcherEntry[] };\ntype CustomErrorsMap = { [fieldName: string]: Record<string, boolean> };\n\ninterface ValidationContextValue {\n getFieldValidity(fieldName: string): ValidityState | undefined;\n onFieldValidityChange(fieldName: string, validity: ValidityState): void;\n\n getFieldCustomMatcherEntries(fieldName: string): CustomMatcherEntry[];\n onFieldCustomMatcherEntryAdd(\n fieldName: string,\n matcherEntry: CustomMatcherEntry,\n ): void;\n onFieldCustomMatcherEntryRemove(\n fieldName: string,\n matcherEntryId: string,\n ): void;\n\n getFieldCustomErrors(fieldName: string): Record<string, boolean>;\n onFieldCustomErrorsChange(\n fieldName: string,\n errors: Record<string, boolean>,\n ): void;\n\n onFieldValiditionClear(fieldName: string): void;\n}\n\n// oxfmt-ignore\nconst ValidationContext = /* @__PURE__ */ React.createContext<ValidationContextValue | null>(null);\nValidationContext.displayName = \"ValidationContext\";\n\nfunction useValidationContext() {\n const context = React.useContext(ValidationContext);\n if (!context) {\n throw new Error(\n `useValidationContext must be used within a ValidationProvider`,\n );\n }\n return context;\n}\n\ntype MessageIdsMap = { [fieldName: string]: Set<string> };\n\ninterface AriaDescriptionContextValue {\n onFieldMessageIdAdd(fieldName: string, id: string): void;\n onFieldMessageIdRemove(fieldName: string, id: string): void;\n getFieldDescription(fieldName: string): string | undefined;\n}\n\n// oxfmt-ignore\nconst AriaDescriptionContext = /* @__PURE__ */ React.createContext<AriaDescriptionContextValue | null>(null);\nAriaDescriptionContext.displayName = \"AriaDescriptionContext\";\nfunction useAriaDescriptionContext() {\n const context = React.useContext(AriaDescriptionContext);\n if (!context) {\n throw new Error(\n `useAriaDescriptionContext must be used within a AriaDescriptionProvider`,\n );\n }\n return context;\n}\n\ntype SlotComponent<T extends Element> = React.ForwardRefExoticComponent<\n React.HTMLAttributes<T> & {\n children?: React.ReactNode;\n } & React.RefAttributes<T>\n>;\n\ntype FormElement = React.ComponentRef<\"form\">;\ninterface PrimitiveFormProps extends React.ComponentPropsWithoutRef<\"form\"> {\n asChild?: boolean;\n}\ninterface FormProps extends PrimitiveFormProps {\n onClearServerErrors?(): void;\n}\n\nconst Form = /* @__PURE__ */ React.forwardRef<FormElement, FormProps>(\n function Form(props, forwardedRef) {\n const { asChild, onClearServerErrors = () => {}, ...rootProps } = props;\n const formRef = React.useRef<FormElement>(null);\n const composedFormRef = useComposedRefs(forwardedRef, formRef);\n\n // custom errors per field\n const [customErrorsMap, setCustomErrorsMap] =\n React.useState<CustomErrorsMap>({});\n\n // native validity per field\n const [validityMap, setValidityMap] = React.useState<ValidityMap>({});\n const getFieldValidity: ValidationContextValue[\"getFieldValidity\"] =\n React.useCallback((fieldName) => validityMap[fieldName], [validityMap]);\n const handleFieldValidityChange: ValidationContextValue[\"onFieldValidityChange\"] =\n React.useCallback(\n (fieldName, validity) =>\n setValidityMap((prevValidityMap) => ({\n ...prevValidityMap,\n [fieldName]: { ...prevValidityMap[fieldName], ...validity },\n })),\n [],\n );\n const handleFieldValiditionClear: ValidationContextValue[\"onFieldValiditionClear\"] =\n React.useCallback((fieldName) => {\n setValidityMap((prevValidityMap) => ({\n ...prevValidityMap,\n [fieldName]: undefined,\n }));\n setCustomErrorsMap((prevCustomErrorsMap) => ({\n ...prevCustomErrorsMap,\n [fieldName]: {},\n }));\n }, []);\n\n // custom matcher entries per field\n const [customMatcherEntriesMap, setCustomMatcherEntriesMap] =\n React.useState<CustomMatcherEntriesMap>({});\n const getFieldCustomMatcherEntries: ValidationContextValue[\"getFieldCustomMatcherEntries\"] =\n React.useCallback(\n (fieldName) => customMatcherEntriesMap[fieldName] ?? [],\n [customMatcherEntriesMap],\n );\n const handleFieldCustomMatcherAdd: ValidationContextValue[\"onFieldCustomMatcherEntryAdd\"] =\n React.useCallback((fieldName, matcherEntry) => {\n setCustomMatcherEntriesMap((prevCustomMatcherEntriesMap) => ({\n ...prevCustomMatcherEntriesMap,\n [fieldName]: [\n ...(prevCustomMatcherEntriesMap[fieldName] ?? []),\n matcherEntry,\n ],\n }));\n }, []);\n const handleFieldCustomMatcherRemove: ValidationContextValue[\"onFieldCustomMatcherEntryRemove\"] =\n React.useCallback((fieldName, matcherEntryId) => {\n setCustomMatcherEntriesMap((prevCustomMatcherEntriesMap) => ({\n ...prevCustomMatcherEntriesMap,\n [fieldName]: (prevCustomMatcherEntriesMap[fieldName] ?? []).filter(\n (matcherEntry) => matcherEntry.id !== matcherEntryId,\n ),\n }));\n }, []);\n\n const getFieldCustomErrors: ValidationContextValue[\"getFieldCustomErrors\"] =\n React.useCallback(\n (fieldName) => customErrorsMap[fieldName] ?? {},\n [customErrorsMap],\n );\n const handleFieldCustomErrorsChange: ValidationContextValue[\"onFieldCustomErrorsChange\"] =\n React.useCallback((fieldName, customErrors) => {\n setCustomErrorsMap((prevCustomErrorsMap) => ({\n ...prevCustomErrorsMap,\n [fieldName]: {\n ...prevCustomErrorsMap[fieldName],\n ...customErrors,\n },\n }));\n }, []);\n\n // messageIds per field\n const [messageIdsMap, setMessageIdsMap] = React.useState<MessageIdsMap>({});\n const handleFieldMessageIdAdd: AriaDescriptionContextValue[\"onFieldMessageIdAdd\"] =\n React.useCallback((fieldName, id) => {\n setMessageIdsMap((prevMessageIdsMap) => {\n const fieldDescriptionIds = new Set(prevMessageIdsMap[fieldName]).add(\n id,\n );\n return { ...prevMessageIdsMap, [fieldName]: fieldDescriptionIds };\n });\n }, []);\n const handleFieldMessageIdRemove: AriaDescriptionContextValue[\"onFieldMessageIdRemove\"] =\n React.useCallback((fieldName, id) => {\n setMessageIdsMap((prevMessageIdsMap) => {\n const fieldDescriptionIds = new Set(prevMessageIdsMap[fieldName]);\n fieldDescriptionIds.delete(id);\n return { ...prevMessageIdsMap, [fieldName]: fieldDescriptionIds };\n });\n }, []);\n const getFieldDescription: AriaDescriptionContextValue[\"getFieldDescription\"] =\n React.useCallback(\n (fieldName) =>\n Array.from(messageIdsMap[fieldName] ?? []).join(\" \") || undefined,\n [messageIdsMap],\n );\n\n const Component = asChild ? (Slot as SlotComponent<FormElement>) : \"form\";\n\n return (\n <ValidationContext.Provider\n value={React.useMemo(\n () => ({\n getFieldValidity: getFieldValidity,\n onFieldValidityChange: handleFieldValidityChange,\n getFieldCustomMatcherEntries: getFieldCustomMatcherEntries,\n onFieldCustomMatcherEntryAdd: handleFieldCustomMatcherAdd,\n onFieldCustomMatcherEntryRemove: handleFieldCustomMatcherRemove,\n getFieldCustomErrors: getFieldCustomErrors,\n onFieldCustomErrorsChange: handleFieldCustomErrorsChange,\n onFieldValiditionClear: handleFieldValiditionClear,\n }),\n [\n getFieldValidity,\n handleFieldValidityChange,\n getFieldCustomMatcherEntries,\n handleFieldCustomMatcherAdd,\n handleFieldCustomMatcherRemove,\n getFieldCustomErrors,\n handleFieldCustomErrorsChange,\n handleFieldValiditionClear,\n ],\n )}\n >\n <AriaDescriptionContext.Provider\n value={React.useMemo(\n () => ({\n onFieldMessageIdAdd: handleFieldMessageIdAdd,\n onFieldMessageIdRemove: handleFieldMessageIdRemove,\n getFieldDescription: getFieldDescription,\n }),\n [\n handleFieldMessageIdAdd,\n handleFieldMessageIdRemove,\n getFieldDescription,\n ],\n )}\n >\n <Component\n {...rootProps}\n ref={composedFormRef}\n // focus first invalid control when the form is submitted\n onInvalid={composeEventHandlers(props.onInvalid, (event) => {\n const firstInvalidControl = getFirstInvalidControl(\n event.currentTarget,\n );\n if (firstInvalidControl === event.target)\n firstInvalidControl.focus();\n\n // prevent default browser UI for form validation\n event.preventDefault();\n })}\n // clear server errors when the form is re-submitted\n onSubmit={(event) => {\n props.onSubmit?.(event);\n onClearServerErrors();\n }}\n // clear server errors when the form is reset\n onReset={composeEventHandlers(props.onReset, onClearServerErrors)}\n />\n </AriaDescriptionContext.Provider>\n </ValidationContext.Provider>\n );\n },\n);\nForm.displayName = \"Form.Root\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormField\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormFieldContextValue {\n id: string;\n name: string;\n serverInvalid: boolean;\n}\n\n// oxfmt-ignore\nconst FormFieldContext = /* @__PURE__ */ React.createContext<FormFieldContextValue | null>(null);\nFormFieldContext.displayName = \"FormFieldContext\";\n\ntype FormFieldElement = React.ComponentRef<\"div\">;\ninterface PrimitiveDivProps extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\ninterface FormFieldProps extends PrimitiveDivProps {\n name: string;\n serverInvalid?: boolean;\n domId?: string;\n}\n\nconst FormField = /* @__PURE__ */ React.forwardRef<\n FormFieldElement,\n FormFieldProps\n>(function FormField(props, forwardedRef) {\n const {\n asChild,\n name,\n serverInvalid = false,\n id: fieldId,\n domId,\n ...domProps\n } = props;\n const validationContext = useValidationContext();\n const validity = validationContext.getFieldValidity(name);\n const generatedId = React.useId();\n const id = fieldId || generatedId;\n const Component = asChild ? (Slot as SlotComponent<FormFieldElement>) : \"div\";\n\n return (\n <FormFieldContext.Provider\n value={React.useMemo(\n () => ({ id, name, serverInvalid }),\n [id, name, serverInvalid],\n )}\n >\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n id={domId}\n {...domProps}\n ref={forwardedRef}\n />\n </FormFieldContext.Provider>\n );\n});\nFormField.displayName = \"Form.Field\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormLabel\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormLabelElement = React.ComponentRef<\"label\">;\ninterface LabelProps extends React.ComponentPropsWithoutRef<\"label\"> {\n asChild?: boolean;\n}\ninterface FormLabelProps extends LabelProps {\n name?: string;\n}\n\nconst FormLabel = /* @__PURE__ */ React.forwardRef<\n FormLabelElement,\n FormLabelProps\n>(function FormLabel(props, forwardedRef) {\n const { asChild, name: nameProp, ...labelProps } = props;\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormLabel\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n const htmlFor = labelProps.htmlFor || fieldContext?.id;\n if (!htmlFor) {\n throw new Error(\n `\\`FormLabel\\` must be used within \\`FormField\\` or specify the \\`htmlFor\\` prop`,\n );\n }\n\n const validity = validationContext.getFieldValidity(name);\n const serverInvalid = fieldContext?.serverInvalid ?? false;\n\n const Component = asChild\n ? (Slot as SlotComponent<FormLabelElement>)\n : \"label\";\n\n return (\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n {...labelProps}\n onMouseDown={(event) => {\n // only prevent text selection if clicking inside the label itself\n const target = event.target as HTMLElement;\n if (target.closest(\"button, input, select, textarea\")) {\n return;\n }\n\n props.onMouseDown?.(event);\n // prevent text selection when double clicking label\n if (!event.defaultPrevented && event.detail > 1) {\n event.preventDefault();\n }\n }}\n ref={forwardedRef}\n htmlFor={htmlFor}\n />\n );\n});\nFormLabel.displayName = \"Form.Label\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormControl\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormControlElement = React.ComponentRef<\"input\">;\ninterface PrimitiveInputProps extends React.ComponentPropsWithoutRef<\"input\"> {\n asChild?: boolean;\n}\ninterface FormControlProps extends PrimitiveInputProps {}\n\nconst FormControl = /* @__PURE__ */ React.forwardRef<\n FormControlElement,\n FormControlProps\n>(function FormControl(props, forwardedRef) {\n const {\n asChild,\n name: nameProp,\n id: idProp,\n \"aria-describedby\": ariaDescribedby,\n ...controlProps\n } = props;\n\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const ariaDescriptionContext = useAriaDescriptionContext();\n\n const ref = React.useRef<FormControlElement>(null);\n const composedRef = useComposedRefs(forwardedRef, ref);\n const name = nameProp || fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormControl\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n const id = idProp || fieldContext?.id;\n if (!id) {\n throw new Error(\n `\\`FormControl\\` must be used within \\`FormField\\` or specify the \\`id\\` prop`,\n );\n }\n\n const customMatcherEntries =\n validationContext.getFieldCustomMatcherEntries(name);\n\n const {\n onFieldValidityChange,\n onFieldCustomErrorsChange,\n onFieldValiditionClear,\n } = validationContext;\n const updateControlValidity = React.useCallback(\n async (control: FormControlElement) => {\n //------------------------------------------------------------------------------------------\n // 1. first, if we have built-in errors we stop here\n\n if (hasBuiltInError(control.validity)) {\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n return;\n }\n\n //------------------------------------------------------------------------------------------\n // 2. then gather the form data to give to custom matchers for cross-comparisons\n\n const formData = control.form\n ? new FormData(control.form)\n : new FormData();\n const matcherArgs: CustomMatcherArgs = [control.value, formData];\n\n //------------------------------------------------------------------------------------------\n // 3. split sync and async custom matcher entries\n\n const syncCustomMatcherEntries: Array<SyncCustomMatcherEntry> = [];\n const ayncCustomMatcherEntries: Array<AsyncCustomMatcherEntry> = [];\n customMatcherEntries.forEach((customMatcherEntry) => {\n if (isAsyncCustomMatcherEntry(customMatcherEntry, matcherArgs)) {\n ayncCustomMatcherEntries.push(customMatcherEntry);\n } else if (isSyncCustomMatcherEntry(customMatcherEntry)) {\n syncCustomMatcherEntries.push(customMatcherEntry);\n }\n });\n\n //------------------------------------------------------------------------------------------\n // 4. run sync custom matchers and update control validity / internal validity + errors\n\n const syncCustomErrors = syncCustomMatcherEntries.map(({ id, match }) => {\n return [id, match(...matcherArgs)] as const;\n });\n const syncCustomErrorsById = Object.fromEntries(syncCustomErrors);\n const hasSyncCustomErrors =\n Object.values(syncCustomErrorsById).some(Boolean);\n const hasCustomError = hasSyncCustomErrors;\n control.setCustomValidity(hasCustomError ? DEFAULT_INVALID_MESSAGE : \"\");\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n onFieldCustomErrorsChange(name, syncCustomErrorsById);\n\n //------------------------------------------------------------------------------------------\n // 5. run async custom matchers and update control validity / internal validity + errors\n\n if (!hasSyncCustomErrors && ayncCustomMatcherEntries.length > 0) {\n const promisedCustomErrors = ayncCustomMatcherEntries.map(\n ({ id, match }) =>\n match(...matcherArgs).then((matches) => [id, matches] as const),\n );\n const asyncCustomErrors = await Promise.all(promisedCustomErrors);\n const asyncCustomErrorsById = Object.fromEntries(asyncCustomErrors);\n const hasAsyncCustomErrors = Object.values(asyncCustomErrorsById).some(\n Boolean,\n );\n const hasCustomError = hasAsyncCustomErrors;\n control.setCustomValidity(\n hasCustomError ? DEFAULT_INVALID_MESSAGE : \"\",\n );\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n onFieldCustomErrorsChange(name, asyncCustomErrorsById);\n }\n },\n [\n customMatcherEntries,\n name,\n onFieldCustomErrorsChange,\n onFieldValidityChange,\n ],\n );\n\n React.useEffect(() => {\n const control = ref.current;\n if (control) {\n // We only want validate on change (native `change` event, not React's `onChange`). This is primarily\n // a UX decision, we don't want to validate on every keystroke and React's `onChange` is the `input` event.\n const handleChange = () => updateControlValidity(control);\n control.addEventListener(\"change\", handleChange);\n return () => control.removeEventListener(\"change\", handleChange);\n }\n }, [updateControlValidity]);\n\n const resetControlValidity = React.useCallback(() => {\n const control = ref.current;\n if (control) {\n control.setCustomValidity(\"\");\n onFieldValiditionClear(name);\n }\n }, [name, onFieldValiditionClear]);\n\n // reset validity and errors when the form is reset\n React.useEffect(() => {\n const form = ref.current?.form;\n if (form) {\n form.addEventListener(\"reset\", resetControlValidity);\n return () => form.removeEventListener(\"reset\", resetControlValidity);\n }\n }, [resetControlValidity]);\n\n const serverInvalid = fieldContext?.serverInvalid ?? false;\n\n // focus first invalid control when fields are set as invalid by server\n React.useEffect(() => {\n if (!serverInvalid) {\n return;\n }\n\n const control = ref.current;\n const form = control?.closest(\"form\");\n const firstInvalidControl = form ? getFirstInvalidControl(form) : null;\n if (firstInvalidControl === control) {\n firstInvalidControl?.focus();\n }\n }, [serverInvalid]);\n\n const validity = validationContext.getFieldValidity(name);\n\n const Component = asChild\n ? (Slot as SlotComponent<FormControlElement>)\n : \"input\";\n\n return (\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n aria-invalid={serverInvalid || undefined}\n aria-describedby={concatAriaDescribedby(\n ariaDescribedby,\n ariaDescriptionContext.getFieldDescription(name),\n )}\n // disable default browser behavior of showing built-in error message on hover\n title=\"\"\n {...controlProps}\n ref={composedRef}\n id={id}\n name={name}\n onInvalid={composeEventHandlers(props.onInvalid, (event) => {\n const control = event.currentTarget;\n updateControlValidity(control);\n })}\n // TODO: Debug; this might be a react compiler error\n // oxlint-disable-next-line react/refs\n onChange={composeEventHandlers(props.onChange, () => {\n // reset validity when user changes value\n resetControlValidity();\n })}\n />\n );\n});\nFormControl.displayName = \"Form.Control\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormMessage\n * -----------------------------------------------------------------------------------------------*/\n\nconst _validityMatchers = [\n \"badInput\",\n \"patternMismatch\",\n \"rangeOverflow\",\n \"rangeUnderflow\",\n \"stepMismatch\",\n \"tooLong\",\n \"tooShort\",\n \"typeMismatch\",\n \"valid\",\n \"valueMissing\",\n] as const;\ntype ValidityMatcher = (typeof _validityMatchers)[number];\n\nconst DEFAULT_INVALID_MESSAGE = \"This value is not valid\";\nconst DEFAULT_BUILT_IN_MESSAGES: Record<ValidityMatcher, string | undefined> = {\n badInput: DEFAULT_INVALID_MESSAGE,\n patternMismatch: \"This value does not match the required pattern\",\n rangeOverflow: \"This value is too large\",\n rangeUnderflow: \"This value is too small\",\n stepMismatch: \"This value does not match the required step\",\n tooLong: \"This value is too long\",\n tooShort: \"This value is too short\",\n typeMismatch: \"This value does not match the required type\",\n valid: undefined,\n valueMissing: \"This value is missing\",\n};\n\ntype FormMessageElement = FormMessageImplElement;\ninterface FormMessageProps extends Omit<FormMessageImplProps, \"name\"> {\n children?: React.ReactNode;\n match?: ValidityMatcher | CustomMatcher;\n forceMatch?: boolean;\n name?: string;\n}\n\nconst FormMessage = /* @__PURE__ */ React.forwardRef<\n FormMessageElement,\n FormMessageProps\n>(function FormMessage(props, forwardedRef) {\n const { match, name: nameProp, ...messageProps } = props;\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormMessage\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n if (match === undefined) {\n return (\n <FormMessageImpl {...messageProps} ref={forwardedRef} name={name}>\n {props.children || DEFAULT_INVALID_MESSAGE}\n </FormMessageImpl>\n );\n } else if (typeof match === \"function\") {\n return (\n <FormCustomMessage\n match={match}\n {...messageProps}\n ref={forwardedRef}\n name={name}\n />\n );\n } else {\n return (\n <FormBuiltInMessage\n match={match}\n {...messageProps}\n ref={forwardedRef}\n name={name}\n />\n );\n }\n});\nFormMessage.displayName = \"Form.Message\";\n\ntype FormBuiltInMessageElement = FormMessageImplElement;\ninterface FormBuiltInMessageProps extends FormMessageImplProps {\n match: ValidityMatcher;\n forceMatch?: boolean;\n name: string;\n}\n\nconst FormBuiltInMessage = /* @__PURE__ */ React.forwardRef<\n FormBuiltInMessageElement,\n FormBuiltInMessageProps\n>(function FormBuiltInMessage(props, forwardedRef) {\n const { match, forceMatch = false, name, children, ...messageProps } = props;\n const validationContext = useValidationContext();\n const validity = validationContext.getFieldValidity(name);\n const matches = forceMatch || validity?.[match];\n\n if (matches) {\n return (\n <FormMessageImpl ref={forwardedRef} {...messageProps} name={name}>\n {children ?? DEFAULT_BUILT_IN_MESSAGES[match]}\n </FormMessageImpl>\n );\n }\n\n return null;\n});\n\ntype FormCustomMessageElement = React.ComponentRef<typeof FormMessageImpl>;\ninterface FormCustomMessageProps extends React.ComponentPropsWithoutRef<\n typeof FormMessageImpl\n> {\n match: CustomMatcher;\n forceMatch?: boolean;\n name: string;\n}\n\nconst FormCustomMessage = /* @__PURE__ */ React.forwardRef<\n FormCustomMessageElement,\n FormCustomMessageProps\n>(function FormCustomMessage(props, forwardedRef) {\n const {\n match,\n forceMatch = false,\n name,\n id: idProp,\n children,\n ...messageProps\n } = props;\n const validationContext = useValidationContext();\n const ref = React.useRef<FormCustomMessageElement>(null);\n const composedRef = useComposedRefs(forwardedRef, ref);\n const generatedId = React.useId();\n const id = idProp || generatedId;\n\n const customMatcherEntry = React.useMemo(() => ({ id, match }), [id, match]);\n const { onFieldCustomMatcherEntryAdd, onFieldCustomMatcherEntryRemove } =\n validationContext;\n React.useEffect(() => {\n onFieldCustomMatcherEntryAdd(name, customMatcherEntry);\n return () => onFieldCustomMatcherEntryRemove(name, customMatcherEntry.id);\n }, [\n customMatcherEntry,\n name,\n onFieldCustomMatcherEntryAdd,\n onFieldCustomMatcherEntryRemove,\n ]);\n\n const validity = validationContext.getFieldValidity(name);\n const customErrors = validationContext.getFieldCustomErrors(name);\n const hasMatchingCustomError = customErrors[id];\n const matches =\n forceMatch ||\n (validity && !hasBuiltInError(validity) && hasMatchingCustomError);\n\n if (matches) {\n return (\n <FormMessageImpl id={id} ref={composedRef} {...messageProps} name={name}>\n {children ?? DEFAULT_INVALID_MESSAGE}\n </FormMessageImpl>\n );\n }\n\n return null;\n});\n\ntype FormMessageImplElement = React.ComponentRef<\"span\">;\ninterface PrimitiveSpanProps extends React.ComponentPropsWithoutRef<\"span\"> {\n asChild?: boolean;\n}\ninterface FormMessageImplProps extends PrimitiveSpanProps {\n name: string;\n}\n\nconst FormMessageImpl = /* @__PURE__ */ React.forwardRef<\n FormMessageImplElement,\n FormMessageImplProps\n>(function FormMessageImpl(props, forwardedRef) {\n const { asChild, id: idProp, name, ...messageProps } = props;\n const ariaDescriptionContext = useAriaDescriptionContext();\n const generatedId = React.useId();\n const id = idProp || generatedId;\n\n const { onFieldMessageIdAdd, onFieldMessageIdRemove } =\n ariaDescriptionContext;\n React.useEffect(() => {\n onFieldMessageIdAdd(name, id);\n return () => onFieldMessageIdRemove(name, id);\n }, [name, id, onFieldMessageIdAdd, onFieldMessageIdRemove]);\n\n const Component = asChild\n ? (Slot as SlotComponent<FormMessageImplElement>)\n : \"span\";\n\n return <Component id={id} {...messageProps} ref={forwardedRef} />;\n});\n\n/* -------------------------------------------------------------------------------------------------\n * FormValidityState\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormValidityStateProps {\n children(validity: ValidityState | undefined): React.ReactNode;\n name?: string;\n}\n\nconst FormValidityState: React.FC<FormValidityStateProps> = (props) => {\n const { name: nameProp, children } = props;\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormValidityState\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n const validity = validationContext.getFieldValidity(name);\n return children(validity);\n};\nFormValidityState.displayName = \"Form.ValidityState\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormSubmit\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormSubmitElement = React.ComponentRef<\"button\">;\ninterface PrimitiveButtonProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\ninterface FormSubmitProps extends PrimitiveButtonProps {}\n\nconst FormSubmit = /* @__PURE__ */ React.forwardRef<\n FormSubmitElement,\n FormSubmitProps\n>(function FormSubmit(props, forwardedRef) {\n const { asChild, ...submitProps } = props;\n const Component = asChild\n ? (Slot as SlotComponent<FormSubmitElement>)\n : \"button\";\n return <Component type=\"submit\" {...submitProps} ref={forwardedRef} />;\n});\nFormSubmit.displayName = \"Form.Submit\";\n\n/* -----------------------------------------------------------------------------------------------*/\n\ntype ValidityStateKey = keyof ValidityState;\ntype SyncCustomMatcher = (value: string, formData: FormData) => boolean;\ntype AsyncCustomMatcher = (\n value: string,\n formData: FormData,\n) => Promise<boolean>;\ntype CustomMatcher = SyncCustomMatcher | AsyncCustomMatcher;\ntype CustomMatcherEntry = { id: string; match: CustomMatcher };\ntype SyncCustomMatcherEntry = { id: string; match: SyncCustomMatcher };\ntype AsyncCustomMatcherEntry = { id: string; match: AsyncCustomMatcher };\ntype CustomMatcherArgs = [string, FormData];\n\nfunction validityStateToObject(validity: ValidityState) {\n const object: any = {};\n for (const key in validity) {\n object[key] = validity[key as ValidityStateKey];\n }\n return object as Record<ValidityStateKey, boolean>;\n}\n\nfunction isHTMLElement(element: any): element is HTMLElement {\n return element instanceof HTMLElement;\n}\n\nfunction isFormControl(element: any): element is { validity: ValidityState } {\n return \"validity\" in element;\n}\n\nfunction isInvalid(control: HTMLElement) {\n return (\n isFormControl(control) &&\n (control.validity.valid === false ||\n control.getAttribute(\"aria-invalid\") === \"true\")\n );\n}\n\nfunction getFirstInvalidControl(form: HTMLFormElement): HTMLElement | null {\n const elements = form.elements;\n const [firstInvalidControl] = Array.from(elements)\n .filter(isHTMLElement)\n .filter(isInvalid);\n return firstInvalidControl ?? null;\n}\n\nfunction isAsyncCustomMatcherEntry(\n entry: CustomMatcherEntry,\n args: CustomMatcherArgs,\n): entry is AsyncCustomMatcherEntry {\n return (\n entry.match.constructor.name === \"AsyncFunction\" ||\n returnsPromise(entry.match, args)\n );\n}\n\nfunction isSyncCustomMatcherEntry(\n entry: CustomMatcherEntry,\n): entry is SyncCustomMatcherEntry {\n return entry.match.constructor.name === \"Function\";\n}\n\nfunction returnsPromise(func: (...args: any[]) => any, args: Array<unknown>) {\n return func(...args) instanceof Promise;\n}\n\nfunction hasBuiltInError(validity: ValidityState) {\n let error = false;\n for (const validityKey in validity) {\n const key = validityKey as ValidityStateKey;\n if (key !== \"valid\" && key !== \"customError\" && validity[key]) {\n error = true;\n break;\n }\n }\n return error;\n}\n\nfunction getValidAttribute(\n validity: ValidityState | undefined,\n serverInvalid: boolean,\n) {\n if (validity?.valid === true && !serverInvalid) return true;\n return undefined;\n}\n\nfunction getInvalidAttribute(\n validity: ValidityState | undefined,\n serverInvalid: boolean,\n) {\n if (validity?.valid === false || serverInvalid) return true;\n return undefined;\n}\n\nfunction concatAriaDescribedby(...values: unknown[]): string | undefined {\n const ids = new Set<string>();\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n for (const id of String(value).trim().split(/\\s+/)) {\n if (id) ids.add(id);\n }\n }\n\n return ids.size > 0 ? Array.from(ids).join(\" \") : undefined;\n}\n\n/* -----------------------------------------------------------------------------------------------*/\n\nexport {\n Form as Root,\n FormField as Field,\n FormLabel as Label,\n FormControl as Control,\n FormMessage as Message,\n FormValidityState as ValidityState,\n FormSubmit as Submit,\n};\n\nexport type {\n FormProps as RootProps,\n FormFieldProps as FieldProps,\n FormLabelProps as LabelProps,\n FormControlProps as ControlProps,\n FormMessageProps as MessageProps,\n FormValidityStateProps as ValidityStateProps,\n FormSubmitProps as SubmitProps,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../../src/components/form.tsx"],"sourcesContent":["\"use client\";\nimport { Slot } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { useComposedEventHandlers } from \"../lib/use-composed-event-handlers.js\";\n\n/* -------------------------------------------------------------------------------------------------\n * Form\n * -----------------------------------------------------------------------------------------------*/\n\ntype ValidityMap = { [fieldName: string]: ValidityState | undefined };\ntype CustomMatcherEntriesMap = { [fieldName: string]: CustomMatcherEntry[] };\ntype CustomErrorsMap = { [fieldName: string]: Record<string, boolean> };\n\ninterface ValidationContextValue {\n getFieldValidity(fieldName: string): ValidityState | undefined;\n onFieldValidityChange(fieldName: string, validity: ValidityState): void;\n\n getFieldCustomMatcherEntries(fieldName: string): CustomMatcherEntry[];\n onFieldCustomMatcherEntryAdd(\n fieldName: string,\n matcherEntry: CustomMatcherEntry,\n ): void;\n onFieldCustomMatcherEntryRemove(\n fieldName: string,\n matcherEntryId: string,\n ): void;\n\n getFieldCustomErrors(fieldName: string): Record<string, boolean>;\n onFieldCustomErrorsChange(\n fieldName: string,\n errors: Record<string, boolean>,\n ): void;\n\n onFieldValiditionClear(fieldName: string): void;\n}\n\n// oxfmt-ignore\nconst ValidationContext = /* @__PURE__ */ React.createContext<ValidationContextValue | null>(null);\nValidationContext.displayName = \"ValidationContext\";\n\nfunction useValidationContext() {\n const context = React.useContext(ValidationContext);\n if (!context) {\n throw new Error(\n `useValidationContext must be used within a ValidationProvider`,\n );\n }\n return context;\n}\n\ntype MessageIdsMap = { [fieldName: string]: Set<string> };\n\ninterface AriaDescriptionContextValue {\n onFieldMessageIdAdd(fieldName: string, id: string): void;\n onFieldMessageIdRemove(fieldName: string, id: string): void;\n getFieldDescription(fieldName: string): string | undefined;\n}\n\n// oxfmt-ignore\nconst AriaDescriptionContext = /* @__PURE__ */ React.createContext<AriaDescriptionContextValue | null>(null);\nAriaDescriptionContext.displayName = \"AriaDescriptionContext\";\nfunction useAriaDescriptionContext() {\n const context = React.useContext(AriaDescriptionContext);\n if (!context) {\n throw new Error(\n `useAriaDescriptionContext must be used within a AriaDescriptionProvider`,\n );\n }\n return context;\n}\n\ntype SlotComponent<T extends Element> = React.ForwardRefExoticComponent<\n React.HTMLAttributes<T> & {\n children?: React.ReactNode;\n } & React.RefAttributes<T>\n>;\n\ntype FormElement = React.ComponentRef<\"form\">;\ninterface PrimitiveFormProps extends React.ComponentPropsWithoutRef<\"form\"> {\n asChild?: boolean;\n}\ninterface FormProps extends PrimitiveFormProps {\n onClearServerErrors?(): void;\n}\n\nconst Form = /* @__PURE__ */ React.forwardRef<FormElement, FormProps>(\n function Form(props, forwardedRef) {\n const { asChild, onClearServerErrors = () => {}, ...rootProps } = props;\n const formRef = React.useRef<FormElement>(null);\n const composedFormRef = useComposedRefs(forwardedRef, formRef);\n\n // custom errors per field\n const [customErrorsMap, setCustomErrorsMap] =\n React.useState<CustomErrorsMap>({});\n\n // native validity per field\n const [validityMap, setValidityMap] = React.useState<ValidityMap>({});\n const getFieldValidity: ValidationContextValue[\"getFieldValidity\"] =\n React.useCallback((fieldName) => validityMap[fieldName], [validityMap]);\n const handleFieldValidityChange: ValidationContextValue[\"onFieldValidityChange\"] =\n React.useCallback(\n (fieldName, validity) =>\n setValidityMap((prevValidityMap) => ({\n ...prevValidityMap,\n [fieldName]: { ...prevValidityMap[fieldName], ...validity },\n })),\n [],\n );\n const handleFieldValiditionClear: ValidationContextValue[\"onFieldValiditionClear\"] =\n React.useCallback((fieldName) => {\n setValidityMap((prevValidityMap) => ({\n ...prevValidityMap,\n [fieldName]: undefined,\n }));\n setCustomErrorsMap((prevCustomErrorsMap) => ({\n ...prevCustomErrorsMap,\n [fieldName]: {},\n }));\n }, []);\n\n // custom matcher entries per field\n const [customMatcherEntriesMap, setCustomMatcherEntriesMap] =\n React.useState<CustomMatcherEntriesMap>({});\n const getFieldCustomMatcherEntries: ValidationContextValue[\"getFieldCustomMatcherEntries\"] =\n React.useCallback(\n (fieldName) => customMatcherEntriesMap[fieldName] ?? [],\n [customMatcherEntriesMap],\n );\n const handleFieldCustomMatcherAdd: ValidationContextValue[\"onFieldCustomMatcherEntryAdd\"] =\n React.useCallback((fieldName, matcherEntry) => {\n setCustomMatcherEntriesMap((prevCustomMatcherEntriesMap) => ({\n ...prevCustomMatcherEntriesMap,\n [fieldName]: [\n ...(prevCustomMatcherEntriesMap[fieldName] ?? []),\n matcherEntry,\n ],\n }));\n }, []);\n const handleFieldCustomMatcherRemove: ValidationContextValue[\"onFieldCustomMatcherEntryRemove\"] =\n React.useCallback((fieldName, matcherEntryId) => {\n setCustomMatcherEntriesMap((prevCustomMatcherEntriesMap) => ({\n ...prevCustomMatcherEntriesMap,\n [fieldName]: (prevCustomMatcherEntriesMap[fieldName] ?? []).filter(\n (matcherEntry) => matcherEntry.id !== matcherEntryId,\n ),\n }));\n }, []);\n\n const getFieldCustomErrors: ValidationContextValue[\"getFieldCustomErrors\"] =\n React.useCallback(\n (fieldName) => customErrorsMap[fieldName] ?? {},\n [customErrorsMap],\n );\n const handleFieldCustomErrorsChange: ValidationContextValue[\"onFieldCustomErrorsChange\"] =\n React.useCallback((fieldName, customErrors) => {\n setCustomErrorsMap((prevCustomErrorsMap) => ({\n ...prevCustomErrorsMap,\n [fieldName]: {\n ...prevCustomErrorsMap[fieldName],\n ...customErrors,\n },\n }));\n }, []);\n\n // messageIds per field\n const [messageIdsMap, setMessageIdsMap] = React.useState<MessageIdsMap>({});\n const handleFieldMessageIdAdd: AriaDescriptionContextValue[\"onFieldMessageIdAdd\"] =\n React.useCallback((fieldName, id) => {\n setMessageIdsMap((prevMessageIdsMap) => {\n const fieldDescriptionIds = new Set(prevMessageIdsMap[fieldName]).add(\n id,\n );\n return { ...prevMessageIdsMap, [fieldName]: fieldDescriptionIds };\n });\n }, []);\n const handleFieldMessageIdRemove: AriaDescriptionContextValue[\"onFieldMessageIdRemove\"] =\n React.useCallback((fieldName, id) => {\n setMessageIdsMap((prevMessageIdsMap) => {\n const fieldDescriptionIds = new Set(prevMessageIdsMap[fieldName]);\n fieldDescriptionIds.delete(id);\n return { ...prevMessageIdsMap, [fieldName]: fieldDescriptionIds };\n });\n }, []);\n const getFieldDescription: AriaDescriptionContextValue[\"getFieldDescription\"] =\n React.useCallback(\n (fieldName) =>\n Array.from(messageIdsMap[fieldName] ?? []).join(\" \") || undefined,\n [messageIdsMap],\n );\n\n const Component = asChild ? (Slot as SlotComponent<FormElement>) : \"form\";\n\n return (\n <ValidationContext.Provider\n value={React.useMemo(\n () => ({\n getFieldValidity,\n onFieldValidityChange: handleFieldValidityChange,\n getFieldCustomMatcherEntries,\n onFieldCustomMatcherEntryAdd: handleFieldCustomMatcherAdd,\n onFieldCustomMatcherEntryRemove: handleFieldCustomMatcherRemove,\n getFieldCustomErrors,\n onFieldCustomErrorsChange: handleFieldCustomErrorsChange,\n onFieldValiditionClear: handleFieldValiditionClear,\n }),\n [\n getFieldValidity,\n handleFieldValidityChange,\n getFieldCustomMatcherEntries,\n handleFieldCustomMatcherAdd,\n handleFieldCustomMatcherRemove,\n getFieldCustomErrors,\n handleFieldCustomErrorsChange,\n handleFieldValiditionClear,\n ],\n )}\n >\n <AriaDescriptionContext.Provider\n value={React.useMemo(\n () => ({\n onFieldMessageIdAdd: handleFieldMessageIdAdd,\n onFieldMessageIdRemove: handleFieldMessageIdRemove,\n getFieldDescription: getFieldDescription,\n }),\n [\n handleFieldMessageIdAdd,\n handleFieldMessageIdRemove,\n getFieldDescription,\n ],\n )}\n >\n <Component\n {...rootProps}\n ref={composedFormRef}\n // focus first invalid control when the form is submitted\n onInvalid={useComposedEventHandlers(\n props.onInvalid,\n React.useCallback((event) => {\n const firstInvalidControl = getFirstInvalidControl(\n event.currentTarget,\n );\n if (firstInvalidControl === event.target)\n firstInvalidControl.focus();\n\n // prevent default browser UI for form validation\n event.preventDefault();\n }, []),\n )}\n // clear server errors when the form is re-submitted\n onSubmit={(event) => {\n props.onSubmit?.(event);\n onClearServerErrors();\n }}\n // clear server errors when the form is reset\n onReset={useComposedEventHandlers(\n props.onReset,\n onClearServerErrors,\n )}\n />\n </AriaDescriptionContext.Provider>\n </ValidationContext.Provider>\n );\n },\n);\nForm.displayName = \"Form.Root\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormField\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormFieldContextValue {\n id: string;\n name: string;\n serverInvalid: boolean;\n}\n\n// oxfmt-ignore\nconst FormFieldContext = /* @__PURE__ */ React.createContext<FormFieldContextValue | null>(null);\nFormFieldContext.displayName = \"FormFieldContext\";\n\ntype FormFieldElement = React.ComponentRef<\"div\">;\ninterface PrimitiveDivProps extends React.ComponentPropsWithoutRef<\"div\"> {\n asChild?: boolean;\n}\ninterface FormFieldProps extends PrimitiveDivProps {\n name: string;\n serverInvalid?: boolean;\n domId?: string;\n}\n\nconst FormField = /* @__PURE__ */ React.forwardRef<\n FormFieldElement,\n FormFieldProps\n>(function FormField(props, forwardedRef) {\n const {\n asChild,\n name,\n serverInvalid = false,\n id: fieldId,\n domId,\n ...domProps\n } = props;\n const validationContext = useValidationContext();\n const validity = validationContext.getFieldValidity(name);\n const generatedId = React.useId();\n const id = fieldId || generatedId;\n const Component = asChild ? (Slot as SlotComponent<FormFieldElement>) : \"div\";\n\n return (\n <FormFieldContext.Provider\n value={React.useMemo(\n () => ({ id, name, serverInvalid }),\n [id, name, serverInvalid],\n )}\n >\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n id={domId}\n {...domProps}\n ref={forwardedRef}\n />\n </FormFieldContext.Provider>\n );\n});\nFormField.displayName = \"Form.Field\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormLabel\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormLabelElement = React.ComponentRef<\"label\">;\ninterface LabelProps extends React.ComponentPropsWithoutRef<\"label\"> {\n asChild?: boolean;\n}\ninterface FormLabelProps extends LabelProps {\n name?: string;\n}\n\nconst FormLabel = /* @__PURE__ */ React.forwardRef<\n FormLabelElement,\n FormLabelProps\n>(function FormLabel(props, forwardedRef) {\n const { asChild, name: nameProp, ...labelProps } = props;\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormLabel\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n const htmlFor = labelProps.htmlFor || fieldContext?.id;\n if (!htmlFor) {\n throw new Error(\n `\\`FormLabel\\` must be used within \\`FormField\\` or specify the \\`htmlFor\\` prop`,\n );\n }\n\n const validity = validationContext.getFieldValidity(name);\n const serverInvalid = fieldContext?.serverInvalid ?? false;\n\n const Component = asChild\n ? (Slot as SlotComponent<FormLabelElement>)\n : \"label\";\n\n return (\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n {...labelProps}\n onMouseDown={(event) => {\n // only prevent text selection if clicking inside the label itself\n const target = event.target as HTMLElement;\n if (target.closest(\"button, input, select, textarea\")) {\n return;\n }\n\n props.onMouseDown?.(event);\n // prevent text selection when double clicking label\n if (!event.defaultPrevented && event.detail > 1) {\n event.preventDefault();\n }\n }}\n ref={forwardedRef}\n htmlFor={htmlFor}\n />\n );\n});\nFormLabel.displayName = \"Form.Label\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormControl\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormControlElement = React.ComponentRef<\"input\">;\ninterface PrimitiveInputProps extends React.ComponentPropsWithoutRef<\"input\"> {\n asChild?: boolean;\n}\ninterface FormControlProps extends PrimitiveInputProps {}\n\nconst FormControl = /* @__PURE__ */ React.forwardRef<\n FormControlElement,\n FormControlProps\n>(function FormControl(props, forwardedRef) {\n const {\n asChild,\n name: nameProp,\n id: idProp,\n \"aria-describedby\": ariaDescribedby,\n ...controlProps\n } = props;\n\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const ariaDescriptionContext = useAriaDescriptionContext();\n\n const ref = React.useRef<FormControlElement>(null);\n const composedRef = useComposedRefs(forwardedRef, ref);\n const name = nameProp || fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormControl\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n const id = idProp || fieldContext?.id;\n if (!id) {\n throw new Error(\n `\\`FormControl\\` must be used within \\`FormField\\` or specify the \\`id\\` prop`,\n );\n }\n\n const customMatcherEntries =\n validationContext.getFieldCustomMatcherEntries(name);\n\n const {\n onFieldValidityChange,\n onFieldCustomErrorsChange,\n onFieldValiditionClear,\n } = validationContext;\n const updateControlValidity = React.useCallback(\n async (event: { currentTarget: FormControlElement }) => {\n const { currentTarget: control } = event;\n //------------------------------------------------------------------------------------------\n // 1. first, if we have built-in errors we stop here\n\n if (hasBuiltInError(control.validity)) {\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n return;\n }\n\n //------------------------------------------------------------------------------------------\n // 2. then gather the form data to give to custom matchers for cross-comparisons\n\n const formData = control.form\n ? new FormData(control.form)\n : new FormData();\n const matcherArgs: CustomMatcherArgs = [control.value, formData];\n\n //------------------------------------------------------------------------------------------\n // 3. split sync and async custom matcher entries\n\n const syncCustomMatcherEntries: Array<SyncCustomMatcherEntry> = [];\n const ayncCustomMatcherEntries: Array<AsyncCustomMatcherEntry> = [];\n customMatcherEntries.forEach((customMatcherEntry) => {\n if (isAsyncCustomMatcherEntry(customMatcherEntry, matcherArgs)) {\n ayncCustomMatcherEntries.push(customMatcherEntry);\n } else if (isSyncCustomMatcherEntry(customMatcherEntry)) {\n syncCustomMatcherEntries.push(customMatcherEntry);\n }\n });\n\n //------------------------------------------------------------------------------------------\n // 4. run sync custom matchers and update control validity / internal validity + errors\n\n const syncCustomErrors = syncCustomMatcherEntries.map(({ id, match }) => {\n return [id, match(...matcherArgs)] as const;\n });\n const syncCustomErrorsById = Object.fromEntries(syncCustomErrors);\n const hasSyncCustomErrors =\n Object.values(syncCustomErrorsById).some(Boolean);\n const hasCustomError = hasSyncCustomErrors;\n control.setCustomValidity(hasCustomError ? DEFAULT_INVALID_MESSAGE : \"\");\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n onFieldCustomErrorsChange(name, syncCustomErrorsById);\n\n //------------------------------------------------------------------------------------------\n // 5. run async custom matchers and update control validity / internal validity + errors\n\n if (!hasSyncCustomErrors && ayncCustomMatcherEntries.length > 0) {\n const promisedCustomErrors = ayncCustomMatcherEntries.map(\n ({ id, match }) =>\n match(...matcherArgs).then((matches) => [id, matches] as const),\n );\n const asyncCustomErrors = await Promise.all(promisedCustomErrors);\n const asyncCustomErrorsById = Object.fromEntries(asyncCustomErrors);\n const hasAsyncCustomErrors = Object.values(asyncCustomErrorsById).some(\n Boolean,\n );\n const hasCustomError = hasAsyncCustomErrors;\n control.setCustomValidity(\n hasCustomError ? DEFAULT_INVALID_MESSAGE : \"\",\n );\n const controlValidity = validityStateToObject(control.validity);\n onFieldValidityChange(name, controlValidity);\n onFieldCustomErrorsChange(name, asyncCustomErrorsById);\n }\n },\n [\n customMatcherEntries,\n name,\n onFieldCustomErrorsChange,\n onFieldValidityChange,\n ],\n );\n\n React.useEffect(() => {\n const control = ref.current;\n if (control) {\n // We only want validate on change (native `change` event, not React's\n // `onChange`). This is primarily a UX decision, we don't want to validate\n // on every keystroke and React's `onChange` is the `input` event.\n const handleChange = () =>\n updateControlValidity({ currentTarget: control });\n control.addEventListener(\"change\", handleChange);\n return () => control.removeEventListener(\"change\", handleChange);\n }\n }, [updateControlValidity]);\n\n const resetControlValidity = React.useCallback(() => {\n const control = ref.current;\n if (control) {\n control.setCustomValidity(\"\");\n onFieldValiditionClear(name);\n }\n }, [name, onFieldValiditionClear]);\n\n // reset validity and errors when the form is reset\n React.useEffect(() => {\n const form = ref.current?.form;\n if (form) {\n form.addEventListener(\"reset\", resetControlValidity);\n return () => form.removeEventListener(\"reset\", resetControlValidity);\n }\n }, [resetControlValidity]);\n\n const serverInvalid = fieldContext?.serverInvalid ?? false;\n\n // focus first invalid control when fields are set as invalid by server\n React.useEffect(() => {\n if (!serverInvalid) {\n return;\n }\n\n const control = ref.current;\n const form = control?.closest(\"form\");\n const firstInvalidControl = form ? getFirstInvalidControl(form) : null;\n if (firstInvalidControl === control) {\n firstInvalidControl?.focus();\n }\n }, [serverInvalid]);\n\n const validity = validationContext.getFieldValidity(name);\n\n const Component = asChild\n ? (Slot as SlotComponent<FormControlElement>)\n : \"input\";\n\n return (\n <Component\n data-valid={getValidAttribute(validity, serverInvalid)}\n data-invalid={getInvalidAttribute(validity, serverInvalid)}\n aria-invalid={serverInvalid || undefined}\n aria-describedby={concatAriaDescribedby(\n ariaDescribedby,\n ariaDescriptionContext.getFieldDescription(name),\n )}\n // disable default browser behavior of showing built-in error message on hover\n title=\"\"\n {...controlProps}\n ref={composedRef}\n id={id}\n name={name}\n onInvalid={useComposedEventHandlers(\n props.onInvalid,\n updateControlValidity,\n )}\n onChange={useComposedEventHandlers(props.onChange, resetControlValidity)}\n />\n );\n});\nFormControl.displayName = \"Form.Control\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormMessage\n * -----------------------------------------------------------------------------------------------*/\n\nconst _validityMatchers = [\n \"badInput\",\n \"patternMismatch\",\n \"rangeOverflow\",\n \"rangeUnderflow\",\n \"stepMismatch\",\n \"tooLong\",\n \"tooShort\",\n \"typeMismatch\",\n \"valid\",\n \"valueMissing\",\n] as const;\ntype ValidityMatcher = (typeof _validityMatchers)[number];\n\nconst DEFAULT_INVALID_MESSAGE = \"This value is not valid\";\nconst DEFAULT_BUILT_IN_MESSAGES: Record<ValidityMatcher, string | undefined> = {\n badInput: DEFAULT_INVALID_MESSAGE,\n patternMismatch: \"This value does not match the required pattern\",\n rangeOverflow: \"This value is too large\",\n rangeUnderflow: \"This value is too small\",\n stepMismatch: \"This value does not match the required step\",\n tooLong: \"This value is too long\",\n tooShort: \"This value is too short\",\n typeMismatch: \"This value does not match the required type\",\n valid: undefined,\n valueMissing: \"This value is missing\",\n};\n\ntype FormMessageElement = FormMessageImplElement;\ninterface FormMessageProps extends Omit<FormMessageImplProps, \"name\"> {\n children?: React.ReactNode;\n match?: ValidityMatcher | CustomMatcher;\n forceMatch?: boolean;\n name?: string;\n}\n\nconst FormMessage = /* @__PURE__ */ React.forwardRef<\n FormMessageElement,\n FormMessageProps\n>(function FormMessage(props, forwardedRef) {\n const { match, name: nameProp, ...messageProps } = props;\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormMessage\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n\n if (match === undefined) {\n return (\n <FormMessageImpl {...messageProps} ref={forwardedRef} name={name}>\n {props.children || DEFAULT_INVALID_MESSAGE}\n </FormMessageImpl>\n );\n } else if (typeof match === \"function\") {\n return (\n <FormCustomMessage\n match={match}\n {...messageProps}\n ref={forwardedRef}\n name={name}\n />\n );\n } else {\n return (\n <FormBuiltInMessage\n match={match}\n {...messageProps}\n ref={forwardedRef}\n name={name}\n />\n );\n }\n});\nFormMessage.displayName = \"Form.Message\";\n\ntype FormBuiltInMessageElement = FormMessageImplElement;\ninterface FormBuiltInMessageProps extends FormMessageImplProps {\n match: ValidityMatcher;\n forceMatch?: boolean;\n name: string;\n}\n\nconst FormBuiltInMessage = /* @__PURE__ */ React.forwardRef<\n FormBuiltInMessageElement,\n FormBuiltInMessageProps\n>(function FormBuiltInMessage(props, forwardedRef) {\n const { match, forceMatch = false, name, children, ...messageProps } = props;\n const validationContext = useValidationContext();\n const validity = validationContext.getFieldValidity(name);\n const matches = forceMatch || validity?.[match];\n\n if (matches) {\n return (\n <FormMessageImpl ref={forwardedRef} {...messageProps} name={name}>\n {children ?? DEFAULT_BUILT_IN_MESSAGES[match]}\n </FormMessageImpl>\n );\n }\n\n return null;\n});\n\ntype FormCustomMessageElement = React.ComponentRef<typeof FormMessageImpl>;\ninterface FormCustomMessageProps extends React.ComponentPropsWithoutRef<\n typeof FormMessageImpl\n> {\n match: CustomMatcher;\n forceMatch?: boolean;\n name: string;\n}\n\nconst FormCustomMessage = /* @__PURE__ */ React.forwardRef<\n FormCustomMessageElement,\n FormCustomMessageProps\n>(function FormCustomMessage(props, forwardedRef) {\n const {\n match,\n forceMatch = false,\n name,\n id: idProp,\n children,\n ...messageProps\n } = props;\n const validationContext = useValidationContext();\n const ref = React.useRef<FormCustomMessageElement>(null);\n const composedRef = useComposedRefs(forwardedRef, ref);\n const generatedId = React.useId();\n const id = idProp || generatedId;\n\n const customMatcherEntry = React.useMemo(() => ({ id, match }), [id, match]);\n const { onFieldCustomMatcherEntryAdd, onFieldCustomMatcherEntryRemove } =\n validationContext;\n React.useEffect(() => {\n onFieldCustomMatcherEntryAdd(name, customMatcherEntry);\n return () => onFieldCustomMatcherEntryRemove(name, customMatcherEntry.id);\n }, [\n customMatcherEntry,\n name,\n onFieldCustomMatcherEntryAdd,\n onFieldCustomMatcherEntryRemove,\n ]);\n\n const validity = validationContext.getFieldValidity(name);\n const customErrors = validationContext.getFieldCustomErrors(name);\n const hasMatchingCustomError = customErrors[id];\n const matches =\n forceMatch ||\n (validity && !hasBuiltInError(validity) && hasMatchingCustomError);\n\n if (matches) {\n return (\n <FormMessageImpl id={id} ref={composedRef} {...messageProps} name={name}>\n {children ?? DEFAULT_INVALID_MESSAGE}\n </FormMessageImpl>\n );\n }\n\n return null;\n});\n\ntype FormMessageImplElement = React.ComponentRef<\"span\">;\ninterface PrimitiveSpanProps extends React.ComponentPropsWithoutRef<\"span\"> {\n asChild?: boolean;\n}\ninterface FormMessageImplProps extends PrimitiveSpanProps {\n name: string;\n}\n\nconst FormMessageImpl = /* @__PURE__ */ React.forwardRef<\n FormMessageImplElement,\n FormMessageImplProps\n>(function FormMessageImpl(props, forwardedRef) {\n const { asChild, id: idProp, name, ...messageProps } = props;\n const ariaDescriptionContext = useAriaDescriptionContext();\n const generatedId = React.useId();\n const id = idProp || generatedId;\n\n const { onFieldMessageIdAdd, onFieldMessageIdRemove } =\n ariaDescriptionContext;\n React.useEffect(() => {\n onFieldMessageIdAdd(name, id);\n return () => onFieldMessageIdRemove(name, id);\n }, [name, id, onFieldMessageIdAdd, onFieldMessageIdRemove]);\n\n const Component = asChild\n ? (Slot as SlotComponent<FormMessageImplElement>)\n : \"span\";\n\n return <Component id={id} {...messageProps} ref={forwardedRef} />;\n});\n\n/* -------------------------------------------------------------------------------------------------\n * FormValidityState\n * -----------------------------------------------------------------------------------------------*/\n\ninterface FormValidityStateProps {\n children(validity: ValidityState | undefined): React.ReactNode;\n name?: string;\n}\n\nconst FormValidityState: React.FC<FormValidityStateProps> = (props) => {\n const { name: nameProp, children } = props;\n const validationContext = useValidationContext();\n const fieldContext = React.useContext(FormFieldContext);\n const name = nameProp ?? fieldContext?.name;\n if (!name) {\n throw new Error(\n `\\`FormValidityState\\` must be used within \\`FormField\\` or specify the \\`name\\` prop`,\n );\n }\n const validity = validationContext.getFieldValidity(name);\n return children(validity);\n};\nFormValidityState.displayName = \"Form.ValidityState\";\n\n/* -------------------------------------------------------------------------------------------------\n * FormSubmit\n * -----------------------------------------------------------------------------------------------*/\n\ntype FormSubmitElement = React.ComponentRef<\"button\">;\ninterface PrimitiveButtonProps extends React.ComponentPropsWithoutRef<\"button\"> {\n asChild?: boolean;\n}\ninterface FormSubmitProps extends PrimitiveButtonProps {}\n\nconst FormSubmit = /* @__PURE__ */ React.forwardRef<\n FormSubmitElement,\n FormSubmitProps\n>(function FormSubmit(props, forwardedRef) {\n const { asChild, ...submitProps } = props;\n const Component = asChild\n ? (Slot as SlotComponent<FormSubmitElement>)\n : \"button\";\n return <Component type=\"submit\" {...submitProps} ref={forwardedRef} />;\n});\nFormSubmit.displayName = \"Form.Submit\";\n\n/* -----------------------------------------------------------------------------------------------*/\n\ntype ValidityStateKey = keyof ValidityState;\ntype SyncCustomMatcher = (value: string, formData: FormData) => boolean;\ntype AsyncCustomMatcher = (\n value: string,\n formData: FormData,\n) => Promise<boolean>;\ntype CustomMatcher = SyncCustomMatcher | AsyncCustomMatcher;\ntype CustomMatcherEntry = { id: string; match: CustomMatcher };\ntype SyncCustomMatcherEntry = { id: string; match: SyncCustomMatcher };\ntype AsyncCustomMatcherEntry = { id: string; match: AsyncCustomMatcher };\ntype CustomMatcherArgs = [string, FormData];\n\nfunction validityStateToObject(validity: ValidityState) {\n const object: any = {};\n for (const key in validity) {\n object[key] = validity[key as ValidityStateKey];\n }\n return object as Record<ValidityStateKey, boolean>;\n}\n\nfunction isHTMLElement(element: any): element is HTMLElement {\n return element instanceof HTMLElement;\n}\n\nfunction isFormControl(element: any): element is { validity: ValidityState } {\n return \"validity\" in element;\n}\n\nfunction isInvalid(control: HTMLElement) {\n return (\n isFormControl(control) &&\n (control.validity.valid === false ||\n control.getAttribute(\"aria-invalid\") === \"true\")\n );\n}\n\nfunction getFirstInvalidControl(form: HTMLFormElement): HTMLElement | null {\n const elements = form.elements;\n const [firstInvalidControl] = Array.from(elements)\n .filter(isHTMLElement)\n .filter(isInvalid);\n return firstInvalidControl ?? null;\n}\n\nfunction isAsyncCustomMatcherEntry(\n entry: CustomMatcherEntry,\n args: CustomMatcherArgs,\n): entry is AsyncCustomMatcherEntry {\n return (\n entry.match.constructor.name === \"AsyncFunction\" ||\n returnsPromise(entry.match, args)\n );\n}\n\nfunction isSyncCustomMatcherEntry(\n entry: CustomMatcherEntry,\n): entry is SyncCustomMatcherEntry {\n return entry.match.constructor.name === \"Function\";\n}\n\nfunction returnsPromise(func: (...args: any[]) => any, args: Array<unknown>) {\n return func(...args) instanceof Promise;\n}\n\nfunction hasBuiltInError(validity: ValidityState) {\n let error = false;\n for (const validityKey in validity) {\n const key = validityKey as ValidityStateKey;\n if (key !== \"valid\" && key !== \"customError\" && validity[key]) {\n error = true;\n break;\n }\n }\n return error;\n}\n\nfunction getValidAttribute(\n validity: ValidityState | undefined,\n serverInvalid: boolean,\n) {\n if (validity?.valid === true && !serverInvalid) return true;\n return undefined;\n}\n\nfunction getInvalidAttribute(\n validity: ValidityState | undefined,\n serverInvalid: boolean,\n) {\n if (validity?.valid === false || serverInvalid) return true;\n return undefined;\n}\n\nfunction concatAriaDescribedby(...values: unknown[]): string | undefined {\n const ids = new Set<string>();\n for (const value of values) {\n if (typeof value !== \"string\") continue;\n for (const id of String(value).trim().split(/\\s+/)) {\n if (id) ids.add(id);\n }\n }\n\n return ids.size > 0 ? Array.from(ids).join(\" \") : undefined;\n}\n\n/* -----------------------------------------------------------------------------------------------*/\n\nexport {\n Form as Root,\n FormField as Field,\n FormLabel as Label,\n FormControl as Control,\n FormMessage as Message,\n FormValidityState as ValidityState,\n FormSubmit as Submit,\n};\n\nexport type {\n FormProps as RootProps,\n FormFieldProps as FieldProps,\n FormLabelProps as LabelProps,\n FormControlProps as ControlProps,\n FormMessageProps as MessageProps,\n FormValidityStateProps as ValidityStateProps,\n FormSubmitProps as SubmitProps,\n};\n"],"mappings":"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"}
@@ -139,6 +139,7 @@ const OtpInput = React.forwardRef(function OtpInput({ style, readOnly, autoCompl
139
139
  } else if (event.key === "Backspace" && char === "") focusSibling(event.currentTarget, { back: true });
140
140
  else if (event.key === "Enter" && char !== "") otpContext.onEnterPressed();
141
141
  },
142
+ "data-index": index,
142
143
  ...props
143
144
  })
144
145
  })
@@ -1 +1 @@
1
- {"version":3,"file":"otp-input.js","names":["Form.Field","Form.Control","TextField.Root"],"sources":["../../../src/components/otp-input.tsx"],"sourcesContent":["\"use client\";\nimport { Grid } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { TextField } from \"./elements.js\";\nimport * as Form from \"./form.js\";\n\ninterface OtpContextValue {\n value: string[];\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n onEnterPressed: () => void;\n onCharChange: (char: string, index: number) => void;\n onChildAdd: (element: HTMLInputElement | null, index: number) => void;\n}\n\nconst OtpContext = React.createContext<OtpContextValue | undefined>(undefined);\nOtpContext.displayName = \"OtpContext\";\n\nconst OtpIndexContext = React.createContext<number>(-1);\nOtpIndexContext.displayName = \"OtpIndexContext\";\n\ntype OtpRootProps = React.ComponentPropsWithoutRef<typeof Grid> & {\n id?: string;\n name?: string;\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n value: string;\n onValueChange: React.Dispatch<React.SetStateAction<string>>;\n autoSubmit?: boolean;\n};\n\nconst OtpRoot = React.forwardRef<HTMLInputElement, OtpRootProps>(\n function OtpRoot(\n {\n name,\n id,\n value: valueProp,\n onValueChange,\n autoSubmit,\n children,\n readOnly,\n state,\n ...gridProps\n },\n forwardedRef,\n ) {\n const [lastCharIndex, setLastCharIndex] = React.useState<number>(0);\n const childCount = React.Children.count(children);\n\n // Internal array state is the source of truth so that empty slots between\n // filled digits are preserved. A `value` string can't encode a gap (e.g.\n // `[\"1\", \"\", \"3\"]` and `[\"1\", \"3\"]` both serialize to \"13\"), so deriving\n // state straight from the prop would shift digits whenever an inner box is\n // cleared or filled out of order.\n const [value, setValueState] = React.useState<string[]>(() =>\n getValueAsArray(valueProp, childCount),\n );\n\n const [previousValueProp, setPreviousValueProp] = React.useState(valueProp);\n if (previousValueProp !== valueProp) {\n setPreviousValueProp(valueProp);\n if (valueProp !== value.join(\"\")) {\n setValueState(getValueAsArray(valueProp, childCount));\n }\n }\n\n const setValue = React.useCallback(\n (action: React.SetStateAction<string[]>) => {\n const nextArrayValue =\n typeof action === \"function\" ? action(value) : action;\n setValueState(nextArrayValue);\n onValueChange(nextArrayValue.join(\"\"));\n },\n [value, onValueChange],\n );\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n const childrenRefs = React.useRef<(HTMLInputElement | null)[]>([]);\n\n const attemptAutoSubmit = React.useCallback(\n (enterPressed = false) => {\n if (\n autoSubmit &&\n value.length > 0 &&\n value.every((char) => char !== \"\") &&\n (enterPressed || lastCharIndex + 1 === childCount)\n ) {\n hiddenInputRef.current?.form?.requestSubmit();\n }\n },\n [value, childCount, lastCharIndex, autoSubmit],\n );\n\n const handleEnterPressed = React.useCallback(\n () => attemptAutoSubmit(true),\n [attemptAutoSubmit],\n );\n\n const handleChildAdd = React.useCallback(\n (element: HTMLInputElement | null, index: number) => {\n childrenRefs.current[index] = element;\n },\n [],\n );\n\n const handleCharChange = React.useCallback(\n (char: string, index: number) => {\n setValue((previousValue) => {\n const newValue = [...previousValue];\n newValue[index] = char;\n return newValue;\n });\n setLastCharIndex(index);\n },\n [setValue],\n );\n\n const otpContext = React.useMemo<OtpContextValue>(\n () =>\n ({\n value,\n readOnly,\n state,\n onEnterPressed: handleEnterPressed,\n onCharChange: handleCharChange,\n onChildAdd: handleChildAdd,\n }) satisfies OtpContextValue,\n [\n value,\n readOnly,\n state,\n handleEnterPressed,\n handleCharChange,\n handleChildAdd,\n ],\n );\n\n React.useEffect(attemptAutoSubmit, [attemptAutoSubmit]);\n\n return (\n <OtpContext.Provider value={otpContext}>\n <Grid\n columns={`repeat(${childCount}, 1fr)`}\n {...gridProps}\n onPaste={(event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData(\"Text\");\n const sanitizedValue = pastedValue\n .replace(/[^\\d]/g, \"\")\n .slice(0, childCount);\n const value = sanitizedValue\n .padEnd(childCount, \"#\")\n .split(\"\")\n .map((char) => (char === \"#\" ? \"\" : char));\n\n setValue(value);\n setLastCharIndex(sanitizedValue.length - 1);\n\n const index = Math.min(sanitizedValue.length, childCount - 1);\n childrenRefs.current?.[index]?.focus();\n }}\n >\n {React.Children.map(children, (child, index) => (\n <OtpIndexContext.Provider value={index}>\n {child}\n </OtpIndexContext.Provider>\n ))}\n <input\n ref={useComposedRefs(forwardedRef, hiddenInputRef)}\n defaultValue={value.join(\"\")}\n minLength={childCount}\n name={name}\n type=\"hidden\"\n />\n </Grid>\n </OtpContext.Provider>\n );\n },\n);\nOtpRoot.displayName = \"Otp.Root\";\n\ninterface OtpInputProps extends TextField.RootProps {\n autoComplete?: \"one-time-code\" | \"off\";\n}\n\nconst OtpInput = React.forwardRef<HTMLInputElement, OtpInputProps>(\n function OtpInput(\n { style, readOnly, autoComplete = \"off\", ...props },\n forwardedRef,\n ) {\n const otpContext = useOptContext();\n const { onChildAdd } = otpContext;\n const index = React.useContext(OtpIndexContext);\n const inputRef = React.useCallback(\n (input: HTMLInputElement | null) => {\n onChildAdd(input, index);\n },\n [onChildAdd, index],\n );\n const composedInputRef = useComposedRefs(forwardedRef, inputRef);\n\n const char = otpContext.value[index] ?? \"\";\n\n return (\n <Form.Field name={`otp-${index}`} asChild>\n <Form.Control asChild>\n <TextField.Root\n ref={composedInputRef}\n autoComplete={index === 0 ? autoComplete : \"off\"}\n color={otpContext.state === \"invalid\" ? \"red\" : undefined}\n inputMode=\"numeric\"\n maxLength={1}\n pattern=\"\\d{1}\"\n readOnly={readOnly ?? otpContext.readOnly}\n size=\"3\"\n value={char}\n variant={otpContext.state === \"invalid\" ? \"soft\" : undefined}\n style={{\n ...style,\n height: \"auto\",\n \"--text-field-padding\": 0,\n textAlign: \"center\",\n }}\n onChange={(event) => {\n // Update the value if it matches the input pattern (number only) or is empty (backspace)\n if (event.target.validity.valid || event.target.value === \"\") {\n const char = event.target.value;\n otpContext.onCharChange(char, index);\n focusSibling(event.currentTarget, { back: char === \"\" });\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"ArrowLeft\") {\n focusSibling(event.currentTarget, { back: true });\n event.preventDefault();\n } else if (event.key === \"ArrowRight\") {\n focusSibling(event.currentTarget);\n event.preventDefault();\n } else if (event.key === \"Backspace\" && char === \"\") {\n focusSibling(event.currentTarget, { back: true });\n } else if (event.key === \"Enter\" && char !== \"\") {\n otpContext.onEnterPressed();\n }\n }}\n {...props}\n />\n </Form.Control>\n </Form.Field>\n );\n },\n);\nOtpInput.displayName = \"Otp.Input\";\n\nconst useOptContext = () => {\n const optContext = React.useContext(OtpContext);\n if (!optContext) {\n throw new Error(\n \"OtpInput compound components cannot be rendered outside the OtpRoot component\",\n );\n }\n\n return optContext;\n};\n\nfunction focusSibling(input: HTMLInputElement, { back = false } = {}) {\n const sibling = back\n ? input.parentElement?.previousSibling\n : input.parentElement?.nextSibling;\n const siblingInput = sibling?.firstChild;\n if (siblingInput && siblingInput instanceof HTMLInputElement) {\n siblingInput?.focus();\n siblingInput?.select();\n }\n}\n\nconst getValueAsArray = (value: string | undefined, length: number) => {\n if (!value) {\n return createEmptyArray(length);\n }\n\n return createEmptyArray(length).map((_, index) => value?.[index] ?? \"\");\n};\n\nconst createEmptyArray = (length: number): string[] =>\n Array.from<string>({ length }).fill(\"\");\nexport { OtpRoot as Root, OtpInput as Input };\n"],"mappings":"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"}
1
+ {"version":3,"file":"otp-input.js","names":["Form.Field","Form.Control","TextField.Root"],"sources":["../../../src/components/otp-input.tsx"],"sourcesContent":["\"use client\";\nimport { Grid } from \"@radix-ui/themes\";\nimport * as React from \"react\";\nimport { useComposedRefs } from \"../lib/compose-refs.js\";\nimport { TextField } from \"./elements.js\";\nimport * as Form from \"./form.js\";\n\ninterface OtpContextValue {\n value: string[];\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n onEnterPressed: () => void;\n onCharChange: (char: string, index: number) => void;\n onChildAdd: (element: HTMLInputElement | null, index: number) => void;\n}\n\nconst OtpContext = React.createContext<OtpContextValue | undefined>(undefined);\nOtpContext.displayName = \"OtpContext\";\n\nconst OtpIndexContext = React.createContext<number>(-1);\nOtpIndexContext.displayName = \"OtpIndexContext\";\n\ntype OtpRootProps = React.ComponentPropsWithoutRef<typeof Grid> & {\n id?: string;\n name?: string;\n readOnly?: boolean;\n state?: \"valid\" | \"invalid\";\n value: string;\n onValueChange: React.Dispatch<React.SetStateAction<string>>;\n autoSubmit?: boolean;\n};\n\nconst OtpRoot = React.forwardRef<HTMLInputElement, OtpRootProps>(\n function OtpRoot(\n {\n name,\n id,\n value: valueProp,\n onValueChange,\n autoSubmit,\n children,\n readOnly,\n state,\n ...gridProps\n },\n forwardedRef,\n ) {\n const [lastCharIndex, setLastCharIndex] = React.useState<number>(0);\n const childCount = React.Children.count(children);\n\n // Internal array state is the source of truth so that empty slots between\n // filled digits are preserved. A `value` string can't encode a gap (e.g.\n // `[\"1\", \"\", \"3\"]` and `[\"1\", \"3\"]` both serialize to \"13\"), so deriving\n // state straight from the prop would shift digits whenever an inner box is\n // cleared or filled out of order.\n const [value, setValueState] = React.useState<string[]>(() =>\n getValueAsArray(valueProp, childCount),\n );\n\n const [previousValueProp, setPreviousValueProp] = React.useState(valueProp);\n if (previousValueProp !== valueProp) {\n setPreviousValueProp(valueProp);\n if (valueProp !== value.join(\"\")) {\n setValueState(getValueAsArray(valueProp, childCount));\n }\n }\n\n const setValue = React.useCallback(\n (action: React.SetStateAction<string[]>) => {\n const nextArrayValue =\n typeof action === \"function\" ? action(value) : action;\n setValueState(nextArrayValue);\n onValueChange(nextArrayValue.join(\"\"));\n },\n [value, onValueChange],\n );\n\n const hiddenInputRef = React.useRef<HTMLInputElement>(null);\n const childrenRefs = React.useRef<(HTMLInputElement | null)[]>([]);\n\n const attemptAutoSubmit = React.useCallback(\n (enterPressed = false) => {\n if (\n autoSubmit &&\n value.length > 0 &&\n value.every((char) => char !== \"\") &&\n (enterPressed || lastCharIndex + 1 === childCount)\n ) {\n hiddenInputRef.current?.form?.requestSubmit();\n }\n },\n [value, childCount, lastCharIndex, autoSubmit],\n );\n\n const handleEnterPressed = React.useCallback(\n () => attemptAutoSubmit(true),\n [attemptAutoSubmit],\n );\n\n const handleChildAdd = React.useCallback(\n (element: HTMLInputElement | null, index: number) => {\n childrenRefs.current[index] = element;\n },\n [],\n );\n\n const handleCharChange = React.useCallback(\n (char: string, index: number) => {\n setValue((previousValue) => {\n const newValue = [...previousValue];\n newValue[index] = char;\n return newValue;\n });\n setLastCharIndex(index);\n },\n [setValue],\n );\n\n const otpContext = React.useMemo<OtpContextValue>(\n () =>\n ({\n value,\n readOnly,\n state,\n onEnterPressed: handleEnterPressed,\n onCharChange: handleCharChange,\n onChildAdd: handleChildAdd,\n }) satisfies OtpContextValue,\n [\n value,\n readOnly,\n state,\n handleEnterPressed,\n handleCharChange,\n handleChildAdd,\n ],\n );\n\n React.useEffect(attemptAutoSubmit, [attemptAutoSubmit]);\n\n return (\n <OtpContext.Provider value={otpContext}>\n <Grid\n columns={`repeat(${childCount}, 1fr)`}\n {...gridProps}\n onPaste={(event: React.ClipboardEvent<HTMLDivElement>) => {\n event.preventDefault();\n const pastedValue = event.clipboardData.getData(\"Text\");\n const sanitizedValue = pastedValue\n .replace(/[^\\d]/g, \"\")\n .slice(0, childCount);\n const value = sanitizedValue\n .padEnd(childCount, \"#\")\n .split(\"\")\n .map((char) => (char === \"#\" ? \"\" : char));\n\n setValue(value);\n setLastCharIndex(sanitizedValue.length - 1);\n\n const index = Math.min(sanitizedValue.length, childCount - 1);\n childrenRefs.current?.[index]?.focus();\n }}\n >\n {React.Children.map(children, (child, index) => (\n <OtpIndexContext.Provider value={index}>\n {child}\n </OtpIndexContext.Provider>\n ))}\n <input\n ref={useComposedRefs(forwardedRef, hiddenInputRef)}\n defaultValue={value.join(\"\")}\n minLength={childCount}\n name={name}\n type=\"hidden\"\n />\n </Grid>\n </OtpContext.Provider>\n );\n },\n);\nOtpRoot.displayName = \"Otp.Root\";\n\ninterface OtpInputProps extends TextField.RootProps {\n autoComplete?: \"one-time-code\" | \"off\";\n}\n\nconst OtpInput = React.forwardRef<HTMLInputElement, OtpInputProps>(\n function OtpInput(\n { style, readOnly, autoComplete = \"off\", ...props },\n forwardedRef,\n ) {\n const otpContext = useOptContext();\n const { onChildAdd } = otpContext;\n const index = React.useContext(OtpIndexContext);\n const inputRef = React.useCallback(\n (input: HTMLInputElement | null) => {\n onChildAdd(input, index);\n },\n [onChildAdd, index],\n );\n const composedInputRef = useComposedRefs(forwardedRef, inputRef);\n\n const char = otpContext.value[index] ?? \"\";\n\n return (\n <Form.Field name={`otp-${index}`} asChild>\n <Form.Control asChild>\n <TextField.Root\n ref={composedInputRef}\n autoComplete={index === 0 ? autoComplete : \"off\"}\n color={otpContext.state === \"invalid\" ? \"red\" : undefined}\n inputMode=\"numeric\"\n maxLength={1}\n pattern=\"\\d{1}\"\n readOnly={readOnly ?? otpContext.readOnly}\n size=\"3\"\n value={char}\n variant={otpContext.state === \"invalid\" ? \"soft\" : undefined}\n style={{\n ...style,\n height: \"auto\",\n \"--text-field-padding\": 0,\n textAlign: \"center\",\n }}\n onChange={(event) => {\n // Update the value if it matches the input pattern (number only) or is empty (backspace)\n if (event.target.validity.valid || event.target.value === \"\") {\n const char = event.target.value;\n otpContext.onCharChange(char, index);\n focusSibling(event.currentTarget, { back: char === \"\" });\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"ArrowLeft\") {\n focusSibling(event.currentTarget, { back: true });\n event.preventDefault();\n } else if (event.key === \"ArrowRight\") {\n focusSibling(event.currentTarget);\n event.preventDefault();\n } else if (event.key === \"Backspace\" && char === \"\") {\n focusSibling(event.currentTarget, { back: true });\n } else if (event.key === \"Enter\" && char !== \"\") {\n otpContext.onEnterPressed();\n }\n }}\n // TODO(v2): remove; we're no longer using it\n data-index={index}\n {...props}\n />\n </Form.Control>\n </Form.Field>\n );\n },\n);\nOtpInput.displayName = \"Otp.Input\";\n\nconst useOptContext = () => {\n const optContext = React.useContext(OtpContext);\n if (!optContext) {\n throw new Error(\n \"OtpInput compound components cannot be rendered outside the OtpRoot component\",\n );\n }\n\n return optContext;\n};\n\nfunction focusSibling(input: HTMLInputElement, { back = false } = {}) {\n const sibling = back\n ? input.parentElement?.previousSibling\n : input.parentElement?.nextSibling;\n const siblingInput = sibling?.firstChild;\n if (siblingInput && siblingInput instanceof HTMLInputElement) {\n siblingInput?.focus();\n siblingInput?.select();\n }\n}\n\nconst getValueAsArray = (value: string | undefined, length: number) => {\n if (!value) {\n return createEmptyArray(length);\n }\n\n return createEmptyArray(length).map((_, index) => value?.[index] ?? \"\");\n};\n\nconst createEmptyArray = (length: number): string[] =>\n Array.from<string>({ length }).fill(\"\");\nexport { OtpRoot as Root, OtpInput as Input };\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { useWorkOsApiUrl } from "./lib/widgets-context.js";
3
+ import { clientGraphqlQueryKey } from "./api/client-graphql/query-keys.js";
3
4
  import { ApiProvider, useApiReady } from "./api/api-provider.js";
4
- import { clientGraphqlQueryKey, useClientGraphqlMutation, useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
+ import { useClientGraphqlMutation, useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
6
  import { ErrorBoundary } from "./components/error-boundary.js";
6
7
  import { openUrlViaForm } from "./lib/utils.js";
7
8
  import { usePermissions } from "./lib/use-permissions.js";
@@ -1 +1 @@
1
- {"version":3,"file":"directory-sync.client.js","names":["DirectorySyncPresentational"],"sources":["../../src/directory-sync.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport type {\n DirectoryFieldsFragment,\n Sdk,\n} from \"./api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { usePermissions } from \"./lib/use-permissions.js\";\nimport { openUrlViaForm } from \"./lib/utils.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n DirectoryState,\n DirectorySyncError,\n DirectorySyncLoading,\n DirectorySync as DirectorySyncPresentational,\n isDirectoryState,\n} from \"./widgets/directory-sync/directory-sync.js\";\nimport type {\n DirectorySyncErrorProps,\n DirectorySyncLoadingProps,\n} from \"./widgets/directory-sync/directory-sync.js\";\n\nconst DIRECTORIES_PAGE_SIZE = 100;\n\nasync function listAllDirectoryConnections(\n sdk: Sdk,\n): Promise<DirectoryFieldsFragment[]> {\n const directories: DirectoryFieldsFragment[] = [];\n let after: string | null = null;\n do {\n const { directoryConnections } = await sdk.ListDirectoryConnections({\n after,\n limit: DIRECTORIES_PAGE_SIZE,\n });\n directories.push(...directoryConnections.data);\n after = directoryConnections.listMetadata.after ?? null;\n } while (after !== null);\n // Directories awaiting a type or mid-deletion are not usable by the\n // organization; treat them as not set up.\n return directories.filter(\n (directory) =>\n isDirectoryState(directory.state) &&\n directory.state !== DirectoryState.requires_type &&\n directory.state !== DirectoryState.deleting,\n );\n}\n\ninterface DirectorySyncProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst DirectorySync: React.FC<DirectorySyncProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError {...domProps} error={error} />\n )}\n >\n <ApiProvider\n widgetType=\"directory-sync\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <DirectorySyncImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface DirectorySyncImplProps extends WidgetRootDomProps {}\n\nconst DirectorySyncImpl: React.FC<DirectorySyncImplProps> = (props) => {\n const isApiReady = useApiReady();\n const {\n data: directories,\n isLoading,\n isError,\n error,\n } = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDirectoryConnections\"),\n queryFn: listAllDirectoryConnections,\n });\n const permissionsQuery = usePermissions(\"widgets:dsync:manage\");\n const { mutate: openAdminPortal, isPending: isOpeningAdminPortal } =\n useClientGraphqlMutation({\n mutationFn: (sdk) => sdk.CreateAdminPortalLink({ intent: \"Dsync\" }),\n onSuccess: (data) => {\n openUrlViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n if (!isApiReady || isLoading || permissionsQuery.isLoading) {\n return <DirectorySyncLoading {...props} />;\n }\n\n if (permissionsQuery.isError || isError) {\n return (\n <DirectorySyncError error={permissionsQuery.error || error} {...props} />\n );\n }\n\n const adminPortalProps = {\n onOpenAdminPortal: () => openAdminPortal(),\n isOpeningAdminPortal,\n };\n\n if (!directories?.length) {\n return (\n <DirectorySyncPresentational\n {...props}\n state={DirectoryState.unlinked}\n {...adminPortalProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError error={error} {...props} />\n )}\n >\n {directories.map((directory) => {\n const { id, state, type, metadata, lastSyncRunAt } = directory;\n const commonProps = {\n ...props,\n type,\n metadata,\n lastSyncAt: lastSyncRunAt ?? null,\n ...adminPortalProps,\n };\n\n if (!isDirectoryState(state)) {\n return null;\n }\n\n switch (state) {\n case DirectoryState.invalid_credentials:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory credentials are invalid or have expired. Please re-authenticate to resume syncing.\"\n />\n );\n case DirectoryState.linked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.validating:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.deleting:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.unlinked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.requires_type:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory requires additional configuration. Please complete setup to begin syncing.\"\n />\n );\n }\n })}\n </ErrorBoundary>\n );\n};\n\nexport type {\n DirectorySyncProps,\n DirectorySyncLoadingProps,\n DirectorySyncErrorProps,\n};\nexport { DirectorySync, DirectorySyncLoading, DirectorySyncError };\n"],"mappings":";;;;;;;;;;;AA+BA,MAAM,wBAAwB;AAE9B,eAAe,4BACb,KACoC;CACpC,MAAM,cAAyC,CAAC;CAChD,IAAI,QAAuB;CAC3B,GAAG;EACD,MAAM,EAAE,yBAAyB,MAAM,IAAI,yBAAyB;GAClE;GACA,OAAO;EACT,CAAC;EACD,YAAY,KAAK,GAAG,qBAAqB,IAAI;EAC7C,QAAQ,qBAAqB,aAAa,SAAS;CACrD,SAAS,UAAU;CAGnB,OAAO,YAAY,QAChB,cACC,iBAAiB,UAAU,KAAK,KAChC,UAAU,UAAU,eAAe,iBACnC,UAAU,UAAU,eAAe,QACvC;AACF;AAMA,MAAM,iBAA+C,EACnD,WACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAAoB,GAAI;GAAiB;EAAQ,CAAA;EAGnD,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,mBAAD,EAAmB,GAAI,SAAW,CAAA;EACvB,CAAA;CACA,CAAA;AAEnB;AAIA,MAAM,qBAAuD,UAAU;CACrE,MAAM,aAAa,YAAY;CAC/B,MAAM,EACJ,MAAM,aACN,WACA,SACA,UACE,sBAAsB;EACxB,UAAU,sBAAsB,0BAA0B;EAC1D,SAAS;CACX,CAAC;CACD,MAAM,mBAAmB,eAAe,sBAAsB;CAC9D,MAAM,EAAE,QAAQ,iBAAiB,WAAW,yBAC1C,yBAAyB;EACvB,aAAa,QAAQ,IAAI,sBAAsB,EAAE,QAAQ,QAAQ,CAAC;EAClE,YAAY,SAAS;GACnB,eAAe,KAAK,sBAAsB,MAAM;IAC9C,QAAQ;IACR,KAAK;GACP,CAAC;EACH;CACF,CAAC;CAEH,IAAI,CAAC,cAAc,aAAa,iBAAiB,WAC/C,OAAO,oBAAC,sBAAD,EAAsB,GAAI,MAAQ,CAAA;CAG3C,IAAI,iBAAiB,WAAW,SAC9B,OACE,oBAAC,oBAAD;EAAoB,OAAO,iBAAiB,SAAS;EAAO,GAAI;CAAQ,CAAA;CAI5E,MAAM,mBAAmB;EACvB,yBAAyB,gBAAgB;EACzC;CACF;CAEA,IAAI,CAAC,aAAa,QAChB,OACE,oBAACA,iBAAD;EACE,GAAI;EACJ,OAAO,eAAe;EACtB,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAA2B;GAAO,GAAI;EAAQ,CAAA;EAG/C,UAAA,YAAY,KAAK,cAAc;GAC9B,MAAM,EAAE,IAAI,OAAO,MAAM,UAAU,kBAAkB;GACrD,MAAM,cAAc;IAClB,GAAG;IACH;IACA;IACA,YAAY,iBAAiB;IAC7B,GAAG;GACL;GAEA,IAAI,CAAC,iBAAiB,KAAK,GACzB,OAAO;GAGT,QAAQ,OAAR;IACE,KAAK,eAAe,qBAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;IAEL,KAAK,eAAe,QAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,YAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,eAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;GAEP;EACF,CAAC;CACY,CAAA;AAEnB"}
1
+ {"version":3,"file":"directory-sync.client.js","names":["DirectorySyncPresentational"],"sources":["../../src/directory-sync.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport type {\n DirectoryFieldsFragment,\n Sdk,\n} from \"./api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { usePermissions } from \"./lib/use-permissions.js\";\nimport { openUrlViaForm } from \"./lib/utils.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n DirectoryState,\n DirectorySyncError,\n DirectorySyncLoading,\n DirectorySync as DirectorySyncPresentational,\n isDirectoryState,\n} from \"./widgets/directory-sync/directory-sync.js\";\nimport type {\n DirectorySyncErrorProps,\n DirectorySyncLoadingProps,\n} from \"./widgets/directory-sync/directory-sync.js\";\n\nconst DIRECTORIES_PAGE_SIZE = 100;\n\nasync function listAllDirectoryConnections(\n sdk: Sdk,\n): Promise<DirectoryFieldsFragment[]> {\n const directories: DirectoryFieldsFragment[] = [];\n let after: string | null = null;\n do {\n const { directoryConnections } = await sdk.ListDirectoryConnections({\n after,\n limit: DIRECTORIES_PAGE_SIZE,\n });\n directories.push(...directoryConnections.data);\n after = directoryConnections.listMetadata.after ?? null;\n } while (after !== null);\n // Directories awaiting a type or mid-deletion are not usable by the\n // organization; treat them as not set up.\n return directories.filter(\n (directory) =>\n isDirectoryState(directory.state) &&\n directory.state !== DirectoryState.requires_type &&\n directory.state !== DirectoryState.deleting,\n );\n}\n\ninterface DirectorySyncProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst DirectorySync: React.FC<DirectorySyncProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError {...domProps} error={error} />\n )}\n >\n <ApiProvider\n widgetType=\"directory-sync\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <DirectorySyncImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface DirectorySyncImplProps extends WidgetRootDomProps {}\n\nconst DirectorySyncImpl: React.FC<DirectorySyncImplProps> = (props) => {\n const isApiReady = useApiReady();\n const {\n data: directories,\n isLoading,\n isError,\n error,\n } = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListDirectoryConnections\"),\n queryFn: listAllDirectoryConnections,\n });\n const permissionsQuery = usePermissions(\"widgets:dsync:manage\");\n const { mutate: openAdminPortal, isPending: isOpeningAdminPortal } =\n useClientGraphqlMutation({\n mutationFn: (sdk) => sdk.CreateAdminPortalLink({ intent: \"Dsync\" }),\n onSuccess: (data) => {\n openUrlViaForm(data.createAdminPortalLink.link, {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n });\n },\n });\n\n if (!isApiReady || isLoading || permissionsQuery.isLoading) {\n return <DirectorySyncLoading {...props} />;\n }\n\n if (permissionsQuery.isError || isError) {\n return (\n <DirectorySyncError error={permissionsQuery.error || error} {...props} />\n );\n }\n\n const adminPortalProps = {\n onOpenAdminPortal: () => openAdminPortal(),\n isOpeningAdminPortal,\n };\n\n if (!directories?.length) {\n return (\n <DirectorySyncPresentational\n {...props}\n state={DirectoryState.unlinked}\n {...adminPortalProps}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <DirectorySyncError error={error} {...props} />\n )}\n >\n {directories.map((directory) => {\n const { id, state, type, metadata, lastSyncRunAt } = directory;\n const commonProps = {\n ...props,\n type,\n metadata,\n lastSyncAt: lastSyncRunAt ?? null,\n ...adminPortalProps,\n };\n\n if (!isDirectoryState(state)) {\n return null;\n }\n\n switch (state) {\n case DirectoryState.invalid_credentials:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory credentials are invalid or have expired. Please re-authenticate to resume syncing.\"\n />\n );\n case DirectoryState.linked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.validating:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.deleting:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.unlinked:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n />\n );\n case DirectoryState.requires_type:\n return (\n <DirectorySyncPresentational\n key={id}\n {...commonProps}\n state={state}\n errorMessage=\"Your directory requires additional configuration. Please complete setup to begin syncing.\"\n />\n );\n }\n })}\n </ErrorBoundary>\n );\n};\n\nexport type {\n DirectorySyncProps,\n DirectorySyncLoadingProps,\n DirectorySyncErrorProps,\n};\nexport { DirectorySync, DirectorySyncLoading, DirectorySyncError };\n"],"mappings":";;;;;;;;;;;;AA+BA,MAAM,wBAAwB;AAE9B,eAAe,4BACb,KACoC;CACpC,MAAM,cAAyC,CAAC;CAChD,IAAI,QAAuB;CAC3B,GAAG;EACD,MAAM,EAAE,yBAAyB,MAAM,IAAI,yBAAyB;GAClE;GACA,OAAO;EACT,CAAC;EACD,YAAY,KAAK,GAAG,qBAAqB,IAAI;EAC7C,QAAQ,qBAAqB,aAAa,SAAS;CACrD,SAAS,UAAU;CAGnB,OAAO,YAAY,QAChB,cACC,iBAAiB,UAAU,KAAK,KAChC,UAAU,UAAU,eAAe,iBACnC,UAAU,UAAU,eAAe,QACvC;AACF;AAMA,MAAM,iBAA+C,EACnD,WACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAAoB,GAAI;GAAiB;EAAQ,CAAA;EAGnD,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,mBAAD,EAAmB,GAAI,SAAW,CAAA;EACvB,CAAA;CACA,CAAA;AAEnB;AAIA,MAAM,qBAAuD,UAAU;CACrE,MAAM,aAAa,YAAY;CAC/B,MAAM,EACJ,MAAM,aACN,WACA,SACA,UACE,sBAAsB;EACxB,UAAU,sBAAsB,0BAA0B;EAC1D,SAAS;CACX,CAAC;CACD,MAAM,mBAAmB,eAAe,sBAAsB;CAC9D,MAAM,EAAE,QAAQ,iBAAiB,WAAW,yBAC1C,yBAAyB;EACvB,aAAa,QAAQ,IAAI,sBAAsB,EAAE,QAAQ,QAAQ,CAAC;EAClE,YAAY,SAAS;GACnB,eAAe,KAAK,sBAAsB,MAAM;IAC9C,QAAQ;IACR,KAAK;GACP,CAAC;EACH;CACF,CAAC;CAEH,IAAI,CAAC,cAAc,aAAa,iBAAiB,WAC/C,OAAO,oBAAC,sBAAD,EAAsB,GAAI,MAAQ,CAAA;CAG3C,IAAI,iBAAiB,WAAW,SAC9B,OACE,oBAAC,oBAAD;EAAoB,OAAO,iBAAiB,SAAS;EAAO,GAAI;CAAQ,CAAA;CAI5E,MAAM,mBAAmB;EACvB,yBAAyB,gBAAgB;EACzC;CACF;CAEA,IAAI,CAAC,aAAa,QAChB,OACE,oBAACA,iBAAD;EACE,GAAI;EACJ,OAAO,eAAe;EACtB,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,oBAAD;GAA2B;GAAO,GAAI;EAAQ,CAAA;EAG/C,UAAA,YAAY,KAAK,cAAc;GAC9B,MAAM,EAAE,IAAI,OAAO,MAAM,UAAU,kBAAkB;GACrD,MAAM,cAAc;IAClB,GAAG;IACH;IACA;IACA,YAAY,iBAAiB;IAC7B,GAAG;GACL;GAEA,IAAI,CAAC,iBAAiB,KAAK,GACzB,OAAO;GAGT,QAAQ,OAAR;IACE,KAAK,eAAe,qBAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;IAEL,KAAK,eAAe,QAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,YAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,UAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;IACR,GAHM,EAGN;IAEL,KAAK,eAAe,eAClB,OACE,oBAACA,iBAAD;KAEE,GAAI;KACG;KACP,cAAa;IACd,GAJM,EAIN;GAEP;EACF,CAAC;CACY,CAAA;AAEnB"}
@@ -1,5 +1,6 @@
1
+ import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
1
2
  import { ApiError } from "../../api/errors.js";
2
- import { clientGraphqlQueryKey, useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
3
+ import { useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
3
4
  import { useApiKeysContext } from "../../widgets/api-keys/api-keys-context.js";
4
5
  import { keepPreviousData, useQueryClient } from "@tanstack/react-query";
5
6
  //#region src/lib/api/api-key.ts
@@ -1 +1 @@
1
- {"version":3,"file":"api-key.js","names":[],"sources":["../../../../src/lib/api/api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ApiKeyOwnerType,\n CreateOrganizationApiKeyMutation,\n ExpireOrganizationApiKeyMutation,\n ListApiKeyPermissionsQuery,\n OrganizationApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { ApiError } from \"../../api/errors.js\";\nimport { useApiKeysContext } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type { ApiKeysContextValue } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type {\n CreateOrganizationApiKeyRequest,\n CreateOrganizationApiKeyResponse,\n ListOrganizationApiKeyPermission,\n ListOrganizationApiKeyPermissionsParams,\n ListOrganizationApiKeyPermissionsResponse,\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"./types.js\";\n\nexport const API_KEYS_PAGE_SIZE = 10;\n\ntype ApiKeyPermissionsParams = ListOrganizationApiKeyPermissionsParams;\n\nfunction toApiKeyPermissions(\n list: ListApiKeyPermissionsQuery[\"permissions\"],\n): ListOrganizationApiKeyPermissionsResponse {\n return {\n data: list.data.map((permission): ListOrganizationApiKeyPermission => ({\n id: permission.id,\n slug: permission.slug,\n name: permission.name,\n description: permission.description ?? null,\n })),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n };\n}\n\nexport const useListApiKeyPermissions = (\n apiKeyOwnerType: ApiKeyOwnerType,\n params: ApiKeyPermissionsParams = {},\n) => {\n const variables = {\n apiKeyOwnerType,\n after: params.after,\n before: params.before,\n limit: params.limit,\n search: params.search || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListApiKeyPermissions\", variables),\n queryFn: async (sdk) => {\n const { permissions } = await sdk.ListApiKeyPermissions(variables);\n return permissions;\n },\n select: toApiKeyPermissions,\n placeholderData: keepPreviousData,\n });\n};\n\nexport const useListOrganizationApiKeyPermissions = (\n params?: ApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"Organization\", params);\n\nconst organizationApiKeysQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationApiKeys\",\n);\n\nfunction toOrganizationApiKey(\n apiKey: OrganizationApiKeyFieldsFragment,\n): ListOrganizationApiKeysResponseData {\n return {\n id: apiKey.id,\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nexport function apiKeyMutationFailure(\n typename: string,\n message: string,\n): ApiError {\n return new ApiError({\n message,\n status: 400,\n queryType: \"mutation\",\n context: { typename },\n });\n}\n\nfunction unwrapCreateOrganizationApiKey(\n result: CreateOrganizationApiKeyMutation[\"createOrganizationApiKey\"],\n): CreateOrganizationApiKeyResponse {\n switch (result.__typename) {\n case \"OrganizationApiKeyCreated\":\n return {\n ...toOrganizationApiKey(result.apiKey),\n value: result.value,\n };\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireOrganizationApiKey(\n result: ExpireOrganizationApiKeyMutation[\"expireOrganizationApiKey\"],\n): ListOrganizationApiKeysResponseData {\n switch (result.__typename) {\n case \"OrganizationApiKeyExpired\":\n return toOrganizationApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useApiKeys = (context?: ApiKeysContextValue) => {\n const {\n state: { pagination, searchQuery },\n } = useApiKeysContext(context);\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListOrganizationApiKeys\", variables),\n queryFn: async (sdk) => {\n const { organizationApiKeys } =\n await sdk.ListOrganizationApiKeys(variables);\n return organizationApiKeys;\n },\n select: (list): ListOrganizationApiKeysResponse => ({\n data: list.data.map(toOrganizationApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateApiKeys = () => {\n const queryClient = useQueryClient();\n return () =>\n queryClient.invalidateQueries({ queryKey: organizationApiKeysQueryKey });\n};\n\nexport const useCreateApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { data }: { data: CreateOrganizationApiKeyRequest },\n ) => {\n const { createOrganizationApiKey: result } =\n await sdk.CreateOrganizationApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteOrganizationApiKey } = await sdk.DeleteOrganizationApiKey({\n apiKeyId,\n });\n return toOrganizationApiKey(deleteOrganizationApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireOrganizationApiKey: result } =\n await sdk.ExpireOrganizationApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-key.js","names":[],"sources":["../../../../src/lib/api/api-key.ts"],"sourcesContent":["import { keepPreviousData, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ApiKeyOwnerType,\n CreateOrganizationApiKeyMutation,\n ExpireOrganizationApiKeyMutation,\n ListApiKeyPermissionsQuery,\n OrganizationApiKeyFieldsFragment,\n} from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlMutation,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\nimport { ApiError } from \"../../api/errors.js\";\nimport { useApiKeysContext } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type { ApiKeysContextValue } from \"../../widgets/api-keys/api-keys-context.js\";\nimport type {\n CreateOrganizationApiKeyRequest,\n CreateOrganizationApiKeyResponse,\n ListOrganizationApiKeyPermission,\n ListOrganizationApiKeyPermissionsParams,\n ListOrganizationApiKeyPermissionsResponse,\n ListOrganizationApiKeysResponse,\n ListOrganizationApiKeysResponseData,\n} from \"./types.js\";\n\nexport const API_KEYS_PAGE_SIZE = 10;\n\ntype ApiKeyPermissionsParams = ListOrganizationApiKeyPermissionsParams;\n\nfunction toApiKeyPermissions(\n list: ListApiKeyPermissionsQuery[\"permissions\"],\n): ListOrganizationApiKeyPermissionsResponse {\n return {\n data: list.data.map((permission): ListOrganizationApiKeyPermission => ({\n id: permission.id,\n slug: permission.slug,\n name: permission.name,\n description: permission.description ?? null,\n })),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n };\n}\n\nexport const useListApiKeyPermissions = (\n apiKeyOwnerType: ApiKeyOwnerType,\n params: ApiKeyPermissionsParams = {},\n) => {\n const variables = {\n apiKeyOwnerType,\n after: params.after,\n before: params.before,\n limit: params.limit,\n search: params.search || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListApiKeyPermissions\", variables),\n queryFn: async (sdk) => {\n const { permissions } = await sdk.ListApiKeyPermissions(variables);\n return permissions;\n },\n select: toApiKeyPermissions,\n placeholderData: keepPreviousData,\n });\n};\n\nexport const useListOrganizationApiKeyPermissions = (\n params?: ApiKeyPermissionsParams,\n) => useListApiKeyPermissions(\"Organization\", params);\n\nconst organizationApiKeysQueryKey = clientGraphqlQueryKey(\n \"ListOrganizationApiKeys\",\n);\n\nfunction toOrganizationApiKey(\n apiKey: OrganizationApiKeyFieldsFragment,\n): ListOrganizationApiKeysResponseData {\n return {\n id: apiKey.id,\n name: apiKey.name,\n obfuscatedValue: apiKey.obfuscatedValue,\n createdAt: apiKey.createdAt,\n lastUsedAt: apiKey.lastUsedAt ?? null,\n expiresAt: apiKey.expiresAt ?? null,\n permissions: apiKey.permissions,\n };\n}\n\nexport function apiKeyMutationFailure(\n typename: string,\n message: string,\n): ApiError {\n return new ApiError({\n message,\n status: 400,\n queryType: \"mutation\",\n context: { typename },\n });\n}\n\nfunction unwrapCreateOrganizationApiKey(\n result: CreateOrganizationApiKeyMutation[\"createOrganizationApiKey\"],\n): CreateOrganizationApiKeyResponse {\n switch (result.__typename) {\n case \"OrganizationApiKeyCreated\":\n return {\n ...toOrganizationApiKey(result.apiKey),\n value: result.value,\n };\n case \"ApiKeyPermissionsNotHeld\":\n case \"ApiKeyPermissionsUnsupportedForToken\":\n case \"InvalidApiKeyExpiration\":\n case \"InvalidApiKeyName\":\n case \"InvalidApiKeyPermissions\":\n throw apiKeyMutationFailure(result.__typename, result.message);\n }\n}\n\nfunction unwrapExpireOrganizationApiKey(\n result: ExpireOrganizationApiKeyMutation[\"expireOrganizationApiKey\"],\n): ListOrganizationApiKeysResponseData {\n switch (result.__typename) {\n case \"OrganizationApiKeyExpired\":\n return toOrganizationApiKey(result.apiKey);\n case \"ApiKeyAlreadyExpired\":\n throw apiKeyMutationFailure(\n result.__typename,\n \"API key is already expired\",\n );\n }\n}\n\nexport const useApiKeys = (context?: ApiKeysContextValue) => {\n const {\n state: { pagination, searchQuery },\n } = useApiKeysContext(context);\n const { before, after } = pagination || {};\n const variables = {\n after: after ?? undefined,\n before: before ?? undefined,\n limit: API_KEYS_PAGE_SIZE,\n search: searchQuery || undefined,\n };\n\n return useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListOrganizationApiKeys\", variables),\n queryFn: async (sdk) => {\n const { organizationApiKeys } =\n await sdk.ListOrganizationApiKeys(variables);\n return organizationApiKeys;\n },\n select: (list): ListOrganizationApiKeysResponse => ({\n data: list.data.map(toOrganizationApiKey),\n list_metadata: {\n after: list.listMetadata.after ?? undefined,\n before: list.listMetadata.before ?? undefined,\n },\n }),\n placeholderData: keepPreviousData,\n });\n};\n\nconst useInvalidateApiKeys = () => {\n const queryClient = useQueryClient();\n return () =>\n queryClient.invalidateQueries({ queryKey: organizationApiKeysQueryKey });\n};\n\nexport const useCreateApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { data }: { data: CreateOrganizationApiKeyRequest },\n ) => {\n const { createOrganizationApiKey: result } =\n await sdk.CreateOrganizationApiKey({\n input: {\n name: data.name,\n permissions: data.permissions,\n expiresAt: data.expiresAt ?? null,\n },\n });\n return unwrapCreateOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n\nexport const useDeleteApiKey = ({\n onSuccess,\n}: { onSuccess?: () => void } = {}) => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (sdk, { apiKeyId }: { apiKeyId: string }) => {\n const { deleteOrganizationApiKey } = await sdk.DeleteOrganizationApiKey({\n apiKeyId,\n });\n return toOrganizationApiKey(deleteOrganizationApiKey);\n },\n onSuccess: () => {\n void invalidate();\n onSuccess?.();\n },\n });\n};\n\nexport const useExpireApiKey = () => {\n const invalidate = useInvalidateApiKeys();\n\n return useClientGraphqlMutation({\n mutationFn: async (\n sdk,\n { apiKeyId, expiresAt }: { apiKeyId: string; expiresAt: string | null },\n ) => {\n const { expireOrganizationApiKey: result } =\n await sdk.ExpireOrganizationApiKey({\n input: { apiKeyId, expiresAt },\n });\n return unwrapExpireOrganizationApiKey(result);\n },\n onSuccess: invalidate,\n });\n};\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { clientGraphqlQueryKey, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
1
+ import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
2
+ import { useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
2
3
  import { useQueryClient } from "@tanstack/react-query";
3
4
  import * as React from "react";
4
5
  //#region src/lib/api/me.ts
@@ -1 +1 @@
1
- {"version":3,"file":"me.js","names":[],"sources":["../../../../src/lib/api/me.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { MeQuery } from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\n\nexport type CurrentUser = MeQuery[\"me\"];\n\nconst meQueryKey = () => clientGraphqlQueryKey(\"Me\");\n\nexport function useMe() {\n return useClientGraphqlQuery({\n queryKey: meQueryKey(),\n queryFn: (sdk) => sdk.Me(),\n select: (data) => data.me,\n });\n}\n\nexport function useMeCache() {\n const client = useQueryClient();\n\n return React.useMemo(\n () => ({\n update(user: Partial<CurrentUser>) {\n client.setQueryData<MeQuery>(meQueryKey(), (old) =>\n old ? { ...old, me: { ...old.me, ...user } } : old,\n );\n },\n invalidate() {\n return client.invalidateQueries({ queryKey: meQueryKey() });\n },\n }),\n [client],\n );\n}\n"],"mappings":";;;;AAUA,MAAM,mBAAmB,sBAAsB,IAAI;AAEnD,SAAgB,QAAQ;CACtB,OAAO,sBAAsB;EAC3B,UAAU,WAAW;EACrB,UAAU,QAAQ,IAAI,GAAG;EACzB,SAAS,SAAS,KAAK;CACzB,CAAC;AACH;AAEA,SAAgB,aAAa;CAC3B,MAAM,SAAS,eAAe;CAE9B,OAAO,MAAM,eACJ;EACL,OAAO,MAA4B;GACjC,OAAO,aAAsB,WAAW,IAAI,QAC1C,MAAM;IAAE,GAAG;IAAK,IAAI;KAAE,GAAG,IAAI;KAAI,GAAG;IAAK;GAAE,IAAI,GACjD;EACF;EACA,aAAa;GACX,OAAO,OAAO,kBAAkB,EAAE,UAAU,WAAW,EAAE,CAAC;EAC5D;CACF,IACA,CAAC,MAAM,CACT;AACF"}
1
+ {"version":3,"file":"me.js","names":[],"sources":["../../../../src/lib/api/me.ts"],"sourcesContent":["import { useQueryClient } from \"@tanstack/react-query\";\nimport * as React from \"react\";\nimport type { MeQuery } from \"../../api/client-graphql/generated.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"../../api/client-graphql/hooks.js\";\n\nexport type CurrentUser = MeQuery[\"me\"];\n\nconst meQueryKey = () => clientGraphqlQueryKey(\"Me\");\n\nexport function useMe() {\n return useClientGraphqlQuery({\n queryKey: meQueryKey(),\n queryFn: (sdk) => sdk.Me(),\n select: (data) => data.me,\n });\n}\n\nexport function useMeCache() {\n const client = useQueryClient();\n\n return React.useMemo(\n () => ({\n update(user: Partial<CurrentUser>) {\n client.setQueryData<MeQuery>(meQueryKey(), (old) =>\n old ? { ...old, me: { ...old.me, ...user } } : old,\n );\n },\n invalidate() {\n return client.invalidateQueries({ queryKey: meQueryKey() });\n },\n }),\n [client],\n );\n}\n"],"mappings":";;;;;AAUA,MAAM,mBAAmB,sBAAsB,IAAI;AAEnD,SAAgB,QAAQ;CACtB,OAAO,sBAAsB;EAC3B,UAAU,WAAW;EACrB,UAAU,QAAQ,IAAI,GAAG;EACzB,SAAS,SAAS,KAAK;CACzB,CAAC;AACH;AAEA,SAAgB,aAAa;CAC3B,MAAM,SAAS,eAAe;CAE9B,OAAO,MAAM,eACJ;EACL,OAAO,MAA4B;GACjC,OAAO,aAAsB,WAAW,IAAI,QAC1C,MAAM;IAAE,GAAG;IAAK,IAAI;KAAE,GAAG,IAAI;KAAI,GAAG;IAAK;GAAE,IAAI,GACjD;EACF;EACA,aAAa;GACX,OAAO,OAAO,kBAAkB,EAAE,UAAU,WAAW,EAAE,CAAC;EAC5D;CACF,IACA,CAAC,MAAM,CACT;AACF"}
@@ -1,4 +1,5 @@
1
- import { clientGraphqlQueryKey, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
1
+ import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
2
+ import { useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
2
3
  import { useQueryClient } from "@tanstack/react-query";
3
4
  import { useCallback } from "react";
4
5
  //#region src/lib/api/pipes.ts