@sanity/sdk-react 0.0.0-alpha.3 → 0.0.0-alpha.31

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 (131) hide show
  1. package/README.md +6 -100
  2. package/dist/index.d.ts +2390 -2
  3. package/dist/index.js +1119 -2
  4. package/dist/index.js.map +1 -1
  5. package/package.json +35 -49
  6. package/src/_exports/index.ts +2 -10
  7. package/src/_exports/sdk-react.ts +73 -0
  8. package/src/components/SDKProvider.test.tsx +103 -0
  9. package/src/components/SDKProvider.tsx +52 -0
  10. package/src/components/SanityApp.test.tsx +244 -0
  11. package/src/components/SanityApp.tsx +106 -0
  12. package/src/components/auth/AuthBoundary.test.tsx +204 -29
  13. package/src/components/auth/AuthBoundary.tsx +96 -19
  14. package/src/components/auth/ConfigurationError.ts +22 -0
  15. package/src/components/auth/LoginCallback.test.tsx +22 -24
  16. package/src/components/auth/LoginCallback.tsx +6 -16
  17. package/src/components/auth/LoginError.test.tsx +11 -18
  18. package/src/components/auth/LoginError.tsx +43 -25
  19. package/src/components/utils.ts +22 -0
  20. package/src/context/ResourceProvider.test.tsx +157 -0
  21. package/src/context/ResourceProvider.tsx +111 -0
  22. package/src/context/SanityInstanceContext.ts +4 -0
  23. package/src/hooks/_synchronous-groq-js.mjs +4 -0
  24. package/src/hooks/auth/useAuthState.tsx +4 -5
  25. package/src/hooks/auth/useAuthToken.tsx +1 -1
  26. package/src/hooks/auth/useCurrentUser.tsx +28 -4
  27. package/src/hooks/auth/useDashboardOrganizationId.test.tsx +42 -0
  28. package/src/hooks/auth/useDashboardOrganizationId.tsx +30 -0
  29. package/src/hooks/auth/useHandleAuthCallback.test.tsx +16 -0
  30. package/src/hooks/auth/{useHandleCallback.tsx → useHandleAuthCallback.tsx} +7 -6
  31. package/src/hooks/auth/useLogOut.test.tsx +2 -2
  32. package/src/hooks/auth/useLogOut.tsx +1 -1
  33. package/src/hooks/auth/useLoginUrl.tsx +14 -0
  34. package/src/hooks/auth/useVerifyOrgProjects.test.tsx +136 -0
  35. package/src/hooks/auth/useVerifyOrgProjects.tsx +48 -0
  36. package/src/hooks/client/useClient.ts +13 -33
  37. package/src/hooks/comlink/useFrameConnection.test.tsx +167 -0
  38. package/src/hooks/comlink/useFrameConnection.ts +107 -0
  39. package/src/hooks/comlink/useManageFavorite.test.ts +368 -0
  40. package/src/hooks/comlink/useManageFavorite.ts +210 -0
  41. package/src/hooks/comlink/useRecordDocumentHistoryEvent.test.ts +85 -0
  42. package/src/hooks/comlink/useRecordDocumentHistoryEvent.ts +115 -0
  43. package/src/hooks/comlink/useWindowConnection.test.ts +135 -0
  44. package/src/hooks/comlink/useWindowConnection.ts +123 -0
  45. package/src/hooks/context/useSanityInstance.test.tsx +157 -15
  46. package/src/hooks/context/useSanityInstance.ts +68 -11
  47. package/src/hooks/dashboard/useNavigateToStudioDocument.test.ts +276 -0
  48. package/src/hooks/dashboard/useNavigateToStudioDocument.ts +139 -0
  49. package/src/hooks/dashboard/useStudioWorkspacesByProjectIdDataset.test.tsx +291 -0
  50. package/src/hooks/dashboard/useStudioWorkspacesByProjectIdDataset.ts +101 -0
  51. package/src/hooks/datasets/useDatasets.test.ts +80 -0
  52. package/src/hooks/datasets/useDatasets.ts +52 -0
  53. package/src/hooks/document/useApplyDocumentActions.test.ts +20 -0
  54. package/src/hooks/document/useApplyDocumentActions.ts +124 -0
  55. package/src/hooks/document/useDocument.test.ts +118 -0
  56. package/src/hooks/document/useDocument.ts +212 -0
  57. package/src/hooks/document/useDocumentEvent.test.ts +62 -0
  58. package/src/hooks/document/useDocumentEvent.ts +94 -0
  59. package/src/hooks/document/useDocumentPermissions.test.ts +204 -0
  60. package/src/hooks/document/useDocumentPermissions.ts +131 -0
  61. package/src/hooks/document/useDocumentSyncStatus.test.ts +23 -0
  62. package/src/hooks/document/useDocumentSyncStatus.ts +61 -0
  63. package/src/hooks/document/useEditDocument.test.ts +196 -0
  64. package/src/hooks/document/useEditDocument.ts +314 -0
  65. package/src/hooks/documents/useDocuments.test.tsx +179 -0
  66. package/src/hooks/documents/useDocuments.ts +300 -0
  67. package/src/hooks/helpers/createCallbackHook.test.tsx +2 -2
  68. package/src/hooks/helpers/createCallbackHook.tsx +1 -1
  69. package/src/hooks/helpers/createStateSourceHook.test.tsx +67 -1
  70. package/src/hooks/helpers/createStateSourceHook.tsx +27 -11
  71. package/src/hooks/paginatedDocuments/usePaginatedDocuments.test.tsx +284 -0
  72. package/src/hooks/paginatedDocuments/usePaginatedDocuments.ts +353 -0
  73. package/src/hooks/preview/usePreview.test.tsx +85 -17
  74. package/src/hooks/preview/usePreview.tsx +81 -22
  75. package/src/hooks/projection/useProjection.test.tsx +283 -0
  76. package/src/hooks/projection/useProjection.ts +232 -0
  77. package/src/hooks/projects/useProject.test.ts +80 -0
  78. package/src/hooks/projects/useProject.ts +51 -0
  79. package/src/hooks/projects/useProjects.test.ts +77 -0
  80. package/src/hooks/projects/useProjects.ts +45 -0
  81. package/src/hooks/query/useQuery.test.tsx +188 -0
  82. package/src/hooks/query/useQuery.ts +193 -0
  83. package/src/hooks/releases/useActiveReleases.test.tsx +84 -0
  84. package/src/hooks/releases/useActiveReleases.ts +39 -0
  85. package/src/hooks/releases/usePerspective.test.tsx +120 -0
  86. package/src/hooks/releases/usePerspective.ts +49 -0
  87. package/src/hooks/users/useUsers.test.tsx +330 -0
  88. package/src/hooks/users/useUsers.ts +120 -0
  89. package/src/utils/getEnv.ts +21 -0
  90. package/src/version.ts +8 -0
  91. package/src/vite-env.d.ts +10 -0
  92. package/dist/_chunks-es/useLogOut.js +0 -44
  93. package/dist/_chunks-es/useLogOut.js.map +0 -1
  94. package/dist/assets/bundle-CcAyERuZ.css +0 -11
  95. package/dist/components.d.ts +0 -259
  96. package/dist/components.js +0 -301
  97. package/dist/components.js.map +0 -1
  98. package/dist/hooks.d.ts +0 -186
  99. package/dist/hooks.js +0 -81
  100. package/dist/hooks.js.map +0 -1
  101. package/src/_exports/components.ts +0 -13
  102. package/src/_exports/hooks.ts +0 -9
  103. package/src/components/DocumentGridLayout/DocumentGridLayout.stories.tsx +0 -113
  104. package/src/components/DocumentGridLayout/DocumentGridLayout.test.tsx +0 -42
  105. package/src/components/DocumentGridLayout/DocumentGridLayout.tsx +0 -21
  106. package/src/components/DocumentListLayout/DocumentListLayout.stories.tsx +0 -105
  107. package/src/components/DocumentListLayout/DocumentListLayout.test.tsx +0 -42
  108. package/src/components/DocumentListLayout/DocumentListLayout.tsx +0 -12
  109. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.md +0 -49
  110. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.stories.tsx +0 -39
  111. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.test.tsx +0 -30
  112. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.tsx +0 -171
  113. package/src/components/Login/LoginLinks.test.tsx +0 -100
  114. package/src/components/Login/LoginLinks.tsx +0 -73
  115. package/src/components/auth/Login.test.tsx +0 -41
  116. package/src/components/auth/Login.tsx +0 -45
  117. package/src/components/auth/LoginFooter.test.tsx +0 -29
  118. package/src/components/auth/LoginFooter.tsx +0 -65
  119. package/src/components/auth/LoginLayout.test.tsx +0 -33
  120. package/src/components/auth/LoginLayout.tsx +0 -81
  121. package/src/components/context/SanityProvider.test.tsx +0 -25
  122. package/src/components/context/SanityProvider.tsx +0 -42
  123. package/src/css/css.config.js +0 -220
  124. package/src/css/paramour.css +0 -2347
  125. package/src/css/styles.css +0 -11
  126. package/src/hooks/auth/useHandleCallback.test.tsx +0 -16
  127. package/src/hooks/auth/useLoginUrls.test.tsx +0 -68
  128. package/src/hooks/auth/useLoginUrls.tsx +0 -51
  129. package/src/hooks/client/useClient.test.tsx +0 -130
  130. package/src/hooks/documentCollection/useDocuments.test.ts +0 -130
  131. package/src/hooks/documentCollection/useDocuments.ts +0 -87
@@ -1,259 +0,0 @@
1
- import {FallbackProps} from 'react-error-boundary'
2
- import {ForwardRefExoticComponent} from 'react'
3
- import {JSX} from 'react'
4
- import type {PropsWithChildren} from 'react'
5
- import {ReactElement} from 'react'
6
- import {RefAttributes} from 'react'
7
- import {SanityInstance} from '@sanity/sdk'
8
-
9
- /**
10
- * A component that handles authentication flow and error boundaries for a
11
- * protected section of the application.
12
- *
13
- * @remarks
14
- * This component manages different authentication states and renders the
15
- * appropriate components based on that state.
16
- *
17
- * @example
18
- * ```tsx
19
- * function App() {
20
- * return (
21
- * <AuthBoundary header={<MyLogo />}>
22
- * <ProtectedContent />
23
- * </AuthBoundary>
24
- * )
25
- * }
26
- * ```
27
- *
28
- * @alpha
29
- */
30
- export declare function AuthBoundary({
31
- LoginErrorComponent,
32
- ...props
33
- }: AuthBoundaryProps): React.ReactNode
34
-
35
- /**
36
- * @alpha
37
- */
38
- export declare interface AuthBoundaryProps extends LoginLayoutProps {
39
- /**
40
- * Custom component to render the login screen.
41
- * Receives all login layout props. Defaults to {@link Login}.
42
- */
43
- LoginComponent?: React.ComponentType<LoginLayoutProps>
44
- /**
45
- * Custom component to render during OAuth callback processing.
46
- * Receives all login layout props. Defaults to {@link LoginCallback}.
47
- */
48
- CallbackComponent?: React.ComponentType<LoginLayoutProps>
49
- /**
50
- * Custom component to render when authentication errors occur.
51
- * Receives login layout props and error boundary props. Defaults to
52
- * {@link LoginError}
53
- */
54
- LoginErrorComponent?: React.ComponentType<LoginErrorProps>
55
- }
56
-
57
- /**
58
- * Error class for authentication-related errors. Wraps errors thrown during the
59
- * authentication flow.
60
- *
61
- * @remarks
62
- * This class provides a consistent error type for authentication failures while
63
- * preserving the original error as the cause. If the original error has a
64
- * message property, it will be used as the error message.
65
- *
66
- * @alpha
67
- */
68
- export declare class AuthError extends Error {
69
- constructor(error: unknown)
70
- }
71
-
72
- /**
73
- * @public
74
- */
75
- export declare const DocumentGridLayout: {
76
- (props: PropsWithChildren): ReactElement
77
- displayName: string
78
- }
79
-
80
- /**
81
- * @public
82
- */
83
- export declare const DocumentListLayout: {
84
- (props: PropsWithChildren): ReactElement
85
- displayName: string
86
- }
87
-
88
- /**
89
- * This is a component that renders a document preview.
90
- *
91
- * @public
92
- *
93
- * @param props - The props for the DocumentPreviewLayout component.
94
- * @returns - The DocumentPreviewLayout component.
95
- */
96
- export declare const DocumentPreviewLayout: ForwardRefExoticComponent<
97
- DocumentPreviewLayoutProps & RefAttributes<HTMLElement>
98
- >
99
-
100
- /**
101
- * @public
102
- */
103
- export declare interface DocumentPreviewLayoutProps {
104
- docType?: string
105
- media?:
106
- | {
107
- type: string
108
- url: string
109
- }
110
- | null
111
- | undefined
112
- onClick?: () => void
113
- selected?: boolean
114
- status?: string
115
- subtitle?: string
116
- title: string
117
- }
118
-
119
- /**
120
- * Login component that displays available authentication providers.
121
- * Renders a list of login options with a loading fallback while providers load.
122
- *
123
- * @alpha
124
- */
125
- export declare function Login({header, footer}: LoginLayoutProps): JSX.Element
126
-
127
- /**
128
- /**
129
- * Component shown during auth callback processing that handles login completion.
130
- * Automatically processes the auth callback when mounted and updates the URL
131
- * to remove callback parameters without triggering a page reload.
132
- *
133
- * @alpha
134
- */
135
- export declare function LoginCallback({header, footer}: LoginLayoutProps): React.ReactNode
136
-
137
- /**
138
- * Displays authentication error details and provides retry functionality.
139
- * Only handles {@link AuthError} instances - rethrows other error types.
140
- *
141
- * @alpha
142
- */
143
- export declare function LoginError({
144
- error,
145
- resetErrorBoundary,
146
- header,
147
- footer,
148
- }: LoginErrorProps): React.ReactNode
149
-
150
- /**
151
- * @alpha
152
- */
153
- export declare type LoginErrorProps = FallbackProps & LoginLayoutProps
154
-
155
- /**
156
- * Layout component for login-related screens providing consistent styling and structure.
157
- * Renders content in a centered card with optional header and footer sections.
158
- *
159
- * Can be used to build custom login screens for the AuthBoundary component, including:
160
- * - Login provider selection (LoginComponent)
161
- * - OAuth callback handling (CallbackComponent)
162
- * - Error states (LoginErrorComponent)
163
- *
164
- * @example
165
- * ```tsx
166
- * // Custom login screen using the layout
167
- * function CustomLogin({header, footer}: LoginLayoutProps) {
168
- * return (
169
- * <LoginLayout
170
- * header={header}
171
- * footer={footer}
172
- * >
173
- * <CustomLoginContent />
174
- * </LoginLayout>
175
- * )
176
- * }
177
- *
178
- * // Use with AuthBoundary
179
- * <AuthBoundary
180
- * LoginComponent={CustomLogin}
181
- * header={<Logo />}
182
- * >
183
- * <ProtectedContent />
184
- * </AuthBoundary>
185
- * ```
186
- *
187
- * @alpha
188
- */
189
- export declare function LoginLayout({children, footer, header}: LoginLayoutProps): React.ReactNode
190
-
191
- /**
192
- * @alpha
193
- */
194
- export declare interface LoginLayoutProps {
195
- /** Optional header content rendered at top of card */
196
- header?: React.ReactNode
197
- /** Optional footer content rendered below card. Defaults to an internal login footer */
198
- footer?: React.ReactNode
199
- /** Main content rendered in card body */
200
- children?: React.ReactNode
201
- }
202
-
203
- /**
204
- * Component that handles Sanity authentication flow and renders login provider options
205
- *
206
- * @public
207
- *
208
- * @returns Rendered component
209
- *
210
- * @remarks
211
- * The component handles three states:
212
- * 1. Loading state during token exchange
213
- * 2. Success state after successful authentication
214
- * 3. Provider selection UI when not authenticated
215
- *
216
- * @example
217
- * ```tsx
218
- * const config = { projectId: 'your-project-id', dataset: 'production' }
219
- * return <LoginLinks sanityInstance={config} />
220
- * ```
221
- */
222
- export declare const LoginLinks: () => ReactElement
223
-
224
- /**
225
- * Top-level context provider that provides a Sanity configuration instance.
226
- * This must wrap any Sanity SDK React component.
227
- * @public
228
- * @param props - Sanity project and dataset configuration
229
- * @returns Rendered component
230
- * @example
231
- * ```tsx
232
- * import {createSanityInstance} from '@sanity/sdk'
233
- * import {ExampleComponent, SanityProvider} from '@sanity/sdk-react'
234
- *
235
- * const sanityInstance = createSanityInstance({projectId: 'your-project-id', dataset: 'production'})
236
- *
237
- * export default function MyApp() {
238
- * return (
239
- * <SanityProvider sanityInstance={sanityInstance}>
240
- * <ExampleComponent />
241
- * </SanityProvider>
242
- * )
243
- * }
244
- * ```
245
- */
246
- export declare const SanityProvider: ({
247
- children,
248
- sanityInstance,
249
- }: SanityProviderProps) => ReactElement
250
-
251
- /**
252
- * @public
253
- */
254
- export declare interface SanityProviderProps {
255
- children: React.ReactNode
256
- sanityInstance: SanityInstance
257
- }
258
-
259
- export {}
@@ -1,301 +0,0 @@
1
- import { jsxs, jsx, Fragment as Fragment$1 } from "react/jsx-runtime";
2
- import { AuthStateType } from "@sanity/sdk";
3
- import { Fragment, Suspense, useEffect, useCallback, useMemo, forwardRef } from "react";
4
- import { ErrorBoundary } from "react-error-boundary";
5
- import { useLoginUrls, useHandleCallback, useLogOut, useAuthState } from "./_chunks-es/useLogOut.js";
6
- import { SanityProvider } from "./_chunks-es/useLogOut.js";
7
- import { Flex, Text, Card, Heading, Spinner, Button, Container, Stack } from "@sanity/ui";
8
- import { SanityLogo } from "@sanity/logos";
9
- import { DocumentIcon } from "@sanity/icons";
10
- class AuthError extends Error {
11
- constructor(error) {
12
- typeof error == "object" && error && "message" in error && typeof error.message == "string" ? super(error.message) : super(), this.cause = error;
13
- }
14
- }
15
- const LINKS = [
16
- {
17
- url: "https://slack.sanity.io/",
18
- i18nKey: "workspaces.community-title",
19
- title: "Community"
20
- },
21
- {
22
- url: "https://www.sanity.io/docs",
23
- i18nKey: "workspaces.docs-title",
24
- title: "Docs"
25
- },
26
- {
27
- url: "https://www.sanity.io/legal/privacy",
28
- i18nKey: "workspaces.privacy-title",
29
- title: "Privacy"
30
- },
31
- {
32
- url: "https://www.sanity.io",
33
- i18nKey: "workspaces.sanity-io-title",
34
- title: "sanity.io"
35
- }
36
- ];
37
- function LoginFooter() {
38
- return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, justify: "center", align: "center", paddingTop: 2, children: [
39
- /* @__PURE__ */ jsx(Text, { size: 3, children: /* @__PURE__ */ jsx(SanityLogo, {}) }),
40
- /* @__PURE__ */ jsx(Flex, { align: "center", gap: 2, children: LINKS.map((link, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
41
- /* @__PURE__ */ jsx(Text, { muted: !0, size: 1, children: /* @__PURE__ */ jsx(
42
- "a",
43
- {
44
- href: link.url,
45
- target: "_blank",
46
- rel: "noopener noreferrer",
47
- style: { color: "inherit" },
48
- children: link.title
49
- }
50
- ) }),
51
- index < LINKS.length - 1 && /* @__PURE__ */ jsx(Text, { size: 1, muted: !0, children: "\u2022" })
52
- ] }, link.title)) })
53
- ] });
54
- }
55
- function LoginLayout({
56
- children,
57
- footer = /* @__PURE__ */ jsx(LoginFooter, {}),
58
- header
59
- }) {
60
- return /* @__PURE__ */ jsx("div", { style: { width: "100%", display: "flex" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, style: { width: "320px", margin: "auto", display: "flex" }, children: [
61
- /* @__PURE__ */ jsx(Card, { border: !0, radius: 2, paddingY: 4, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
62
- header && /* @__PURE__ */ jsx(Card, { borderBottom: !0, paddingX: 4, paddingBottom: 3, children: header }),
63
- children && /* @__PURE__ */ jsx(Flex, { paddingX: 4, direction: "column", style: { minHeight: "154px" }, children })
64
- ] }) }),
65
- footer
66
- ] }) });
67
- }
68
- function Login({ header, footer }) {
69
- return /* @__PURE__ */ jsx(LoginLayout, { header, footer, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
70
- /* @__PURE__ */ jsx(Heading, { as: "h1", size: 1, align: "center", children: "Choose login provider" }),
71
- /* @__PURE__ */ jsx(
72
- Suspense,
73
- {
74
- fallback: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "center", style: { height: "123px" }, children: /* @__PURE__ */ jsx(Spinner, {}) }),
75
- children: /* @__PURE__ */ jsx(Providers, {})
76
- }
77
- )
78
- ] }) });
79
- }
80
- function Providers() {
81
- const loginUrls = useLoginUrls();
82
- return /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 3, children: loginUrls.map(({ title, url }) => /* @__PURE__ */ jsx(Button, { text: title, as: "a", href: url, mode: "ghost" }, url)) });
83
- }
84
- function LoginCallback({ header, footer }) {
85
- const handleCallback = useHandleCallback();
86
- return useEffect(() => {
87
- const url = new URL(location.href);
88
- handleCallback(url.toString()).then((replacementLocation) => {
89
- replacementLocation && history.replaceState(null, "", replacementLocation);
90
- });
91
- }, [handleCallback]), /* @__PURE__ */ jsx(LoginLayout, { header, footer, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justify: "center", align: "center", gap: 4, style: { margin: "auto" }, children: [
92
- /* @__PURE__ */ jsx(Text, { size: 1, children: "Logging you in\u2026" }),
93
- /* @__PURE__ */ jsx(Spinner, { size: 4 })
94
- ] }) });
95
- }
96
- function LoginError({
97
- error,
98
- resetErrorBoundary,
99
- header,
100
- footer
101
- }) {
102
- if (!(error instanceof AuthError)) throw error;
103
- const logout = useLogOut(), handleRetry = useCallback(async () => {
104
- await logout(), resetErrorBoundary();
105
- }, [logout, resetErrorBoundary]);
106
- return /* @__PURE__ */ jsx(LoginLayout, { header, footer, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, style: { margin: "auto" }, children: [
107
- /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, children: [
108
- /* @__PURE__ */ jsx(Text, { as: "h2", align: "center", weight: "bold", size: 3, children: "Authentication Error" }),
109
- /* @__PURE__ */ jsx(Text, { size: 1, align: "center", children: "Please try again or contact support if the problem persists." })
110
- ] }),
111
- /* @__PURE__ */ jsx(Button, { text: "Retry", tone: "primary", onClick: handleRetry })
112
- ] }) });
113
- }
114
- function AuthBoundary({
115
- LoginErrorComponent = LoginError,
116
- ...props
117
- }) {
118
- const { header, footer } = props, FallbackComponent = useMemo(() => function(fallbackProps) {
119
- return /* @__PURE__ */ jsx(LoginErrorComponent, { ...fallbackProps, header, footer });
120
- }, [header, footer, LoginErrorComponent]);
121
- return /* @__PURE__ */ jsx(ErrorBoundary, { FallbackComponent, children: /* @__PURE__ */ jsx(AuthSwitch, { ...props }) });
122
- }
123
- function AuthSwitch({
124
- LoginComponent = Login,
125
- CallbackComponent = LoginCallback,
126
- children,
127
- ...props
128
- }) {
129
- const authState = useAuthState();
130
- switch (authState.type) {
131
- case AuthStateType.ERROR:
132
- throw new AuthError(authState.error);
133
- case AuthStateType.LOGGING_IN:
134
- return /* @__PURE__ */ jsx(CallbackComponent, { ...props });
135
- case AuthStateType.LOGGED_IN:
136
- return children;
137
- default:
138
- return /* @__PURE__ */ jsx(LoginComponent, { ...props });
139
- }
140
- }
141
- const DocumentGridLayout = (props) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
142
- /* @__PURE__ */ jsx("style", { children: `
143
- .DocumentGridLayout {
144
- grid-template-columns: repeat(auto-fit, minmax(38ch, 1fr));
145
- }
146
- ` }),
147
- /* @__PURE__ */ jsx("ol", { className: "DocumentGridLayout list-none grid", children: props.children })
148
- ] });
149
- DocumentGridLayout.displayName = "DocumentGridLayout";
150
- const DocumentListLayout = (props) => /* @__PURE__ */ jsx("ol", { className: "DocumentListLayout list-none", children: props.children });
151
- DocumentListLayout.displayName = "DocumentListLayout";
152
- const DocumentPreviewLayout = forwardRef(
153
- ({
154
- docType,
155
- media,
156
- onClick,
157
- selected = !1,
158
- status = "",
159
- subtitle = "",
160
- title
161
- }, ref) => {
162
- if (!title)
163
- return /* @__PURE__ */ jsx(Fragment$1, {});
164
- let PreviewMedia;
165
- if (media?.url) {
166
- const baseUrl = new URL(media.url);
167
- baseUrl.searchParams.set("h", "66"), baseUrl.searchParams.set("w", "66"), baseUrl.searchParams.set("fit", "crop");
168
- const mediaUrl = baseUrl.toString();
169
- PreviewMedia = /* @__PURE__ */ jsx("img", { src: mediaUrl, alt: "" });
170
- } else
171
- PreviewMedia = /* @__PURE__ */ jsx(DocumentIcon, {});
172
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [
173
- /* @__PURE__ */ jsx("style", { children: `
174
- .DocumentPreviewLayout {
175
- --_hoverFocusBg: light-dark(var(--shade-11), var(--tint-1));
176
- --_selectedBg: light-dark(var(--blue-10), var(--blue-2));
177
- --_selectedFg: light-dark(var(--gray-1), var(--gray-10));
178
- --_titleFg: light-dark(var(--gray-1), var(--gray-10));
179
- --_subtitleFg: light-dark(var(--gray-4), var(--gray-7));
180
- --_docTypeFg: light-dark(var(--gray-1), var(--gray-10));
181
- --_docTypeBg: light-dark(var(--shade-10), var(--tint-1));
182
- --_publishedFg: light-dark(var(--gray-1), var(--gray-10));
183
- --_publishedBg: light-dark(var(--green-10), var(--green-2));
184
- --_draftFg: light-dark(var(--gray-1), var(--gray-10));
185
- --_draftBg: light-dark(var(--yellow-6), var(--yellow-2));
186
-
187
- appearance: none;
188
-
189
- &:has(:hover, focus) {
190
- background-color: var(--hoverFocusBg, var(--_hoverFocusBg));
191
- }
192
-
193
- &.selected {
194
- background-color: var(--selectedBg, var(--_selectedBg));
195
- color: var(--selectedFg, var(--_selectedFg));
196
- }
197
-
198
- .Title {
199
- color: var(--titleFg, var(--_titleFg));
200
- }
201
-
202
- &:not(.selected) .Subtitle {
203
- color: var(--subtitleFg, var(--_subtitleFg));
204
- }
205
-
206
- .Media {
207
- aspect-ratio: 1;
208
- inline-size: 33px;
209
- border-color: var(--gray-8);
210
- }
211
-
212
- .DocType {
213
- color: var(--docTypeFg, var(--_docTypeFg));
214
- background-color: var(--docTypeBg, var(--_docTypeBg));
215
- }
216
-
217
- .Published {
218
- color: var(--publishedFg, var(--_publishedFg));
219
- background-color: var(--publishedBg, var(--_publishedBg));
220
- }
221
-
222
- .Draft {
223
- color: var(--draftFg, var(--_draftFg));
224
- background-color: var(--draftBg, var(--_draftBg));
225
- }
226
-
227
- :is(.Published, .Draft) figcaption {
228
- @container (width < 52ch) {
229
- clip: rect(0 0 0 0);
230
- clip-path: inset(50%);
231
- height: 1px;
232
- overflow: hidden;
233
- position: absolute;
234
- white-space: nowrap;
235
- width: 1px;
236
- }
237
- }
238
-
239
- }
240
- ` }),
241
- /* @__PURE__ */ jsx(
242
- "button",
243
- {
244
- onClick,
245
- ref,
246
- className: `DocumentPreviewLayout block si-100 text-start p-1 radius1 ${selected ? "selected" : ""}`,
247
- children: /* @__PURE__ */ jsxs("div", { className: "container-inline flex align-items-center gap-2 font-sans", children: [
248
- /* @__PURE__ */ jsx("figure", { className: "Media border0 border-solid flex-none flex align-items-center justify-content-center object-cover", children: PreviewMedia }),
249
- /* @__PURE__ */ jsxs("div", { className: "leading2 flex-grow overflow-hidden", children: [
250
- /* @__PURE__ */ jsx("p", { className: "Title text-1 font-medium truncate", children: title }),
251
- subtitle && /* @__PURE__ */ jsx("p", { className: "Subtitle text-1 truncate", children: subtitle })
252
- ] }),
253
- docType && /* @__PURE__ */ jsx("figure", { className: "DocType inline-block pb-5 pi-3 radius-pill text-2", children: /* @__PURE__ */ jsx("figcaption", { className: "inline", children: docType }) }),
254
- status === "published" && /* @__PURE__ */ jsxs("figure", { className: "Published inline-block pb-5 pi-3 radius-pill text-2", children: [
255
- "\u2714\uFE0E ",
256
- /* @__PURE__ */ jsx("figcaption", { className: "inline", children: "published" })
257
- ] }),
258
- status === "draft" && /* @__PURE__ */ jsxs("figure", { className: "Draft inline-block pb-5 pi-3 radius-pill text-2", children: [
259
- "\u26D1\uFE0E ",
260
- /* @__PURE__ */ jsx("figcaption", { className: "inline", children: "draft" })
261
- ] })
262
- ] })
263
- }
264
- )
265
- ] });
266
- }
267
- );
268
- DocumentPreviewLayout.displayName = "DocumentPreviewLayout";
269
- const LoginLinks = () => {
270
- const loginUrls = useLoginUrls(), authState = useAuthState();
271
- return useHandleCallback(), authState.type === "logging-in" ? /* @__PURE__ */ jsx("div", { children: "Logging in..." }) : authState.type === "logged-in" ? /* @__PURE__ */ jsx("div", { children: "You are logged in" }) : /* @__PURE__ */ jsx(Card, { height: "fill", overflow: "auto", paddingX: 4, children: /* @__PURE__ */ jsx(Flex, { height: "fill", direction: "column", align: "center", justify: "center", paddingTop: 4, children: /* @__PURE__ */ jsx(Container, { width: 0, children: /* @__PURE__ */ jsxs(Stack, { space: 4, children: [
272
- /* @__PURE__ */ jsx(Heading, { align: "center", size: 1, children: "Choose login provider" }),
273
- /* @__PURE__ */ jsx(Stack, { space: 2, children: loginUrls.map((provider, index) => /* @__PURE__ */ jsx(
274
- Button,
275
- {
276
- as: "a",
277
- href: provider.url,
278
- mode: "ghost",
279
- tone: "default",
280
- space: 3,
281
- padding: 3,
282
- text: provider.title
283
- },
284
- `${provider.url}_${index}`
285
- )) })
286
- ] }) }) }) });
287
- };
288
- export {
289
- AuthBoundary,
290
- AuthError,
291
- DocumentGridLayout,
292
- DocumentListLayout,
293
- DocumentPreviewLayout,
294
- Login,
295
- LoginCallback,
296
- LoginError,
297
- LoginLayout,
298
- LoginLinks,
299
- SanityProvider
300
- };
301
- //# sourceMappingURL=components.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"components.js","sources":["../src/components/auth/AuthError.ts","../src/components/auth/LoginFooter.tsx","../src/components/auth/LoginLayout.tsx","../src/components/auth/Login.tsx","../src/components/auth/LoginCallback.tsx","../src/components/auth/LoginError.tsx","../src/components/auth/AuthBoundary.tsx","../src/components/DocumentGridLayout/DocumentGridLayout.tsx","../src/components/DocumentListLayout/DocumentListLayout.tsx","../src/components/DocumentPreviewLayout/DocumentPreviewLayout.tsx","../src/components/Login/LoginLinks.tsx"],"sourcesContent":["/**\n * Error class for authentication-related errors. Wraps errors thrown during the\n * authentication flow.\n *\n * @remarks\n * This class provides a consistent error type for authentication failures while\n * preserving the original error as the cause. If the original error has a\n * message property, it will be used as the error message.\n *\n * @alpha\n */\nexport class AuthError extends Error {\n constructor(error: unknown) {\n if (\n typeof error === 'object' &&\n !!error &&\n 'message' in error &&\n typeof error.message === 'string'\n ) {\n super(error.message)\n } else {\n super()\n }\n\n this.cause = error\n }\n}\n","import {SanityLogo} from '@sanity/logos'\nimport {Flex, Text} from '@sanity/ui'\nimport {Fragment} from 'react'\n\nconst LINKS = [\n {\n url: 'https://slack.sanity.io/',\n i18nKey: 'workspaces.community-title',\n title: 'Community',\n },\n {\n url: 'https://www.sanity.io/docs',\n i18nKey: 'workspaces.docs-title',\n title: 'Docs',\n },\n {\n url: 'https://www.sanity.io/legal/privacy',\n i18nKey: 'workspaces.privacy-title',\n title: 'Privacy',\n },\n {\n url: 'https://www.sanity.io',\n i18nKey: 'workspaces.sanity-io-title',\n title: 'sanity.io',\n },\n]\n\n/**\n * Default footer component for login screens showing Sanity branding and legal\n * links.\n *\n * @alpha\n */\nexport function LoginFooter(): React.ReactNode {\n return (\n <Flex direction=\"column\" gap={4} justify=\"center\" align=\"center\" paddingTop={2}>\n <Text size={3}>\n <SanityLogo />\n </Text>\n\n <Flex align=\"center\" gap={2}>\n {LINKS.map((link, index) => (\n <Fragment key={link.title}>\n <Text muted size={1}>\n <a\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{color: 'inherit'}}\n >\n {link.title}\n </a>\n </Text>\n\n {index < LINKS.length - 1 && (\n <Text size={1} muted>\n •\n </Text>\n )}\n </Fragment>\n ))}\n </Flex>\n </Flex>\n )\n}\n","import {Card, Flex} from '@sanity/ui'\n\nimport {LoginFooter} from './LoginFooter'\n\n/**\n * @alpha\n */\nexport interface LoginLayoutProps {\n /** Optional header content rendered at top of card */\n header?: React.ReactNode\n\n /** Optional footer content rendered below card. Defaults to an internal login footer */\n footer?: React.ReactNode\n\n /** Main content rendered in card body */\n children?: React.ReactNode\n}\n\n/**\n * Layout component for login-related screens providing consistent styling and structure.\n * Renders content in a centered card with optional header and footer sections.\n *\n * Can be used to build custom login screens for the AuthBoundary component, including:\n * - Login provider selection (LoginComponent)\n * - OAuth callback handling (CallbackComponent)\n * - Error states (LoginErrorComponent)\n *\n * @example\n * ```tsx\n * // Custom login screen using the layout\n * function CustomLogin({header, footer}: LoginLayoutProps) {\n * return (\n * <LoginLayout\n * header={header}\n * footer={footer}\n * >\n * <CustomLoginContent />\n * </LoginLayout>\n * )\n * }\n *\n * // Use with AuthBoundary\n * <AuthBoundary\n * LoginComponent={CustomLogin}\n * header={<Logo />}\n * >\n * <ProtectedContent />\n * </AuthBoundary>\n * ```\n *\n * @alpha\n */\nexport function LoginLayout({\n children,\n footer = <LoginFooter />,\n header,\n}: LoginLayoutProps): React.ReactNode {\n return (\n <div style={{width: '100%', display: 'flex'}}>\n <Flex direction=\"column\" gap={4} style={{width: '320px', margin: 'auto', display: 'flex'}}>\n <Card border radius={2} paddingY={4}>\n <Flex direction=\"column\" gap={4}>\n {header && (\n <Card borderBottom paddingX={4} paddingBottom={3}>\n {header}\n </Card>\n )}\n\n {children && (\n <Flex paddingX={4} direction=\"column\" style={{minHeight: '154px'}}>\n {children}\n </Flex>\n )}\n </Flex>\n </Card>\n\n {footer}\n </Flex>\n </div>\n )\n}\n","import {Button, Flex, Heading, Spinner} from '@sanity/ui'\nimport {type JSX, Suspense} from 'react'\n\nimport {useLoginUrls} from '../../hooks/auth/useLoginUrls'\nimport {LoginLayout, type LoginLayoutProps} from './LoginLayout'\n\n/**\n * Login component that displays available authentication providers.\n * Renders a list of login options with a loading fallback while providers load.\n *\n * @alpha\n */\nexport function Login({header, footer}: LoginLayoutProps): JSX.Element {\n return (\n <LoginLayout header={header} footer={footer}>\n <Flex direction=\"column\" gap={4}>\n <Heading as=\"h1\" size={1} align=\"center\">\n Choose login provider\n </Heading>\n\n <Suspense\n fallback={\n <Flex align=\"center\" justify=\"center\" style={{height: '123px'}}>\n <Spinner />\n </Flex>\n }\n >\n <Providers />\n </Suspense>\n </Flex>\n </LoginLayout>\n )\n}\n\nfunction Providers() {\n const loginUrls = useLoginUrls()\n\n return (\n <Flex direction=\"column\" gap={3}>\n {loginUrls.map(({title, url}) => (\n <Button key={url} text={title} as=\"a\" href={url} mode=\"ghost\" />\n ))}\n </Flex>\n )\n}\n","import {Flex, Spinner, Text} from '@sanity/ui'\nimport {useEffect} from 'react'\n\nimport {useHandleCallback} from '../../hooks/auth/useHandleCallback'\nimport {LoginLayout, type LoginLayoutProps} from './LoginLayout'\n\n/**\n/**\n * Component shown during auth callback processing that handles login completion.\n * Automatically processes the auth callback when mounted and updates the URL\n * to remove callback parameters without triggering a page reload.\n *\n * @alpha\n */\nexport function LoginCallback({header, footer}: LoginLayoutProps): React.ReactNode {\n const handleCallback = useHandleCallback()\n\n useEffect(() => {\n const url = new URL(location.href)\n handleCallback(url.toString()).then((replacementLocation) => {\n if (replacementLocation) {\n // history API with `replaceState` is used to prevent a reload but still\n // remove the short-lived token from the URL\n history.replaceState(null, '', replacementLocation)\n }\n })\n }, [handleCallback])\n\n return (\n <LoginLayout header={header} footer={footer}>\n <Flex direction=\"column\" justify=\"center\" align=\"center\" gap={4} style={{margin: 'auto'}}>\n <Text size={1}>Logging you in…</Text>\n <Spinner size={4} />\n </Flex>\n </LoginLayout>\n )\n}\n","import {Button, Flex, Text} from '@sanity/ui'\nimport {useCallback} from 'react'\nimport {type FallbackProps} from 'react-error-boundary'\n\nimport {useLogOut} from '../../hooks/auth/useLogOut'\nimport {AuthError} from './AuthError'\nimport {LoginLayout, type LoginLayoutProps} from './LoginLayout'\n\n/**\n * @alpha\n */\nexport type LoginErrorProps = FallbackProps & LoginLayoutProps\n\n/**\n * Displays authentication error details and provides retry functionality.\n * Only handles {@link AuthError} instances - rethrows other error types.\n *\n * @alpha\n */\nexport function LoginError({\n error,\n resetErrorBoundary,\n header,\n footer,\n}: LoginErrorProps): React.ReactNode {\n if (!(error instanceof AuthError)) throw error\n const logout = useLogOut()\n\n const handleRetry = useCallback(async () => {\n await logout()\n resetErrorBoundary()\n }, [logout, resetErrorBoundary])\n\n return (\n <LoginLayout header={header} footer={footer}>\n <Flex direction=\"column\" gap={4} style={{margin: 'auto'}}>\n <Flex direction=\"column\" gap={3}>\n <Text as=\"h2\" align=\"center\" weight=\"bold\" size={3}>\n Authentication Error\n </Text>\n <Text size={1} align=\"center\">\n Please try again or contact support if the problem persists.\n </Text>\n </Flex>\n <Button text=\"Retry\" tone=\"primary\" onClick={handleRetry} />\n </Flex>\n </LoginLayout>\n )\n}\n","import {AuthStateType} from '@sanity/sdk'\nimport {useMemo} from 'react'\nimport {ErrorBoundary, type FallbackProps} from 'react-error-boundary'\n\nimport {useAuthState} from '../../hooks/auth/useAuthState'\nimport {AuthError} from './AuthError'\nimport {Login} from './Login'\nimport {LoginCallback} from './LoginCallback'\nimport {LoginError, type LoginErrorProps} from './LoginError'\nimport type {LoginLayoutProps} from './LoginLayout'\n\n/**\n * @alpha\n */\nexport interface AuthBoundaryProps extends LoginLayoutProps {\n /**\n * Custom component to render the login screen.\n * Receives all login layout props. Defaults to {@link Login}.\n */\n LoginComponent?: React.ComponentType<LoginLayoutProps>\n\n /**\n * Custom component to render during OAuth callback processing.\n * Receives all login layout props. Defaults to {@link LoginCallback}.\n */\n CallbackComponent?: React.ComponentType<LoginLayoutProps>\n\n /**\n * Custom component to render when authentication errors occur.\n * Receives login layout props and error boundary props. Defaults to\n * {@link LoginError}\n */\n LoginErrorComponent?: React.ComponentType<LoginErrorProps>\n}\n\n/**\n * A component that handles authentication flow and error boundaries for a\n * protected section of the application.\n *\n * @remarks\n * This component manages different authentication states and renders the\n * appropriate components based on that state.\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <AuthBoundary header={<MyLogo />}>\n * <ProtectedContent />\n * </AuthBoundary>\n * )\n * }\n * ```\n *\n * @alpha\n */\nexport function AuthBoundary({\n LoginErrorComponent = LoginError,\n ...props\n}: AuthBoundaryProps): React.ReactNode {\n const {header, footer} = props\n const FallbackComponent = useMemo(() => {\n return function LoginComponentWithLayoutProps(fallbackProps: FallbackProps) {\n return <LoginErrorComponent {...fallbackProps} header={header} footer={footer} />\n }\n }, [header, footer, LoginErrorComponent])\n\n return (\n <ErrorBoundary FallbackComponent={FallbackComponent}>\n <AuthSwitch {...props} />\n </ErrorBoundary>\n )\n}\n\ninterface AuthSwitchProps extends LoginLayoutProps {\n LoginComponent?: React.ComponentType<LoginLayoutProps>\n CallbackComponent?: React.ComponentType<LoginLayoutProps>\n}\n\nfunction AuthSwitch({\n LoginComponent = Login,\n CallbackComponent = LoginCallback,\n children,\n ...props\n}: AuthSwitchProps) {\n const authState = useAuthState()\n\n switch (authState.type) {\n case AuthStateType.ERROR: {\n throw new AuthError(authState.error)\n }\n case AuthStateType.LOGGING_IN: {\n return <CallbackComponent {...props} />\n }\n case AuthStateType.LOGGED_IN: {\n return children\n }\n default: {\n return <LoginComponent {...props} />\n }\n }\n}\n","import '../../css/styles.css'\n\nimport type {PropsWithChildren, ReactElement} from 'react'\n\n/**\n * @public\n */\nexport const DocumentGridLayout = (props: PropsWithChildren): ReactElement => {\n return (\n <>\n <style>{`\n .DocumentGridLayout {\n grid-template-columns: repeat(auto-fit, minmax(38ch, 1fr));\n }\n `}</style>\n <ol className=\"DocumentGridLayout list-none grid\">{props.children}</ol>\n </>\n )\n}\n\nDocumentGridLayout.displayName = 'DocumentGridLayout'\n","import '../../css/styles.css'\n\nimport type {PropsWithChildren, ReactElement} from 'react'\n\n/**\n * @public\n */\nexport const DocumentListLayout = (props: PropsWithChildren): ReactElement => {\n return <ol className=\"DocumentListLayout list-none\">{props.children}</ol>\n}\n\nDocumentListLayout.displayName = 'DocumentListLayout'\n","import 'inter-ui/inter.css'\nimport '../../css/styles.css'\n\nimport {DocumentIcon} from '@sanity/icons'\nimport {forwardRef, type JSX} from 'react'\n\n/**\n * @public\n */\nexport interface DocumentPreviewLayoutProps {\n docType?: string\n media?: {type: string; url: string} | null | undefined\n onClick?: () => void\n selected?: boolean\n status?: string\n subtitle?: string\n title: string\n}\n\n/**\n * This is a component that renders a document preview.\n *\n * @public\n *\n * @param props - The props for the DocumentPreviewLayout component.\n * @returns - The DocumentPreviewLayout component.\n */\nexport const DocumentPreviewLayout = forwardRef(\n (\n {\n docType,\n media,\n onClick,\n selected = false,\n status = '',\n subtitle = '',\n title,\n }: DocumentPreviewLayoutProps,\n ref: React.Ref<HTMLElement>,\n ): JSX.Element => {\n // @TODO: empty state\n if (!title) {\n return <></>\n }\n\n let PreviewMedia\n\n if (media?.url) {\n const baseUrl = new URL(media.url)\n baseUrl.searchParams.set('h', '66')\n baseUrl.searchParams.set('w', '66')\n baseUrl.searchParams.set('fit', 'crop')\n const mediaUrl = baseUrl.toString()\n // media url string params for sanity img\n PreviewMedia = <img src={mediaUrl} alt=\"\" />\n } else {\n PreviewMedia = <DocumentIcon />\n }\n\n return (\n <>\n <style>{`\n .DocumentPreviewLayout {\n --_hoverFocusBg: light-dark(var(--shade-11), var(--tint-1));\n --_selectedBg: light-dark(var(--blue-10), var(--blue-2));\n --_selectedFg: light-dark(var(--gray-1), var(--gray-10));\n --_titleFg: light-dark(var(--gray-1), var(--gray-10));\n --_subtitleFg: light-dark(var(--gray-4), var(--gray-7));\n --_docTypeFg: light-dark(var(--gray-1), var(--gray-10));\n --_docTypeBg: light-dark(var(--shade-10), var(--tint-1));\n --_publishedFg: light-dark(var(--gray-1), var(--gray-10));\n --_publishedBg: light-dark(var(--green-10), var(--green-2));\n --_draftFg: light-dark(var(--gray-1), var(--gray-10));\n --_draftBg: light-dark(var(--yellow-6), var(--yellow-2));\n\n appearance: none;\n\n &:has(:hover, focus) {\n background-color: var(--hoverFocusBg, var(--_hoverFocusBg));\n }\n\n &.selected {\n background-color: var(--selectedBg, var(--_selectedBg));\n color: var(--selectedFg, var(--_selectedFg));\n }\n\n .Title {\n color: var(--titleFg, var(--_titleFg));\n }\n\n &:not(.selected) .Subtitle {\n color: var(--subtitleFg, var(--_subtitleFg));\n }\n\n .Media {\n aspect-ratio: 1;\n inline-size: 33px;\n border-color: var(--gray-8);\n }\n\n .DocType {\n color: var(--docTypeFg, var(--_docTypeFg));\n background-color: var(--docTypeBg, var(--_docTypeBg));\n }\n\n .Published {\n color: var(--publishedFg, var(--_publishedFg));\n background-color: var(--publishedBg, var(--_publishedBg));\n }\n\n .Draft {\n color: var(--draftFg, var(--_draftFg));\n background-color: var(--draftBg, var(--_draftBg));\n }\n\n :is(.Published, .Draft) figcaption {\n @container (width < 52ch) {\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n height: 1px;\n overflow: hidden;\n position: absolute;\n white-space: nowrap;\n width: 1px;\n }\n }\n\n }\n `}</style>\n <button\n onClick={onClick}\n ref={ref as React.Ref<HTMLButtonElement>}\n className={`DocumentPreviewLayout block si-100 text-start p-1 radius1 ${selected ? 'selected' : ''}`}\n >\n <div className=\"container-inline flex align-items-center gap-2 font-sans\">\n <figure className=\"Media border0 border-solid flex-none flex align-items-center justify-content-center object-cover\">\n {PreviewMedia}\n </figure>\n\n <div className=\"leading2 flex-grow overflow-hidden\">\n <p className=\"Title text-1 font-medium truncate\">{title}</p>\n {subtitle && <p className=\"Subtitle text-1 truncate\">{subtitle}</p>}\n </div>\n\n {docType && (\n <figure className=\"DocType inline-block pb-5 pi-3 radius-pill text-2\">\n <figcaption className=\"inline\">{docType}</figcaption>\n </figure>\n )}\n\n {/* @TODO: finalize UI for this */}\n {status === 'published' && (\n <figure className=\"Published inline-block pb-5 pi-3 radius-pill text-2\">\n ✔︎ <figcaption className=\"inline\">published</figcaption>\n </figure>\n )}\n\n {/* @TODO: finalize UI for this */}\n {status === 'draft' && (\n <figure className=\"Draft inline-block pb-5 pi-3 radius-pill text-2\">\n ⛑︎ <figcaption className=\"inline\">draft</figcaption>\n </figure>\n )}\n </div>\n </button>\n </>\n )\n },\n)\n\nDocumentPreviewLayout.displayName = 'DocumentPreviewLayout'\n","import {Button, Card, Container, Flex, Heading, Stack} from '@sanity/ui'\nimport {type ReactElement} from 'react'\n\nimport {useAuthState} from '../../hooks/auth/useAuthState'\nimport {useHandleCallback} from '../../hooks/auth/useHandleCallback'\nimport {useLoginUrls} from '../../hooks/auth/useLoginUrls'\n\n/**\n * Component that handles Sanity authentication flow and renders login provider options\n *\n * @public\n *\n * @returns Rendered component\n *\n * @remarks\n * The component handles three states:\n * 1. Loading state during token exchange\n * 2. Success state after successful authentication\n * 3. Provider selection UI when not authenticated\n *\n * @example\n * ```tsx\n * const config = { projectId: 'your-project-id', dataset: 'production' }\n * return <LoginLinks sanityInstance={config} />\n * ```\n */\nexport const LoginLinks = (): ReactElement => {\n const loginUrls = useLoginUrls()\n const authState = useAuthState()\n useHandleCallback()\n\n if (authState.type === 'logging-in') {\n return <div>Logging in...</div>\n }\n\n // Show success state after authentication\n if (authState.type === 'logged-in') {\n return <div>You are logged in</div>\n }\n\n /**\n * Render provider selection UI\n * Uses Sanity UI components for consistent styling\n */\n return (\n <Card height=\"fill\" overflow=\"auto\" paddingX={4}>\n <Flex height=\"fill\" direction=\"column\" align=\"center\" justify=\"center\" paddingTop={4}>\n <Container width={0}>\n <Stack space={4}>\n <Heading align=\"center\" size={1}>\n Choose login provider\n </Heading>\n\n <Stack space={2}>\n {loginUrls.map((provider, index) => (\n <Button\n key={`${provider.url}_${index}`}\n as=\"a\"\n href={provider.url}\n mode=\"ghost\"\n tone=\"default\"\n space={3}\n padding={3}\n text={provider.title}\n />\n ))}\n </Stack>\n </Stack>\n </Container>\n </Flex>\n </Card>\n )\n}\n"],"names":["Fragment"],"mappings":"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"}