@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 +1 @@
1
- {"version":3,"file":"pipes.client.js","names":["PipesPresentational","PipesSectionsPresentational"],"sources":["../../src/pipes.client.tsx"],"sourcesContent":["\"use client\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport {\n useMyDataIntegrations,\n useSharedDataConnections,\n} from \"./lib/api/pipes.js\";\nimport type {\n DataIntegration,\n DataIntegrationWithConnections,\n SharedDataConnection,\n} from \"./lib/api/types.js\";\nimport { useIsHydrated } from \"./lib/use-is-hydrated.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n PipesError,\n PipesLoading,\n Pipes as PipesPresentational,\n PipesSections as PipesSectionsPresentational,\n} from \"./widgets/pipes/pipes.js\";\nimport type {\n PipesErrorProps,\n PipesLoadingProps,\n} from \"./widgets/pipes/pipes.js\";\n\n/** An auth method a provider advertises (defaults to `oauth` when unset). */\ntype PipesAuthMethod = NonNullable<DataIntegration[\"authMethods\"]>[number];\n\n/**\n * Serializable criteria for narrowing which integrations render. All provided\n * criteria are ANDed; an absent criterion is ignored. Safe to pass from a\n * Server Component, since props cross the server/client boundary.\n */\ninterface PipesFilterCriteria {\n /** Render only integrations whose `slug` is in this list. */\n slugs?: string[];\n /** Render only integrations whose `integrationType` is in this list. */\n integrationTypes?: string[];\n /** Render only integrations that advertise at least one of these methods. */\n authMethods?: PipesAuthMethod[];\n}\n\n/**\n * Narrows which enabled integrations the widget renders. The widget still\n * fetches the full set of integrations the user's organization has enabled\n * (plus any the user is still connected to so they can disconnect); a filter\n * only controls which of those rows are shown, in either of two forms:\n *\n * - **Serializable criteria** (`{ slugs, integrationTypes, authMethods }`),\n * ANDed together. This is the form to use when `<Pipes>` is embedded in a\n * Server Component (the documented token-minting pattern), because props must\n * be serializable across the server/client boundary and plain objects survive\n * it. e.g. `filter={{ slugs: [\"google-drive\"] }}`.\n *\n * - **A predicate** `((integration) => boolean)` for arbitrary filtering by any\n * field on the integration (`authMethods`, `integrationType`,\n * `installation.state`, etc.). A function is **not serializable across the\n * server/client boundary**: the predicate must be defined inside client code\n * and must never be passed in from a Server Component. Concretely, a host\n * using the App Router server-component pattern that needs a predicate must\n * author its own `\"use client\"` wrapper that *owns* the predicate and\n * receives only serializable props (e.g. `authToken`) from the server page.\n *\n * Undefined renders every enabled integration (the default).\n */\ntype PipesFilter =\n | PipesFilterCriteria\n | ((integration: DataIntegration) => boolean);\n\n/** A row the widget renders when `enableSharedConnections` is on. */\ntype PipesConnection = DataIntegrationWithConnections | SharedDataConnection;\n\n/**\n * {@link PipesFilter} as `enableSharedConnections` widens it: the same two\n * forms, except they narrow both sections. The predicate also sees the\n * organization's shared rows, discriminated with `\"integrationType\" in\n * connection` — shared rows carry none of the provider metadata the member's\n * own rows do. Neither `ownership` nor `connected_accounts` discriminates\n * them: the member's own connections can be `\"organization\"` too, and both\n * payloads carry `connected_accounts` (of different element types). Criteria\n * narrow shared rows by `slugs` alone, for the same want of metadata.\n */\ntype PipesConnectionFilter =\n | PipesFilterCriteria\n | ((connection: PipesConnection) => boolean);\n\n/** The unsectioned widget, whose `filter` is what it always was. */\ninterface PipesPersonalProps extends WidgetRootDomProps {\n authToken: AuthToken;\n /**\n * Defaults to `false`, which renders the single unsectioned list of the\n * member's own connections and never requests shared connections.\n */\n enableSharedConnections?: false;\n /** Narrows the member's own connections: {@link PipesFilter}. */\n filter?: PipesFilter;\n}\n\n/**\n * The sectioned widget, whose `filter` also narrows the shared section and so\n * takes the widened predicate.\n */\ninterface PipesSectionsProps extends WidgetRootDomProps {\n authToken: AuthToken;\n /**\n * Opt in to the sectioned member experience: the connections the organization\n * owns and shares with everyone, followed by the member's own connections.\n *\n * Shared connections are read-only for members — they carry no\n * credential-management actions — and are fetched separately from the\n * member's own connections, so the personal section renders as soon as it\n * resolves regardless of the shared one.\n *\n * Typed `boolean` rather than `true` so a host can forward a runtime feature\n * flag: a predicate has to cope with shared rows whenever the flag can be on.\n */\n enableSharedConnections: boolean;\n /** Narrows both sections: {@link PipesConnectionFilter}. */\n filter?: PipesConnectionFilter;\n}\n\ntype PipesProps = PipesPersonalProps | PipesSectionsProps;\n\ntype PipesImplProps =\n | Omit<PipesPersonalProps, \"authToken\">\n | Omit<PipesSectionsProps, \"authToken\">;\n\n/**\n * Overloads rather than one props union, so that opting in widens the\n * predicate's parameter for that host alone while every other host's `filter`\n * stays exactly as it was. A union leaves `enableSharedConnections={false}`\n * satisfying both members — the opt-in one accepts every `boolean` — leaving an\n * inline predicate no single contextual type to draw on (`TS7006`). Overloads\n * are ordered instead: a literal `false` resolves to the personal signature,\n * and anything else, a runtime flag included, to the widened one.\n *\n * The last signature takes the whole union, so that a wrapper forwarding\n * `PipesProps` it hasn't narrowed (`<Pipes {...props} />`) still resolves, and\n * so that `React.ComponentProps<typeof Pipes>` — which reads the last\n * signature — describes the widget rather than only its opted-in half.\n */\ninterface PipesComponent {\n (props: PipesPersonalProps): React.ReactNode;\n (props: PipesSectionsProps): React.ReactNode;\n (props: PipesProps): React.ReactNode;\n}\n\nconst PipesRoot = ({ authToken, ...props }: PipesProps) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => <PipesError {...props} error={error} />}\n >\n <ApiProvider widgetType=\"pipes\" authToken={authToken} baseUrl={baseUrl}>\n <PipesImpl {...props} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\n/**\n * Evaluates serializable {@link PipesFilterCriteria} against an integration.\n * Provided criteria are ANDed; an integration with no declared `authMethods`\n * is treated as `oauth` (matching the widget's connect-method defaults).\n */\nfunction matchesPipesFilterCriteria(\n integration: DataIntegration,\n criteria: PipesFilterCriteria,\n): boolean {\n if (criteria.slugs && !criteria.slugs.includes(integration.slug)) {\n return false;\n }\n if (\n criteria.integrationTypes &&\n !criteria.integrationTypes.includes(integration.integrationType)\n ) {\n return false;\n }\n if (criteria.authMethods) {\n const methods = integration.authMethods ?? [\"oauth\"];\n if (!criteria.authMethods.some((method) => methods.includes(method))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Narrows shared connections. Criteria match them on `slugs` alone, since their\n * payload carries none of the provider metadata the other criteria read.\n */\nfunction applySharedPipesFilter(\n connections: SharedDataConnection[],\n filter: PipesConnectionFilter | undefined,\n): SharedDataConnection[] {\n if (!filter) {\n return connections;\n }\n\n if (typeof filter === \"function\") {\n return connections.filter(filter);\n }\n\n const { slugs } = filter;\n\n return slugs\n ? connections.filter((connection) => slugs.includes(connection.slug))\n : connections;\n}\n\n/** Applies a {@link PipesFilter} in either of its forms. */\nfunction applyPipesFilter<T extends DataIntegrationWithConnections>(\n integrations: T[],\n filter: PipesFilter | PipesConnectionFilter | undefined,\n): T[] {\n if (!filter) {\n return integrations;\n }\n\n return typeof filter === \"function\"\n ? integrations.filter((integration) => filter(integration))\n : integrations.filter((integration) =>\n matchesPipesFilterCriteria(integration, filter),\n );\n}\n\ninterface PipesSectionsImplProps extends WidgetRootDomProps {\n filter?: PipesConnectionFilter;\n}\n\n// The two experiences are separate components so the opt-out path mounts no\n// shared-connections hook at all, and therefore issues exactly the requests it\n// always has.\nconst PipesImpl: React.FC<PipesImplProps> = (props) => {\n if (props.enableSharedConnections) {\n const { enableSharedConnections, ...sectionsProps } = props;\n return <PipesSectionsImpl {...sectionsProps} />;\n }\n\n const { enableSharedConnections, ...personalProps } = props;\n return <PipesPersonalImpl {...personalProps} />;\n};\n\ninterface PipesPersonalImplProps extends WidgetRootDomProps {\n filter?: PipesFilter | PipesConnectionFilter;\n}\n\nconst PipesPersonalImpl: React.FC<PipesPersonalImplProps> = (props) => {\n const isHydrated = useIsHydrated();\n const integrations = useMyDataIntegrations();\n\n if (!isHydrated || integrations.isLoading) {\n return <PipesLoading count={6} {...props} />;\n }\n\n if (integrations.isError) {\n return <PipesError error={integrations.error} {...props} />;\n }\n\n if (integrations.isSuccess) {\n const visible = applyPipesFilter(integrations.data, props.filter);\n\n return (\n <PipesPresentational\n integrations={visible}\n hasUnfilteredIntegrations={integrations.data.length > 0}\n {...props}\n />\n );\n }\n\n return <PipesError error={integrations.error} {...props} />;\n};\n\nconst PipesSectionsImpl: React.FC<PipesSectionsImplProps> = (props) => {\n const isHydrated = useIsHydrated();\n const integrations = useMyDataIntegrations();\n // Both sections have their own cache entry and resolve independently: the\n // member's own connections render as soon as they arrive, and a slow or\n // failing shared request only affects the shared section.\n const shared = useSharedDataConnections();\n const organizations = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserOrganizations\"),\n queryFn: (sdk) => sdk.ListUserOrganizations(),\n });\n const organizationName = organizations.data?.organizations.find(\n (organization) => organization.isCurrent,\n )?.name;\n\n if (!isHydrated || integrations.isLoading) {\n return <PipesLoading count={6} {...props} />;\n }\n\n if (integrations.isError || !integrations.isSuccess) {\n return <PipesError error={integrations.error} {...props} />;\n }\n\n const visible = applyPipesFilter(integrations.data, props.filter);\n\n return (\n <PipesSectionsPresentational\n integrations={visible}\n hasUnfilteredIntegrations={integrations.data.length > 0}\n sharedConnections={applySharedPipesFilter(shared.data, props.filter)}\n hasUnfilteredSharedConnections={shared.data.length > 0}\n // A failed attempt drops the section rather than leaving skeletons up\n // for the whole retry sequence.\n isSharedLoading={shared.isPending && shared.failureCount === 0}\n organizationName={organizationName}\n {...props}\n />\n );\n};\n\nconst Pipes: PipesComponent = PipesRoot;\n\nexport type {\n PipesProps,\n PipesConnection,\n PipesFilter,\n PipesFilterCriteria,\n PipesConnectionFilter,\n PipesAuthMethod,\n PipesLoadingProps,\n PipesErrorProps,\n};\nexport { Pipes, PipesLoading, PipesError };\n"],"mappings":"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"}
1
+ {"version":3,"file":"pipes.client.js","names":["PipesPresentational","PipesSectionsPresentational"],"sources":["../../src/pipes.client.tsx"],"sourcesContent":["\"use client\";\nimport type { AuthToken } from \"./api/api-provider.js\";\nimport { ApiProvider } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport {\n useMyDataIntegrations,\n useSharedDataConnections,\n} from \"./lib/api/pipes.js\";\nimport type {\n DataIntegration,\n DataIntegrationWithConnections,\n SharedDataConnection,\n} from \"./lib/api/types.js\";\nimport { useIsHydrated } from \"./lib/use-is-hydrated.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n PipesError,\n PipesLoading,\n Pipes as PipesPresentational,\n PipesSections as PipesSectionsPresentational,\n} from \"./widgets/pipes/pipes.js\";\nimport type {\n PipesErrorProps,\n PipesLoadingProps,\n} from \"./widgets/pipes/pipes.js\";\n\n/** An auth method a provider advertises (defaults to `oauth` when unset). */\ntype PipesAuthMethod = NonNullable<DataIntegration[\"authMethods\"]>[number];\n\n/**\n * Serializable criteria for narrowing which integrations render. All provided\n * criteria are ANDed; an absent criterion is ignored. Safe to pass from a\n * Server Component, since props cross the server/client boundary.\n */\ninterface PipesFilterCriteria {\n /** Render only integrations whose `slug` is in this list. */\n slugs?: string[];\n /** Render only integrations whose `integrationType` is in this list. */\n integrationTypes?: string[];\n /** Render only integrations that advertise at least one of these methods. */\n authMethods?: PipesAuthMethod[];\n}\n\n/**\n * Narrows which enabled integrations the widget renders. The widget still\n * fetches the full set of integrations the user's organization has enabled\n * (plus any the user is still connected to so they can disconnect); a filter\n * only controls which of those rows are shown, in either of two forms:\n *\n * - **Serializable criteria** (`{ slugs, integrationTypes, authMethods }`),\n * ANDed together. This is the form to use when `<Pipes>` is embedded in a\n * Server Component (the documented token-minting pattern), because props must\n * be serializable across the server/client boundary and plain objects survive\n * it. e.g. `filter={{ slugs: [\"google-drive\"] }}`.\n *\n * - **A predicate** `((integration) => boolean)` for arbitrary filtering by any\n * field on the integration (`authMethods`, `integrationType`,\n * `installation.state`, etc.). A function is **not serializable across the\n * server/client boundary**: the predicate must be defined inside client code\n * and must never be passed in from a Server Component. Concretely, a host\n * using the App Router server-component pattern that needs a predicate must\n * author its own `\"use client\"` wrapper that *owns* the predicate and\n * receives only serializable props (e.g. `authToken`) from the server page.\n *\n * Undefined renders every enabled integration (the default).\n */\ntype PipesFilter =\n | PipesFilterCriteria\n | ((integration: DataIntegration) => boolean);\n\n/** A row the widget renders when `enableSharedConnections` is on. */\ntype PipesConnection = DataIntegrationWithConnections | SharedDataConnection;\n\n/**\n * {@link PipesFilter} as `enableSharedConnections` widens it: the same two\n * forms, except they narrow both sections. The predicate also sees the\n * organization's shared rows, discriminated with `\"integrationType\" in\n * connection` — shared rows carry none of the provider metadata the member's\n * own rows do. Neither `ownership` nor `connected_accounts` discriminates\n * them: the member's own connections can be `\"organization\"` too, and both\n * payloads carry `connected_accounts` (of different element types). Criteria\n * narrow shared rows by `slugs` alone, for the same want of metadata.\n */\ntype PipesConnectionFilter =\n | PipesFilterCriteria\n | ((connection: PipesConnection) => boolean);\n\n/** The unsectioned widget, whose `filter` is what it always was. */\ninterface PipesPersonalProps extends WidgetRootDomProps {\n authToken: AuthToken;\n /**\n * Defaults to `false`, which renders the single unsectioned list of the\n * member's own connections and never requests shared connections.\n */\n enableSharedConnections?: false;\n /** Narrows the member's own connections: {@link PipesFilter}. */\n filter?: PipesFilter;\n}\n\n/**\n * The sectioned widget, whose `filter` also narrows the shared section and so\n * takes the widened predicate.\n */\ninterface PipesSectionsProps extends WidgetRootDomProps {\n authToken: AuthToken;\n /**\n * Opt in to the sectioned member experience: the connections the organization\n * owns and shares with everyone, followed by the member's own connections.\n *\n * Shared connections are read-only for members — they carry no\n * credential-management actions — and are fetched separately from the\n * member's own connections, so the personal section renders as soon as it\n * resolves regardless of the shared one.\n *\n * Typed `boolean` rather than `true` so a host can forward a runtime feature\n * flag: a predicate has to cope with shared rows whenever the flag can be on.\n */\n enableSharedConnections: boolean;\n /** Narrows both sections: {@link PipesConnectionFilter}. */\n filter?: PipesConnectionFilter;\n}\n\ntype PipesProps = PipesPersonalProps | PipesSectionsProps;\n\ntype PipesImplProps =\n | Omit<PipesPersonalProps, \"authToken\">\n | Omit<PipesSectionsProps, \"authToken\">;\n\n/**\n * Overloads rather than one props union, so that opting in widens the\n * predicate's parameter for that host alone while every other host's `filter`\n * stays exactly as it was. A union leaves `enableSharedConnections={false}`\n * satisfying both members — the opt-in one accepts every `boolean` — leaving an\n * inline predicate no single contextual type to draw on (`TS7006`). Overloads\n * are ordered instead: a literal `false` resolves to the personal signature,\n * and anything else, a runtime flag included, to the widened one.\n *\n * The last signature takes the whole union, so that a wrapper forwarding\n * `PipesProps` it hasn't narrowed (`<Pipes {...props} />`) still resolves, and\n * so that `React.ComponentProps<typeof Pipes>` — which reads the last\n * signature — describes the widget rather than only its opted-in half.\n */\ninterface PipesComponent {\n (props: PipesPersonalProps): React.ReactNode;\n (props: PipesSectionsProps): React.ReactNode;\n (props: PipesProps): React.ReactNode;\n}\n\nconst PipesRoot = ({ authToken, ...props }: PipesProps) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => <PipesError {...props} error={error} />}\n >\n <ApiProvider widgetType=\"pipes\" authToken={authToken} baseUrl={baseUrl}>\n <PipesImpl {...props} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\n/**\n * Evaluates serializable {@link PipesFilterCriteria} against an integration.\n * Provided criteria are ANDed; an integration with no declared `authMethods`\n * is treated as `oauth` (matching the widget's connect-method defaults).\n */\nfunction matchesPipesFilterCriteria(\n integration: DataIntegration,\n criteria: PipesFilterCriteria,\n): boolean {\n if (criteria.slugs && !criteria.slugs.includes(integration.slug)) {\n return false;\n }\n if (\n criteria.integrationTypes &&\n !criteria.integrationTypes.includes(integration.integrationType)\n ) {\n return false;\n }\n if (criteria.authMethods) {\n const methods = integration.authMethods ?? [\"oauth\"];\n if (!criteria.authMethods.some((method) => methods.includes(method))) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Narrows shared connections. Criteria match them on `slugs` alone, since their\n * payload carries none of the provider metadata the other criteria read.\n */\nfunction applySharedPipesFilter(\n connections: SharedDataConnection[],\n filter: PipesConnectionFilter | undefined,\n): SharedDataConnection[] {\n if (!filter) {\n return connections;\n }\n\n if (typeof filter === \"function\") {\n return connections.filter(filter);\n }\n\n const { slugs } = filter;\n\n return slugs\n ? connections.filter((connection) => slugs.includes(connection.slug))\n : connections;\n}\n\n/** Applies a {@link PipesFilter} in either of its forms. */\nfunction applyPipesFilter<T extends DataIntegrationWithConnections>(\n integrations: T[],\n filter: PipesFilter | PipesConnectionFilter | undefined,\n): T[] {\n if (!filter) {\n return integrations;\n }\n\n return typeof filter === \"function\"\n ? integrations.filter((integration) => filter(integration))\n : integrations.filter((integration) =>\n matchesPipesFilterCriteria(integration, filter),\n );\n}\n\ninterface PipesSectionsImplProps extends WidgetRootDomProps {\n filter?: PipesConnectionFilter;\n}\n\n// The two experiences are separate components so the opt-out path mounts no\n// shared-connections hook at all, and therefore issues exactly the requests it\n// always has.\nconst PipesImpl: React.FC<PipesImplProps> = (props) => {\n if (props.enableSharedConnections) {\n const { enableSharedConnections, ...sectionsProps } = props;\n return <PipesSectionsImpl {...sectionsProps} />;\n }\n\n const { enableSharedConnections, ...personalProps } = props;\n return <PipesPersonalImpl {...personalProps} />;\n};\n\ninterface PipesPersonalImplProps extends WidgetRootDomProps {\n filter?: PipesFilter | PipesConnectionFilter;\n}\n\nconst PipesPersonalImpl: React.FC<PipesPersonalImplProps> = (props) => {\n const isHydrated = useIsHydrated();\n const integrations = useMyDataIntegrations();\n\n if (!isHydrated || integrations.isLoading) {\n return <PipesLoading count={6} {...props} />;\n }\n\n if (integrations.isError) {\n return <PipesError error={integrations.error} {...props} />;\n }\n\n if (integrations.isSuccess) {\n const visible = applyPipesFilter(integrations.data, props.filter);\n\n return (\n <PipesPresentational\n integrations={visible}\n hasUnfilteredIntegrations={integrations.data.length > 0}\n {...props}\n />\n );\n }\n\n return <PipesError error={integrations.error} {...props} />;\n};\n\nconst PipesSectionsImpl: React.FC<PipesSectionsImplProps> = (props) => {\n const isHydrated = useIsHydrated();\n const integrations = useMyDataIntegrations();\n // Both sections have their own cache entry and resolve independently: the\n // member's own connections render as soon as they arrive, and a slow or\n // failing shared request only affects the shared section.\n const shared = useSharedDataConnections();\n const organizations = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"ListUserOrganizations\"),\n queryFn: (sdk) => sdk.ListUserOrganizations(),\n });\n const organizationName = organizations.data?.organizations.find(\n (organization) => organization.isCurrent,\n )?.name;\n\n if (!isHydrated || integrations.isLoading) {\n return <PipesLoading count={6} {...props} />;\n }\n\n if (integrations.isError || !integrations.isSuccess) {\n return <PipesError error={integrations.error} {...props} />;\n }\n\n const visible = applyPipesFilter(integrations.data, props.filter);\n\n return (\n <PipesSectionsPresentational\n integrations={visible}\n hasUnfilteredIntegrations={integrations.data.length > 0}\n sharedConnections={applySharedPipesFilter(shared.data, props.filter)}\n hasUnfilteredSharedConnections={shared.data.length > 0}\n // A failed attempt drops the section rather than leaving skeletons up\n // for the whole retry sequence.\n isSharedLoading={shared.isPending && shared.failureCount === 0}\n organizationName={organizationName}\n {...props}\n />\n );\n};\n\nconst Pipes: PipesComponent = PipesRoot;\n\nexport type {\n PipesProps,\n PipesConnection,\n PipesFilter,\n PipesFilterCriteria,\n PipesConnectionFilter,\n PipesAuthMethod,\n PipesLoadingProps,\n PipesErrorProps,\n};\nexport { Pipes, PipesLoading, PipesError };\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, useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
+ import { useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
6
  import { ErrorBoundary } from "./components/error-boundary.js";
6
7
  import { useMe } from "./lib/api/me.js";
7
8
  import { UserSecurity as UserSecurity$1, UserSecurityError, UserSecurityLoading } from "./widgets/user-security/user-security.js";
@@ -1 +1 @@
1
- {"version":3,"file":"user-security.client.js","names":["UserSecurityPresentational"],"sources":["../../src/user-security.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 {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { useMe } from \"./lib/api/me.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n UserSecurityError,\n UserSecurityLoading,\n UserSecurity as UserSecurityPresentational,\n} from \"./widgets/user-security/user-security.js\";\nimport type {\n UserSecurityErrorProps,\n UserSecurityLoadingProps,\n} from \"./widgets/user-security/user-security.js\";\n\ninterface UserSecurityProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst UserSecurity: React.FC<UserSecurityProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSecurityError error={error} {...domProps} />\n )}\n >\n <ApiProvider\n widgetType=\"user-security\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <UserSecurityImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface UserSecurityImplProps extends WidgetRootDomProps {}\n\nconst UserSecurityImpl: React.FC<UserSecurityImplProps> = (props) => {\n const isApiReady = useApiReady();\n const meQuery = useMe();\n const settingsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"AuthenticationSettings\"),\n queryFn: (sdk) => sdk.AuthenticationSettings(),\n select: (data) => data.authenticationSettings,\n });\n\n if (!isApiReady || meQuery.isLoading || settingsQuery.isLoading) {\n return <UserSecurityLoading {...props} />;\n }\n\n if (!meQuery.isSuccess || !settingsQuery.isSuccess) {\n return (\n <UserSecurityError\n error={meQuery.error ?? settingsQuery.error}\n {...props}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSecurityError error={error} {...props} />\n )}\n >\n <UserSecurityPresentational\n user={meQuery.data}\n settings={settingsQuery.data}\n {...props}\n />\n </ErrorBoundary>\n );\n};\n\nexport type {\n UserSecurityProps,\n UserSecurityLoadingProps,\n UserSecurityErrorProps,\n};\nexport { UserSecurity, UserSecurityLoading, UserSecurityError };\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,gBAA6C,EACjD,WACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAW,CAAA;EAGlD,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,kBAAD,EAAkB,GAAI,SAAW,CAAA;EACtB,CAAA;CACA,CAAA;AAEnB;AAIA,MAAM,oBAAqD,UAAU;CACnE,MAAM,aAAa,YAAY;CAC/B,MAAM,UAAU,MAAM;CACtB,MAAM,gBAAgB,sBAAsB;EAC1C,UAAU,sBAAsB,wBAAwB;EACxD,UAAU,QAAQ,IAAI,uBAAuB;EAC7C,SAAS,SAAS,KAAK;CACzB,CAAC;CAED,IAAI,CAAC,cAAc,QAAQ,aAAa,cAAc,WACpD,OAAO,oBAAC,qBAAD,EAAqB,GAAI,MAAQ,CAAA;CAG1C,IAAI,CAAC,QAAQ,aAAa,CAAC,cAAc,WACvC,OACE,oBAAC,mBAAD;EACE,OAAO,QAAQ,SAAS,cAAc;EACtC,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAQ,CAAA;EAG/C,UAAA,oBAACA,gBAAD;GACE,MAAM,QAAQ;GACd,UAAU,cAAc;GACxB,GAAI;EACL,CAAA;CACY,CAAA;AAEnB"}
1
+ {"version":3,"file":"user-security.client.js","names":["UserSecurityPresentational"],"sources":["../../src/user-security.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 {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport { useMe } from \"./lib/api/me.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n UserSecurityError,\n UserSecurityLoading,\n UserSecurity as UserSecurityPresentational,\n} from \"./widgets/user-security/user-security.js\";\nimport type {\n UserSecurityErrorProps,\n UserSecurityLoadingProps,\n} from \"./widgets/user-security/user-security.js\";\n\ninterface UserSecurityProps extends WidgetRootDomProps {\n authToken: AuthToken;\n}\n\nconst UserSecurity: React.FC<UserSecurityProps> = ({\n authToken,\n ...domProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSecurityError error={error} {...domProps} />\n )}\n >\n <ApiProvider\n widgetType=\"user-security\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <UserSecurityImpl {...domProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface UserSecurityImplProps extends WidgetRootDomProps {}\n\nconst UserSecurityImpl: React.FC<UserSecurityImplProps> = (props) => {\n const isApiReady = useApiReady();\n const meQuery = useMe();\n const settingsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"AuthenticationSettings\"),\n queryFn: (sdk) => sdk.AuthenticationSettings(),\n select: (data) => data.authenticationSettings,\n });\n\n if (!isApiReady || meQuery.isLoading || settingsQuery.isLoading) {\n return <UserSecurityLoading {...props} />;\n }\n\n if (!meQuery.isSuccess || !settingsQuery.isSuccess) {\n return (\n <UserSecurityError\n error={meQuery.error ?? settingsQuery.error}\n {...props}\n />\n );\n }\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSecurityError error={error} {...props} />\n )}\n >\n <UserSecurityPresentational\n user={meQuery.data}\n settings={settingsQuery.data}\n {...props}\n />\n </ErrorBoundary>\n );\n};\n\nexport type {\n UserSecurityProps,\n UserSecurityLoadingProps,\n UserSecurityErrorProps,\n};\nexport { UserSecurity, UserSecurityLoading, UserSecurityError };\n"],"mappings":";;;;;;;;;;;AA2BA,MAAM,gBAA6C,EACjD,WACA,GAAG,eACC;CACJ,MAAM,UAAU,gBAAgB;CAEhC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAW,CAAA;EAGlD,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,kBAAD,EAAkB,GAAI,SAAW,CAAA;EACtB,CAAA;CACA,CAAA;AAEnB;AAIA,MAAM,oBAAqD,UAAU;CACnE,MAAM,aAAa,YAAY;CAC/B,MAAM,UAAU,MAAM;CACtB,MAAM,gBAAgB,sBAAsB;EAC1C,UAAU,sBAAsB,wBAAwB;EACxD,UAAU,QAAQ,IAAI,uBAAuB;EAC7C,SAAS,SAAS,KAAK;CACzB,CAAC;CAED,IAAI,CAAC,cAAc,QAAQ,aAAa,cAAc,WACpD,OAAO,oBAAC,qBAAD,EAAqB,GAAI,MAAQ,CAAA;CAG1C,IAAI,CAAC,QAAQ,aAAa,CAAC,cAAc,WACvC,OACE,oBAAC,mBAAD;EACE,OAAO,QAAQ,SAAS,cAAc;EACtC,GAAI;CACL,CAAA;CAIL,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAQ,CAAA;EAG/C,UAAA,oBAACA,gBAAD;GACE,MAAM,QAAQ;GACd,UAAU,cAAc;GACxB,GAAI;EACL,CAAA;CACY,CAAA;AAEnB"}
@@ -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, useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
+ import { useClientGraphqlQuery } from "./api/client-graphql/hooks.js";
5
6
  import { ErrorBoundary } from "./components/error-boundary.js";
6
7
  import { UserSessions as UserSessions$1, UserSessionsError, UserSessionsLoading } from "./widgets/user-sessions/user-sessions.js";
7
8
  import "react";
@@ -1 +1 @@
1
- {"version":3,"file":"user-sessions.client.js","names":["UserSessionsPresentational"],"sources":["../../src/user-sessions.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n UserSessionsError,\n UserSessionsLoading,\n UserSessions as UserSessionsPresentational,\n} from \"./widgets/user-sessions/user-sessions.js\";\nimport type {\n UserSessionsErrorProps,\n UserSessionsLoadingProps,\n} from \"./widgets/user-sessions/user-sessions.js\";\n\ninterface UserSessionsWithoutCurrentSessionIdProps {\n authToken: () => Promise<string>;\n currentSessionId?: never;\n}\n\ninterface UserSessionsWithCurrentSessionIdProps {\n authToken: string;\n currentSessionId: string;\n}\n\ntype UserSessionsProps = WidgetRootDomProps &\n (\n | UserSessionsWithoutCurrentSessionIdProps\n | UserSessionsWithCurrentSessionIdProps\n );\n\nconst UserSessions: React.FC<UserSessionsProps> = ({\n authToken,\n ...passthroughProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => {\n const { currentSessionId, ...domProps } = passthroughProps;\n return <UserSessionsError error={error} {...domProps} />;\n }}\n >\n <ApiProvider\n widgetType=\"user-sessions\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <UserSessionsImpl {...passthroughProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface UserSessionsImplProps extends WidgetRootDomProps {\n currentSessionId?: string;\n}\n\nconst UserSessionsImpl: React.FC<UserSessionsImplProps> = ({\n currentSessionId,\n ...domProps\n}) => {\n const isApiReady = useApiReady();\n const sessionsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"Sessions\"),\n queryFn: (sdk) => sdk.Sessions(),\n select: (data) => data.sessions,\n });\n\n if (!isApiReady || sessionsQuery.isLoading) {\n return <UserSessionsLoading {...domProps} />;\n }\n\n if (sessionsQuery.isError) {\n return <UserSessionsError error={sessionsQuery.error} {...domProps} />;\n }\n\n const sessions = sessionsQuery.data ?? [];\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSessionsError error={error} {...domProps} />\n )}\n >\n <UserSessionsPresentational\n sessionsData={sessions}\n currentSessionId={\n currentSessionId ??\n sessions.find((session) => session.isCurrent)?.id ??\n \"\"\n }\n {...domProps}\n />\n </ErrorBoundary>\n );\n};\n\nexport type {\n UserSessionsProps,\n UserSessionsLoadingProps,\n UserSessionsErrorProps,\n};\nexport { UserSessions, UserSessionsLoading, UserSessionsError };\n"],"mappings":";;;;;;;;;AAqCA,MAAM,gBAA6C,EACjD,WACA,GAAG,uBACC;CACJ,MAAM,UAAU,gBAAgB;CAChC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YAAY;GAC7B,MAAM,EAAE,kBAAkB,GAAG,aAAa;GAC1C,OAAO,oBAAC,mBAAD;IAA0B;IAAO,GAAI;GAAW,CAAA;EACzD;EAEA,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,kBAAD,EAAkB,GAAI,iBAAmB,CAAA;EAC9B,CAAA;CACA,CAAA;AAEnB;AAMA,MAAM,oBAAqD,EACzD,kBACA,GAAG,eACC;CACJ,MAAM,aAAa,YAAY;CAC/B,MAAM,gBAAgB,sBAAsB;EAC1C,UAAU,sBAAsB,UAAU;EAC1C,UAAU,QAAQ,IAAI,SAAS;EAC/B,SAAS,SAAS,KAAK;CACzB,CAAC;CAED,IAAI,CAAC,cAAc,cAAc,WAC/B,OAAO,oBAAC,qBAAD,EAAqB,GAAI,SAAW,CAAA;CAG7C,IAAI,cAAc,SAChB,OAAO,oBAAC,mBAAD;EAAmB,OAAO,cAAc;EAAO,GAAI;CAAW,CAAA;CAGvE,MAAM,WAAW,cAAc,QAAQ,CAAC;CAExC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAW,CAAA;EAGlD,UAAA,oBAACA,gBAAD;GACE,cAAc;GACd,kBACE,oBACA,SAAS,MAAM,YAAY,QAAQ,SAAS,CAAC,EAAE,MAC/C;GAEF,GAAI;EACL,CAAA;CACY,CAAA;AAEnB"}
1
+ {"version":3,"file":"user-sessions.client.js","names":["UserSessionsPresentational"],"sources":["../../src/user-sessions.client.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { ApiProvider, useApiReady } from \"./api/api-provider.js\";\nimport {\n clientGraphqlQueryKey,\n useClientGraphqlQuery,\n} from \"./api/client-graphql/hooks.js\";\nimport { ErrorBoundary } from \"./components/error-boundary.js\";\nimport type { WidgetRootDomProps } from \"./lib/widget-types.js\";\nimport { useWorkOsApiUrl } from \"./lib/widgets-context.js\";\nimport {\n UserSessionsError,\n UserSessionsLoading,\n UserSessions as UserSessionsPresentational,\n} from \"./widgets/user-sessions/user-sessions.js\";\nimport type {\n UserSessionsErrorProps,\n UserSessionsLoadingProps,\n} from \"./widgets/user-sessions/user-sessions.js\";\n\ninterface UserSessionsWithoutCurrentSessionIdProps {\n authToken: () => Promise<string>;\n currentSessionId?: never;\n}\n\ninterface UserSessionsWithCurrentSessionIdProps {\n authToken: string;\n currentSessionId: string;\n}\n\ntype UserSessionsProps = WidgetRootDomProps &\n (\n | UserSessionsWithoutCurrentSessionIdProps\n | UserSessionsWithCurrentSessionIdProps\n );\n\nconst UserSessions: React.FC<UserSessionsProps> = ({\n authToken,\n ...passthroughProps\n}) => {\n const baseUrl = useWorkOsApiUrl();\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => {\n const { currentSessionId, ...domProps } = passthroughProps;\n return <UserSessionsError error={error} {...domProps} />;\n }}\n >\n <ApiProvider\n widgetType=\"user-sessions\"\n authToken={authToken}\n baseUrl={baseUrl}\n >\n <UserSessionsImpl {...passthroughProps} />\n </ApiProvider>\n </ErrorBoundary>\n );\n};\n\ninterface UserSessionsImplProps extends WidgetRootDomProps {\n currentSessionId?: string;\n}\n\nconst UserSessionsImpl: React.FC<UserSessionsImplProps> = ({\n currentSessionId,\n ...domProps\n}) => {\n const isApiReady = useApiReady();\n const sessionsQuery = useClientGraphqlQuery({\n queryKey: clientGraphqlQueryKey(\"Sessions\"),\n queryFn: (sdk) => sdk.Sessions(),\n select: (data) => data.sessions,\n });\n\n if (!isApiReady || sessionsQuery.isLoading) {\n return <UserSessionsLoading {...domProps} />;\n }\n\n if (sessionsQuery.isError) {\n return <UserSessionsError error={sessionsQuery.error} {...domProps} />;\n }\n\n const sessions = sessionsQuery.data ?? [];\n\n return (\n <ErrorBoundary\n fallbackRender={({ error }) => (\n <UserSessionsError error={error} {...domProps} />\n )}\n >\n <UserSessionsPresentational\n sessionsData={sessions}\n currentSessionId={\n currentSessionId ??\n sessions.find((session) => session.isCurrent)?.id ??\n \"\"\n }\n {...domProps}\n />\n </ErrorBoundary>\n );\n};\n\nexport type {\n UserSessionsProps,\n UserSessionsLoadingProps,\n UserSessionsErrorProps,\n};\nexport { UserSessions, UserSessionsLoading, UserSessionsError };\n"],"mappings":";;;;;;;;;;AAqCA,MAAM,gBAA6C,EACjD,WACA,GAAG,uBACC;CACJ,MAAM,UAAU,gBAAgB;CAChC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YAAY;GAC7B,MAAM,EAAE,kBAAkB,GAAG,aAAa;GAC1C,OAAO,oBAAC,mBAAD;IAA0B;IAAO,GAAI;GAAW,CAAA;EACzD;EAEA,UAAA,oBAAC,aAAD;GACE,YAAW;GACA;GACF;GAET,UAAA,oBAAC,kBAAD,EAAkB,GAAI,iBAAmB,CAAA;EAC9B,CAAA;CACA,CAAA;AAEnB;AAMA,MAAM,oBAAqD,EACzD,kBACA,GAAG,eACC;CACJ,MAAM,aAAa,YAAY;CAC/B,MAAM,gBAAgB,sBAAsB;EAC1C,UAAU,sBAAsB,UAAU;EAC1C,UAAU,QAAQ,IAAI,SAAS;EAC/B,SAAS,SAAS,KAAK;CACzB,CAAC;CAED,IAAI,CAAC,cAAc,cAAc,WAC/B,OAAO,oBAAC,qBAAD,EAAqB,GAAI,SAAW,CAAA;CAG7C,IAAI,cAAc,SAChB,OAAO,oBAAC,mBAAD;EAAmB,OAAO,cAAc;EAAO,GAAI;CAAW,CAAA;CAGvE,MAAM,WAAW,cAAc,QAAQ,CAAC;CAExC,OACE,oBAAC,eAAD;EACE,iBAAiB,EAAE,YACjB,oBAAC,mBAAD;GAA0B;GAAO,GAAI;EAAW,CAAA;EAGlD,UAAA,oBAACA,gBAAD;GACE,cAAc;GACd,kBACE,oBACA,SAAS,MAAM,YAAY,QAAQ,SAAS,CAAC,EAAE,MAC/C;GAEF,GAAI;EACL,CAAA;CACY,CAAA;AAEnB"}
@@ -22,7 +22,7 @@ const ApiKeysSearch = React.forwardRef(function ApiKeysSearch({ className, ...pr
22
22
  type: "FILTER_BY_SEARCH",
23
23
  searchQuery: value
24
24
  });
25
- }, 200);
25
+ }, { wait: 200 });
26
26
  const resetSearch = () => {
27
27
  clearSearch();
28
28
  filter.cancel();
@@ -1 +1 @@
1
- {"version":3,"file":"api-keys-search.js","names":["TextField.Root","TextField.Slot"],"sources":["../../../../src/widgets/api-keys/api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { IconButton, TextField } from \"../../components/elements.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useDebouncedCallback } from \"../../lib/use-debounce.js\";\nimport { namespaceClassName } from \"../../lib/widget-dom-props.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\n\ninterface ApiKeysSearchProps extends TextField.RootProps {}\n\nconst ApiKeysSearch = React.forwardRef<HTMLInputElement, ApiKeysSearchProps>(\n function ApiKeysSearch({ className, ...props }, ref) {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useApiKeysSearchContext();\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback((value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n }, 200);\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField.Root\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassName(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextField.Slot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextField.Slot>\n\n <TextField.Slot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextField.Slot>\n </TextField.Root>\n );\n },\n);\nexport { ApiKeysSearch };\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,gBAAgB,MAAM,WAC1B,SAAS,cAAc,EAAE,WAAW,GAAG,SAAS,KAAK;CACnD,MAAM,EAAE,UAAU,aAAa,aAAa,mBAC1C,wBAAwB;CAC1B,MAAM,EAAE,aAAa,kBAAkB;CACvC,MAAM,YAAY,eAAe;CAEjC,MAAM,SAAS,sBAAsB,UAAU;EAC7C,SAAS;GAAE,MAAM;GAAoB,aAAa;EAAM,CAAC;CAC3D,GAAG,GAAG;CAEN,MAAM,oBAAoB;EACxB,YAAY;EACZ,OAAO,OAAO;CAChB;CAEA,OACE,qBAACA,eAAD;EACE,KAAK,gBAAgB,UAAU,GAAG;EAClC,WAAW,GAAG,mBAAmB,iBAAiB,GAAG,SAAS;EAC9D,cAAa;EACb,aAAa,UAAU;GACrB,gBAAgB;GAChB,IAAI;GACJ,aAAa;EACf,CAAC;EACD,OAAO;EACP,WAAW,UAAU;GACnB,MAAM,QAAQ,MAAM,OAAO;GAC3B,eAAe,KAAK;GACpB,OAAO,KAAK;EACd;EACA,YAAY,UAAU;GACpB,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,YAAY;GACd;EACF;EACA,GAAI;EArBN,UAAA,CAuBE,oBAACC,eAAD;GAAgB,MAAK;GACnB,UAAA,oBAAC,qBAAD;IAAqB,eAAY;IAAO,QAAO;IAAK,OAAM;GAAM,CAAA;EAClD,CAAA,GAEhB,oBAACA,eAAD;GAAgB,MAAK;GAClB,UAAA,CAAC,CAAC,eACD,oBAAC,YAAD;IACE,MAAK;IACL,SAAS;IACT,OAAO,UAAU;KACf,gBAAgB;KAChB,IAAI;KACJ,aAAa;IACf,CAAC;IAED,UAAA,oBAAC,YAAD,EAAY,eAAY,OAAQ,CAAA;GACtB,CAAA;EAEA,CAAA,CACF;;AAEpB,CACF"}
1
+ {"version":3,"file":"api-keys-search.js","names":["TextField.Root","TextField.Slot"],"sources":["../../../../src/widgets/api-keys/api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { IconButton, TextField } from \"../../components/elements.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useDebouncedCallback } from \"../../lib/use-debounce.js\";\nimport { namespaceClassName } from \"../../lib/widget-dom-props.js\";\nimport { useApiKeysContext } from \"./api-keys-context.js\";\nimport { useApiKeysSearchContext } from \"./api-keys-search-provider.js\";\n\ninterface ApiKeysSearchProps extends TextField.RootProps {}\n\nconst ApiKeysSearch = React.forwardRef<HTMLInputElement, ApiKeysSearchProps>(\n function ApiKeysSearch({ className, ...props }, ref) {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useApiKeysSearchContext();\n const { dispatch } = useApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback(\n (value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n },\n { wait: 200 },\n );\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField.Root\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassName(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextField.Slot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextField.Slot>\n\n <TextField.Slot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextField.Slot>\n </TextField.Root>\n );\n },\n);\nexport { ApiKeysSearch };\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,gBAAgB,MAAM,WAC1B,SAAS,cAAc,EAAE,WAAW,GAAG,SAAS,KAAK;CACnD,MAAM,EAAE,UAAU,aAAa,aAAa,mBAC1C,wBAAwB;CAC1B,MAAM,EAAE,aAAa,kBAAkB;CACvC,MAAM,YAAY,eAAe;CAEjC,MAAM,SAAS,sBACZ,UAAU;EACT,SAAS;GAAE,MAAM;GAAoB,aAAa;EAAM,CAAC;CAC3D,GACA,EAAE,MAAM,IAAI,CACd;CAEA,MAAM,oBAAoB;EACxB,YAAY;EACZ,OAAO,OAAO;CAChB;CAEA,OACE,qBAACA,eAAD;EACE,KAAK,gBAAgB,UAAU,GAAG;EAClC,WAAW,GAAG,mBAAmB,iBAAiB,GAAG,SAAS;EAC9D,cAAa;EACb,aAAa,UAAU;GACrB,gBAAgB;GAChB,IAAI;GACJ,aAAa;EACf,CAAC;EACD,OAAO;EACP,WAAW,UAAU;GACnB,MAAM,QAAQ,MAAM,OAAO;GAC3B,eAAe,KAAK;GACpB,OAAO,KAAK;EACd;EACA,YAAY,UAAU;GACpB,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,YAAY;GACd;EACF;EACA,GAAI;EArBN,UAAA,CAuBE,oBAACC,eAAD;GAAgB,MAAK;GACnB,UAAA,oBAAC,qBAAD;IAAqB,eAAY;IAAO,QAAO;IAAK,OAAM;GAAM,CAAA;EAClD,CAAA,GAEhB,oBAACA,eAAD;GAAgB,MAAK;GAClB,UAAA,CAAC,CAAC,eACD,oBAAC,YAAD;IACE,MAAK;IACL,SAAS;IACT,OAAO,UAAU;KACf,gBAAgB;KAChB,IAAI;KACJ,aAAa;IACf,CAAC;IAED,UAAA,oBAAC,YAAD,EAAY,eAAY,OAAQ,CAAA;GACtB,CAAA;EAEA,CAAA,CACF;;AAEpB,CACF"}
@@ -22,7 +22,7 @@ const UserApiKeysSearch = React.forwardRef(function UserApiKeysSearch({ classNam
22
22
  type: "FILTER_BY_SEARCH",
23
23
  searchQuery: value
24
24
  });
25
- }, 200);
25
+ }, { wait: 200 });
26
26
  const resetSearch = () => {
27
27
  clearSearch();
28
28
  filter.cancel();
@@ -1 +1 @@
1
- {"version":3,"file":"user-api-keys-search.js","names":["TextField.Root","TextField.Slot"],"sources":["../../../../src/widgets/api-keys/user-api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { IconButton, TextField } from \"../../components/elements.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useDebouncedCallback } from \"../../lib/use-debounce.js\";\nimport { namespaceClassName } from \"../../lib/widget-dom-props.js\";\nimport { useUserApiKeysContext } from \"./user-api-keys-context.js\";\nimport { useUserApiKeysSearchContext } from \"./user-api-keys-search-provider.js\";\n\ninterface UserApiKeysSearchProps extends TextField.RootProps {}\n\nconst UserApiKeysSearch = React.forwardRef<\n HTMLInputElement,\n UserApiKeysSearchProps\n>(function UserApiKeysSearch({ className, ...props }, ref) {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useUserApiKeysSearchContext();\n const { dispatch } = useUserApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback((value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n }, 200);\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField.Root\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassName(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextField.Slot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextField.Slot>\n\n <TextField.Slot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextField.Slot>\n </TextField.Root>\n );\n});\nexport { UserApiKeysSearch };\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,oBAAoB,MAAM,WAG9B,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAS,KAAK;CACzD,MAAM,EAAE,UAAU,aAAa,aAAa,mBAC1C,4BAA4B;CAC9B,MAAM,EAAE,aAAa,sBAAsB;CAC3C,MAAM,YAAY,eAAe;CAEjC,MAAM,SAAS,sBAAsB,UAAU;EAC7C,SAAS;GAAE,MAAM;GAAoB,aAAa;EAAM,CAAC;CAC3D,GAAG,GAAG;CAEN,MAAM,oBAAoB;EACxB,YAAY;EACZ,OAAO,OAAO;CAChB;CAEA,OACE,qBAACA,eAAD;EACE,KAAK,gBAAgB,UAAU,GAAG;EAClC,WAAW,GAAG,mBAAmB,iBAAiB,GAAG,SAAS;EAC9D,cAAa;EACb,aAAa,UAAU;GACrB,gBAAgB;GAChB,IAAI;GACJ,aAAa;EACf,CAAC;EACD,OAAO;EACP,WAAW,UAAU;GACnB,MAAM,QAAQ,MAAM,OAAO;GAC3B,eAAe,KAAK;GACpB,OAAO,KAAK;EACd;EACA,YAAY,UAAU;GACpB,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,YAAY;GACd;EACF;EACA,GAAI;EArBN,UAAA,CAuBE,oBAACC,eAAD;GAAgB,MAAK;GACnB,UAAA,oBAAC,qBAAD;IAAqB,eAAY;IAAO,QAAO;IAAK,OAAM;GAAM,CAAA;EAClD,CAAA,GAEhB,oBAACA,eAAD;GAAgB,MAAK;GAClB,UAAA,CAAC,CAAC,eACD,oBAAC,YAAD;IACE,MAAK;IACL,SAAS;IACT,OAAO,UAAU;KACf,gBAAgB;KAChB,IAAI;KACJ,aAAa;IACf,CAAC;IAED,UAAA,oBAAC,YAAD,EAAY,eAAY,OAAQ,CAAA;GACtB,CAAA;EAEA,CAAA,CACF;;AAEpB,CAAC"}
1
+ {"version":3,"file":"user-api-keys-search.js","names":["TextField.Root","TextField.Slot"],"sources":["../../../../src/widgets/api-keys/user-api-keys-search.tsx"],"sourcesContent":["\"use client\";\n\nimport { Cross2Icon, MagnifyingGlassIcon } from \"@radix-ui/react-icons\";\nimport cx from \"clsx\";\nimport * as React from \"react\";\nimport { IconButton, TextField } from \"../../components/elements.js\";\nimport { useComposedRefs } from \"../../lib/compose-refs.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useDebouncedCallback } from \"../../lib/use-debounce.js\";\nimport { namespaceClassName } from \"../../lib/widget-dom-props.js\";\nimport { useUserApiKeysContext } from \"./user-api-keys-context.js\";\nimport { useUserApiKeysSearchContext } from \"./user-api-keys-search-provider.js\";\n\ninterface UserApiKeysSearchProps extends TextField.RootProps {}\n\nconst UserApiKeysSearch = React.forwardRef<\n HTMLInputElement,\n UserApiKeysSearchProps\n>(function UserApiKeysSearch({ className, ...props }, ref) {\n const { inputRef, clearSearch, searchValue, setSearchValue } =\n useUserApiKeysSearchContext();\n const { dispatch } = useUserApiKeysContext();\n const translate = useTranslation();\n\n const filter = useDebouncedCallback(\n (value) => {\n dispatch({ type: \"FILTER_BY_SEARCH\", searchQuery: value });\n },\n { wait: 200 },\n );\n\n const resetSearch = () => {\n clearSearch();\n filter.cancel();\n };\n\n return (\n <TextField.Root\n ref={useComposedRefs(inputRef, ref)}\n className={cx(namespaceClassName(\"api-keys-search\"), className)}\n autoComplete=\"off\"\n placeholder={translate({\n defaultMessage: \"Search by name\",\n id: \"GC8aGI\",\n description: \"Placeholder for API key search input\",\n })}\n value={searchValue}\n onChange={(event) => {\n const value = event.target.value;\n setSearchValue(value);\n filter(value);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n resetSearch();\n }\n }}\n {...props}\n >\n <TextField.Slot side=\"left\">\n <MagnifyingGlassIcon aria-hidden=\"true\" height=\"16\" width=\"16\" />\n </TextField.Slot>\n\n <TextField.Slot side=\"right\">\n {!!searchValue && (\n <IconButton\n size=\"1\"\n onClick={resetSearch}\n title={translate({\n defaultMessage: \"Clear search\",\n id: \"7enwzK\",\n description: \"Title tooltip for clear search button\",\n })}\n >\n <Cross2Icon aria-hidden=\"true\" />\n </IconButton>\n )}\n </TextField.Slot>\n </TextField.Root>\n );\n});\nexport { UserApiKeysSearch };\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAM,oBAAoB,MAAM,WAG9B,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAS,KAAK;CACzD,MAAM,EAAE,UAAU,aAAa,aAAa,mBAC1C,4BAA4B;CAC9B,MAAM,EAAE,aAAa,sBAAsB;CAC3C,MAAM,YAAY,eAAe;CAEjC,MAAM,SAAS,sBACZ,UAAU;EACT,SAAS;GAAE,MAAM;GAAoB,aAAa;EAAM,CAAC;CAC3D,GACA,EAAE,MAAM,IAAI,CACd;CAEA,MAAM,oBAAoB;EACxB,YAAY;EACZ,OAAO,OAAO;CAChB;CAEA,OACE,qBAACA,eAAD;EACE,KAAK,gBAAgB,UAAU,GAAG;EAClC,WAAW,GAAG,mBAAmB,iBAAiB,GAAG,SAAS;EAC9D,cAAa;EACb,aAAa,UAAU;GACrB,gBAAgB;GAChB,IAAI;GACJ,aAAa;EACf,CAAC;EACD,OAAO;EACP,WAAW,UAAU;GACnB,MAAM,QAAQ,MAAM,OAAO;GAC3B,eAAe,KAAK;GACpB,OAAO,KAAK;EACd;EACA,YAAY,UAAU;GACpB,IAAI,MAAM,QAAQ,UAAU;IAC1B,MAAM,eAAe;IACrB,YAAY;GACd;EACF;EACA,GAAI;EArBN,UAAA,CAuBE,oBAACC,eAAD;GAAgB,MAAK;GACnB,UAAA,oBAAC,qBAAD;IAAqB,eAAY;IAAO,QAAO;IAAK,OAAM;GAAM,CAAA;EAClD,CAAA,GAEhB,oBAACA,eAAD;GAAgB,MAAK;GAClB,UAAA,CAAC,CAAC,eACD,oBAAC,YAAD;IACE,MAAK;IACL,SAAS;IACT,OAAO,UAAU;KACf,gBAAgB;KAChB,IAAI;KACJ,aAAa;IACf,CAAC;IAED,UAAA,oBAAC,YAAD,EAAY,eAAY,OAAQ,CAAA;GACtB,CAAA;EAEA,CAAA,CACF;;AAEpB,CAAC"}
@@ -29,7 +29,8 @@ interface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {
29
29
  }
30
30
  declare const OrganizationSwitcherLoading: React.FC<OrganizationSwitcherLoadingProps>;
31
31
  interface OrganizationSwitcherErrorProps extends WidgetRootDomProps {
32
- error: unknown;
32
+ error?: unknown;
33
+ message?: string;
33
34
  variant?: OrganizationSwitcherVariant;
34
35
  }
35
36
  declare const OrganizationSwitcherError: React.FC<OrganizationSwitcherErrorProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"organization-switcher.d.ts","names":[],"sources":["../../../../src/widgets/organization-switcher/organization-switcher.tsx"],"mappings":";;;KAyBK;UAGK,6CAA6C;EACrD,yBACE;IAEA;eACW;EAEb,UAAU;EACV;EACA,WAAW,MAAM;;;;;;;;;EASjB;;KAGG,mBAAmB;UAEd,kCAAkC;EAC1C,eAAe;;cAGX,sBAAsB,MAAM,GAAG;UA6H3B,yCAAyC;EACjD,UAAU;;cAGN,6BAA6B,MAAM,GACvC;UAqBQ,uCAAuC;EAC/C;EACA,UAAU;;cAGN,2BAA2B,MAAM,GAAG"}
1
+ {"version":3,"file":"organization-switcher.d.ts","names":[],"sources":["../../../../src/widgets/organization-switcher/organization-switcher.tsx"],"mappings":";;;KAyBK;UAGK,6CAA6C;EACrD,yBACE;IAEA;eACW;EAEb,UAAU;EACV;EACA,WAAW,MAAM;;;;;;;;;EASjB;;KAGG,mBAAmB;UAEd,kCAAkC;EAC1C,eAAe;;cAGX,sBAAsB,MAAM,GAAG;UAmJ3B,yCAAyC;EACjD,UAAU;;cAGN,6BAA6B,MAAM,GACvC;UAqBQ,uCAAuC;EAC/C;EACA;EACA,UAAU;;cAGN,2BAA2B,MAAM,GAAG"}
@@ -17,7 +17,21 @@ import { CheckIcon } from "@radix-ui/react-icons";
17
17
  const OrganizationSwitcher = ({ organizations, switchToOrganization, variant, organizationLabel = "Organizations", truncateBehavior = "right", children, ...domProps }) => {
18
18
  const currentOrganization = organizations.find((organization) => organization.isCurrent);
19
19
  const invalidateAllWidgets = useWidgetsInvalidator();
20
- if (!currentOrganization) return null;
20
+ const translate = useTranslation();
21
+ if (organizations.length === 0) return /* @__PURE__ */ jsx(OrganizationSwitcherError, {
22
+ variant,
23
+ ...domProps,
24
+ message: translate({
25
+ id: "XimGbo",
26
+ defaultMessage: "No organizations found",
27
+ description: "Shown in the disabled organization switcher when the user belongs to no organizations"
28
+ })
29
+ });
30
+ const currentOrganizationName = currentOrganization?.name ?? translate({
31
+ id: "aZ7eyn",
32
+ defaultMessage: "Select an organization",
33
+ description: "Placeholder in the organization switcher trigger when the user has organizations but none is active"
34
+ });
21
35
  return /* @__PURE__ */ jsxs(Root, { children: [/* @__PURE__ */ jsx(Trigger, { children: /* @__PURE__ */ jsx(Button$1, {
22
36
  variant: "secondary",
23
37
  ...mapVariantProps(variant),
@@ -33,7 +47,7 @@ const OrganizationSwitcher = ({ organizations, switchToOrganization, variant, or
33
47
  overflow: "hidden",
34
48
  minWidth: "0",
35
49
  children: [/* @__PURE__ */ jsx(TruncatedOrganizationName, {
36
- organizationName: currentOrganization.name,
50
+ organizationName: currentOrganizationName,
37
51
  truncateBehavior
38
52
  }), /* @__PURE__ */ jsx(Flex, {
39
53
  asChild: true,
@@ -48,7 +62,7 @@ const OrganizationSwitcher = ({ organizations, switchToOrganization, variant, or
48
62
  minWidth: "180px",
49
63
  children: /* @__PURE__ */ jsx(DropdownMenuItem, {
50
64
  onClick: () => {
51
- if (organization.id !== currentOrganization.id) {
65
+ if (!currentOrganization || organization.id !== currentOrganization.id) {
52
66
  const result = switchToOrganization({ organizationId: organization.id });
53
67
  if (isPromiseLike(result)) result.then(invalidateAllWidgets);
54
68
  else invalidateAllWidgets();
@@ -101,9 +115,9 @@ const OrganizationSwitcherLoading = ({ variant, ...props }) => {
101
115
  })
102
116
  });
103
117
  };
104
- const OrganizationSwitcherError = ({ error, variant, ...domProps }) => {
118
+ const OrganizationSwitcherError = ({ error, variant, message, ...domProps }) => {
105
119
  const translate = useTranslation();
106
- const { heading } = getErrorMessage(error, translate);
120
+ const heading = message || getErrorMessage(error, translate).heading;
107
121
  return /* @__PURE__ */ jsx(Button$1, {
108
122
  variant: "secondary",
109
123
  disabled: true,
@@ -1 +1 @@
1
- {"version":3,"file":"organization-switcher.js","names":["DropdownMenu.Root","DropdownMenu.Trigger","Button","DropdownMenu.TriggerIcon","DropdownMenu.Content","DropdownMenu.Group","DropdownMenu.Label","DropdownMenu.Item","Skeleton"],"sources":["../../../../src/widgets/organization-switcher/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport cx from \"clsx\";\nimport type { ListUserOrganizationsQuery } from \"../../api/client-graphql/generated.js\";\nimport { Button, DropdownMenu, Skeleton } from \"../../components/elements.js\";\nimport type { ButtonProps } from \"../../components/elements.js\";\nimport { getErrorMessage } from \"../../components/generic-error.js\";\nimport { Translation } from \"../../lib/i18n/translation.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useWidgetsInvalidator } from \"../../lib/use-widgets-invalidator.js\";\nimport { isPromiseLike } from \"../../lib/utils.js\";\nimport { getWidgetDomProps } from \"../../lib/widget-dom-props.js\";\nimport type {\n WidgetRootDomProps,\n WidgetRootState,\n} from \"../../lib/widget-types.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ntype UserOrganization = ListUserOrganizationsQuery[\"organizations\"][number];\n\ninterface OrganizationSwitcherProps extends OrganizationSwitcherPassthroughProps {\n organizations: UserOrganization[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.isCurrent,\n );\n const invalidateAllWidgets = useWidgetsInvalidator();\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO(v2): Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.isCurrent && (\n <VisuallyHidden>\n <Translation\n defaultMessage=\"(current)\"\n id=\"daFXTP\"\n description=\"Label for screen readers indicating current organization\"\n />\n </VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.isCurrent ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherError: React.FC<OrganizationSwitcherErrorProps> = ({\n error,\n variant,\n ...domProps\n}) => {\n const translate = useTranslation();\n const { heading } = getErrorMessage(error, translate);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\ninterface TruncatedOrganizationNameProps {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}\n\nconst TruncatedOrganizationName: React.FC<TruncatedOrganizationNameProps> = ({\n organizationName,\n truncateBehavior,\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getWidgetDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\nexport type {\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n OrganizationSwitcherPassthroughProps,\n UserOrganization,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"organization-switcher.js","names":["DropdownMenu.Root","DropdownMenu.Trigger","Button","DropdownMenu.TriggerIcon","DropdownMenu.Content","DropdownMenu.Group","DropdownMenu.Label","DropdownMenu.Item","Skeleton"],"sources":["../../../../src/widgets/organization-switcher/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport cx from \"clsx\";\nimport type { ListUserOrganizationsQuery } from \"../../api/client-graphql/generated.js\";\nimport { Button, DropdownMenu, Skeleton } from \"../../components/elements.js\";\nimport type { ButtonProps } from \"../../components/elements.js\";\nimport { getErrorMessage } from \"../../components/generic-error.js\";\nimport { Translation } from \"../../lib/i18n/translation.js\";\nimport { useTranslation } from \"../../lib/i18n/use-translation.js\";\nimport { useWidgetsInvalidator } from \"../../lib/use-widgets-invalidator.js\";\nimport { isPromiseLike } from \"../../lib/utils.js\";\nimport { getWidgetDomProps } from \"../../lib/widget-dom-props.js\";\nimport type {\n WidgetRootDomProps,\n WidgetRootState,\n} from \"../../lib/widget-types.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ntype UserOrganization = ListUserOrganizationsQuery[\"organizations\"][number];\n\ninterface OrganizationSwitcherProps extends OrganizationSwitcherPassthroughProps {\n organizations: UserOrganization[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.isCurrent,\n );\n const invalidateAllWidgets = useWidgetsInvalidator();\n const translate = useTranslation();\n\n if (organizations.length === 0) {\n return (\n <OrganizationSwitcherError\n variant={variant}\n {...domProps}\n message={translate({\n id: \"XimGbo\",\n defaultMessage: \"No organizations found\",\n description:\n \"Shown in the disabled organization switcher when the user belongs to no organizations\",\n })}\n />\n );\n }\n\n const currentOrganizationName =\n currentOrganization?.name ??\n translate({\n id: \"aZ7eyn\",\n defaultMessage: \"Select an organization\",\n description:\n \"Placeholder in the organization switcher trigger when the user has organizations but none is active\",\n });\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO(v2): Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganizationName}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (\n !currentOrganization ||\n organization.id !== currentOrganization.id\n ) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.isCurrent && (\n <VisuallyHidden>\n <Translation\n defaultMessage=\"(current)\"\n id=\"daFXTP\"\n description=\"Label for screen readers indicating current organization\"\n />\n </VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.isCurrent ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n {/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error?: unknown;\n message?: string;\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherError: React.FC<OrganizationSwitcherErrorProps> = ({\n error,\n variant,\n message,\n ...domProps\n}) => {\n const translate = useTranslation();\n const heading = message || getErrorMessage(error, translate).heading;\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\ninterface TruncatedOrganizationNameProps {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}\n\nconst TruncatedOrganizationName: React.FC<TruncatedOrganizationNameProps> = ({\n organizationName,\n truncateBehavior,\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getWidgetDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\nexport type {\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n OrganizationSwitcherPassthroughProps,\n UserOrganization,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
  import { getWidgetDomProps } from "../../lib/widget-dom-props.js";
3
+ import { clientGraphqlQueryKey } from "../../api/client-graphql/query-keys.js";
3
4
  import { ApiError } from "../../api/errors.js";
4
5
  import { useClientGraphql } from "../../api/client-graphql/client.js";
5
- import { clientGraphqlQueryKey, useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
6
+ import { useClientGraphqlMutation, useClientGraphqlQuery } from "../../api/client-graphql/hooks.js";
6
7
  import { Button as Button$1 } from "../../components/elements/button.js";
7
8
  import { IconButton as IconButton$1 } from "../../components/elements/icon-button.js";
8
9
  import { Label } from "../../components/elements/label.js";