@sanity/sdk-react 0.0.0-alpha.2 → 0.0.0-alpha.21

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