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

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 (112) hide show
  1. package/README.md +76 -34
  2. package/dist/_chunks-es/useLogOut.js +44 -0
  3. package/dist/_chunks-es/useLogOut.js.map +1 -0
  4. package/dist/assets/bundle-CcAyERuZ.css +11 -0
  5. package/dist/components.d.ts +259 -0
  6. package/dist/components.js +301 -0
  7. package/dist/components.js.map +1 -0
  8. package/dist/hooks.d.ts +186 -0
  9. package/dist/hooks.js +81 -0
  10. package/dist/hooks.js.map +1 -0
  11. package/dist/index.d.ts +2 -4742
  12. package/dist/index.js +2 -1054
  13. package/dist/index.js.map +1 -1
  14. package/package.json +43 -23
  15. package/src/_exports/components.ts +13 -0
  16. package/src/_exports/hooks.ts +9 -0
  17. package/src/_exports/index.ts +10 -66
  18. package/src/components/DocumentGridLayout/DocumentGridLayout.stories.tsx +113 -0
  19. package/src/components/DocumentGridLayout/DocumentGridLayout.test.tsx +42 -0
  20. package/src/components/DocumentGridLayout/DocumentGridLayout.tsx +21 -0
  21. package/src/components/DocumentListLayout/DocumentListLayout.stories.tsx +105 -0
  22. package/src/components/DocumentListLayout/DocumentListLayout.test.tsx +42 -0
  23. package/src/components/DocumentListLayout/DocumentListLayout.tsx +12 -0
  24. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.md +49 -0
  25. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.stories.tsx +39 -0
  26. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.test.tsx +30 -0
  27. package/src/components/DocumentPreviewLayout/DocumentPreviewLayout.tsx +171 -0
  28. package/src/components/Login/LoginLinks.test.tsx +12 -2
  29. package/src/components/Login/LoginLinks.tsx +29 -14
  30. package/src/components/auth/AuthBoundary.test.tsx +17 -4
  31. package/src/components/auth/AuthBoundary.tsx +4 -20
  32. package/src/components/auth/Login.test.tsx +16 -2
  33. package/src/components/auth/Login.tsx +16 -10
  34. package/src/components/auth/LoginCallback.test.tsx +17 -2
  35. package/src/components/auth/LoginCallback.tsx +5 -4
  36. package/src/components/auth/LoginError.test.tsx +17 -2
  37. package/src/components/auth/LoginError.tsx +11 -11
  38. package/src/components/auth/LoginFooter.test.tsx +16 -2
  39. package/src/components/auth/LoginFooter.tsx +23 -9
  40. package/src/components/auth/LoginLayout.test.tsx +16 -2
  41. package/src/components/auth/LoginLayout.tsx +19 -7
  42. package/src/{context → components/context}/SanityProvider.test.tsx +2 -2
  43. package/src/components/context/SanityProvider.tsx +42 -0
  44. package/src/css/css.config.js +220 -0
  45. package/src/css/paramour.css +2347 -0
  46. package/src/css/styles.css +11 -0
  47. package/src/hooks/auth/useAuthState.tsx +5 -4
  48. package/src/hooks/auth/useAuthToken.tsx +1 -1
  49. package/src/hooks/auth/useCurrentUser.tsx +4 -27
  50. package/src/hooks/auth/useHandleCallback.tsx +0 -1
  51. package/src/hooks/auth/useLogOut.tsx +1 -1
  52. package/src/hooks/auth/useLoginUrls.tsx +0 -1
  53. package/src/hooks/client/useClient.test.tsx +130 -0
  54. package/src/hooks/client/useClient.ts +30 -8
  55. package/src/hooks/context/useSanityInstance.test.tsx +2 -2
  56. package/src/hooks/context/useSanityInstance.ts +8 -24
  57. package/src/hooks/documentCollection/useDocuments.test.ts +130 -0
  58. package/src/hooks/documentCollection/useDocuments.ts +87 -0
  59. package/src/hooks/helpers/createCallbackHook.tsx +2 -3
  60. package/src/hooks/helpers/createStateSourceHook.test.tsx +0 -66
  61. package/src/hooks/helpers/createStateSourceHook.tsx +10 -29
  62. package/src/hooks/preview/usePreview.test.tsx +11 -20
  63. package/src/hooks/preview/usePreview.tsx +12 -66
  64. package/src/components/SDKProvider.test.tsx +0 -79
  65. package/src/components/SDKProvider.tsx +0 -42
  66. package/src/components/SanityApp.test.tsx +0 -156
  67. package/src/components/SanityApp.tsx +0 -90
  68. package/src/components/auth/authTestHelpers.tsx +0 -11
  69. package/src/components/utils.ts +0 -22
  70. package/src/context/SanityInstanceContext.ts +0 -4
  71. package/src/context/SanityProvider.tsx +0 -50
  72. package/src/hooks/_synchronous-groq-js.mjs +0 -4
  73. package/src/hooks/auth/useDashboardOrganizationId.test.tsx +0 -42
  74. package/src/hooks/auth/useDashboardOrganizationId.tsx +0 -29
  75. package/src/hooks/comlink/useFrameConnection.test.tsx +0 -167
  76. package/src/hooks/comlink/useFrameConnection.ts +0 -107
  77. package/src/hooks/comlink/useManageFavorite.test.ts +0 -106
  78. package/src/hooks/comlink/useManageFavorite.ts +0 -101
  79. package/src/hooks/comlink/useRecordDocumentHistoryEvent.test.ts +0 -77
  80. package/src/hooks/comlink/useRecordDocumentHistoryEvent.ts +0 -79
  81. package/src/hooks/comlink/useWindowConnection.test.ts +0 -135
  82. package/src/hooks/comlink/useWindowConnection.ts +0 -122
  83. package/src/hooks/dashboard/useNavigateToStudioDocument.ts +0 -97
  84. package/src/hooks/dashboard/useStudioWorkspacesByResourceId.test.tsx +0 -274
  85. package/src/hooks/dashboard/useStudioWorkspacesByResourceId.ts +0 -91
  86. package/src/hooks/datasets/useDatasets.ts +0 -37
  87. package/src/hooks/document/useApplyActions.test.ts +0 -25
  88. package/src/hooks/document/useApplyActions.ts +0 -74
  89. package/src/hooks/document/useDocument.test.ts +0 -81
  90. package/src/hooks/document/useDocument.ts +0 -107
  91. package/src/hooks/document/useDocumentEvent.test.ts +0 -63
  92. package/src/hooks/document/useDocumentEvent.ts +0 -54
  93. package/src/hooks/document/useDocumentSyncStatus.test.ts +0 -16
  94. package/src/hooks/document/useDocumentSyncStatus.ts +0 -30
  95. package/src/hooks/document/useEditDocument.test.ts +0 -179
  96. package/src/hooks/document/useEditDocument.ts +0 -195
  97. package/src/hooks/document/usePermissions.ts +0 -82
  98. package/src/hooks/infiniteList/useInfiniteList.test.tsx +0 -152
  99. package/src/hooks/infiniteList/useInfiniteList.ts +0 -174
  100. package/src/hooks/paginatedList/usePaginatedList.test.tsx +0 -259
  101. package/src/hooks/paginatedList/usePaginatedList.ts +0 -290
  102. package/src/hooks/projection/useProjection.test.tsx +0 -218
  103. package/src/hooks/projection/useProjection.ts +0 -147
  104. package/src/hooks/projects/useProject.ts +0 -45
  105. package/src/hooks/projects/useProjects.ts +0 -41
  106. package/src/hooks/query/useQuery.test.tsx +0 -188
  107. package/src/hooks/query/useQuery.ts +0 -103
  108. package/src/hooks/users/useUsers.test.ts +0 -163
  109. package/src/hooks/users/useUsers.ts +0 -107
  110. package/src/utils/getEnv.ts +0 -21
  111. package/src/version.ts +0 -8
  112. package/src/vite-env.d.ts +0 -10
@@ -1,3 +1,4 @@
1
+ import {Button, Card, Container, Flex, Heading, Stack} from '@sanity/ui'
1
2
  import {type ReactElement} from 'react'
2
3
 
3
4
  import {useAuthState} from '../../hooks/auth/useAuthState'
@@ -29,30 +30,44 @@ export const LoginLinks = (): ReactElement => {
29
30
  useHandleCallback()
30
31
 
31
32
  if (authState.type === 'logging-in') {
32
- return <div className="sc-login-links__logging-in">Logging in...</div>
33
+ return <div>Logging in...</div>
33
34
  }
34
35
 
35
36
  // Show success state after authentication
36
37
  if (authState.type === 'logged-in') {
37
- return <div className="sc-login-links__logged-in">You are logged in</div>
38
+ return <div>You are logged in</div>
38
39
  }
39
40
 
40
41
  /**
41
42
  * Render provider selection UI
43
+ * Uses Sanity UI components for consistent styling
42
44
  */
43
45
  return (
44
- <div className="sc-login-links">
45
- <h2 className="sc-login-links__title">Choose login provider</h2>
46
+ <Card height="fill" overflow="auto" paddingX={4}>
47
+ <Flex height="fill" direction="column" align="center" justify="center" paddingTop={4}>
48
+ <Container width={0}>
49
+ <Stack space={4}>
50
+ <Heading align="center" size={1}>
51
+ Choose login provider
52
+ </Heading>
46
53
 
47
- <ul className="sc-login-links__list">
48
- {loginUrls.map((provider, index) => (
49
- <li key={`${provider.url}_${index}`} className="sc-login-links__item">
50
- <a href={provider.url} className="sc-login-links__link">
51
- {provider.title}
52
- </a>
53
- </li>
54
- ))}
55
- </ul>
56
- </div>
54
+ <Stack space={2}>
55
+ {loginUrls.map((provider, index) => (
56
+ <Button
57
+ key={`${provider.url}_${index}`}
58
+ as="a"
59
+ href={provider.url}
60
+ mode="ghost"
61
+ tone="default"
62
+ space={3}
63
+ padding={3}
64
+ text={provider.title}
65
+ />
66
+ ))}
67
+ </Stack>
68
+ </Stack>
69
+ </Container>
70
+ </Flex>
71
+ </Card>
57
72
  )
58
73
  }
@@ -1,10 +1,13 @@
1
- import {AuthStateType} from '@sanity/sdk'
2
- import {useAuthState} from '@sanity/sdk-react'
3
- import {screen, waitFor} from '@testing-library/react'
1
+ import {AuthStateType, createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {render, screen, waitFor} from '@testing-library/react'
5
+ import React from 'react'
4
6
  import {beforeEach, describe, expect, it, type MockInstance, vi} from 'vitest'
5
7
 
8
+ import {useAuthState} from '../../hooks/auth/useAuthState'
9
+ import {SanityProvider} from '../context/SanityProvider'
6
10
  import {AuthBoundary} from './AuthBoundary'
7
- import {renderWithWrappers} from './authTestHelpers'
8
11
 
9
12
  // Mock hooks
10
13
  vi.mock('../../hooks/auth/useAuthState', () => ({
@@ -35,6 +38,16 @@ vi.mock('./AuthError', async (importOriginal) => {
35
38
  }
36
39
  })
37
40
 
41
+ const theme = buildTheme({})
42
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
43
+ const renderWithWrappers = (ui: React.ReactElement) => {
44
+ return render(
45
+ <ThemeProvider theme={theme}>
46
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
47
+ </ThemeProvider>,
48
+ )
49
+ }
50
+
38
51
  describe('AuthBoundary', () => {
39
52
  let consoleErrorSpy: MockInstance
40
53
  beforeEach(() => {
@@ -3,32 +3,16 @@ import {useMemo} from 'react'
3
3
  import {ErrorBoundary, type FallbackProps} from 'react-error-boundary'
4
4
 
5
5
  import {useAuthState} from '../../hooks/auth/useAuthState'
6
- import {isInIframe} from '../utils'
7
6
  import {AuthError} from './AuthError'
8
7
  import {Login} from './Login'
9
8
  import {LoginCallback} from './LoginCallback'
10
9
  import {LoginError, type LoginErrorProps} from './LoginError'
11
- import {type LoginLayoutProps} from './LoginLayout'
12
-
13
- // Only import bridge if we're in an iframe. This assumes that the app is
14
- // running within SanityOS if it is in an iframe.
15
- if (isInIframe()) {
16
- const parsedUrl = new URL(window.location.href)
17
- const mode = new URLSearchParams(parsedUrl.hash.slice(1)).get('mode')
18
- const script = document.createElement('script')
19
- script.src =
20
- mode === 'core-ui--staging'
21
- ? 'https://core.sanity-cdn.work/bridge.js'
22
- : 'https://core.sanity-cdn.com/bridge.js'
23
- script.type = 'module'
24
- script.async = true
25
- document.head.appendChild(script)
26
- }
10
+ import type {LoginLayoutProps} from './LoginLayout'
27
11
 
28
12
  /**
29
- * @internal
13
+ * @alpha
30
14
  */
31
- interface AuthBoundaryProps extends LoginLayoutProps {
15
+ export interface AuthBoundaryProps extends LoginLayoutProps {
32
16
  /**
33
17
  * Custom component to render the login screen.
34
18
  * Receives all login layout props. Defaults to {@link Login}.
@@ -68,7 +52,7 @@ interface AuthBoundaryProps extends LoginLayoutProps {
68
52
  * }
69
53
  * ```
70
54
  *
71
- * @internal
55
+ * @alpha
72
56
  */
73
57
  export function AuthBoundary({
74
58
  LoginErrorComponent = LoginError,
@@ -1,7 +1,11 @@
1
- import {screen} from '@testing-library/react'
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {render, screen} from '@testing-library/react'
5
+ import React from 'react'
2
6
  import {describe, expect, it, vi} from 'vitest'
3
7
 
4
- import {renderWithWrappers} from './authTestHelpers'
8
+ import {SanityProvider} from '../context/SanityProvider'
5
9
  import {Login} from './Login'
6
10
 
7
11
  vi.mock('../../hooks/auth/useLoginUrls', () => ({
@@ -11,6 +15,16 @@ vi.mock('../../hooks/auth/useLoginUrls', () => ({
11
15
  ]),
12
16
  }))
13
17
 
18
+ const theme = buildTheme({})
19
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
20
+ const renderWithWrappers = (ui: React.ReactElement) => {
21
+ return render(
22
+ <ThemeProvider theme={theme}>
23
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
24
+ </ThemeProvider>,
25
+ )
26
+ }
27
+
14
28
  describe('Login', () => {
15
29
  it('renders login providers', () => {
16
30
  renderWithWrappers(<Login />)
@@ -1,3 +1,4 @@
1
+ import {Button, Flex, Heading, Spinner} from '@sanity/ui'
1
2
  import {type JSX, Suspense} from 'react'
2
3
 
3
4
  import {useLoginUrls} from '../../hooks/auth/useLoginUrls'
@@ -8,18 +9,25 @@ import {LoginLayout, type LoginLayoutProps} from './LoginLayout'
8
9
  * Renders a list of login options with a loading fallback while providers load.
9
10
  *
10
11
  * @alpha
11
- * @internal
12
12
  */
13
13
  export function Login({header, footer}: LoginLayoutProps): JSX.Element {
14
14
  return (
15
15
  <LoginLayout header={header} footer={footer}>
16
- <div className="sc-login">
17
- <h1 className="sc-login__title">Choose login provider</h1>
16
+ <Flex direction="column" gap={4}>
17
+ <Heading as="h1" size={1} align="center">
18
+ Choose login provider
19
+ </Heading>
18
20
 
19
- <Suspense fallback={<div className="sc-login__loading">Loading…</div>}>
21
+ <Suspense
22
+ fallback={
23
+ <Flex align="center" justify="center" style={{height: '123px'}}>
24
+ <Spinner />
25
+ </Flex>
26
+ }
27
+ >
20
28
  <Providers />
21
29
  </Suspense>
22
- </div>
30
+ </Flex>
23
31
  </LoginLayout>
24
32
  )
25
33
  }
@@ -28,12 +36,10 @@ function Providers() {
28
36
  const loginUrls = useLoginUrls()
29
37
 
30
38
  return (
31
- <div className="sc-login-providers">
39
+ <Flex direction="column" gap={3}>
32
40
  {loginUrls.map(({title, url}) => (
33
- <a key={url} href={url}>
34
- {title}
35
- </a>
41
+ <Button key={url} text={title} as="a" href={url} mode="ghost" />
36
42
  ))}
37
- </div>
43
+ </Flex>
38
44
  )
39
45
  }
@@ -1,7 +1,22 @@
1
- import {screen, waitFor} from '@testing-library/react'
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {render, screen, waitFor} from '@testing-library/react'
5
+ import React from 'react'
2
6
  import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest'
3
7
 
4
- import {renderWithWrappers} from './authTestHelpers'
8
+ import {SanityProvider} from '../context/SanityProvider'
9
+
10
+ const theme = buildTheme({})
11
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
12
+
13
+ const renderWithWrappers = (ui: React.ReactElement) => {
14
+ return render(
15
+ <ThemeProvider theme={theme}>
16
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
17
+ </ThemeProvider>,
18
+ )
19
+ }
5
20
 
6
21
  // Mock `useHandleCallback`
7
22
  vi.mock('../../hooks/auth/useHandleCallback', () => ({
@@ -1,3 +1,4 @@
1
+ import {Flex, Spinner, Text} from '@sanity/ui'
1
2
  import {useEffect} from 'react'
2
3
 
3
4
  import {useHandleCallback} from '../../hooks/auth/useHandleCallback'
@@ -27,10 +28,10 @@ export function LoginCallback({header, footer}: LoginLayoutProps): React.ReactNo
27
28
 
28
29
  return (
29
30
  <LoginLayout header={header} footer={footer}>
30
- <div className="sc-login-callback">
31
- <h1 className="sc-login-callback__title">Logging you in…</h1>
32
- <div className="sc-login-callback__loading">Loading…</div>
33
- </div>
31
+ <Flex direction="column" justify="center" align="center" gap={4} style={{margin: 'auto'}}>
32
+ <Text size={1}>Logging you in…</Text>
33
+ <Spinner size={4} />
34
+ </Flex>
34
35
  </LoginLayout>
35
36
  )
36
37
  }
@@ -1,14 +1,29 @@
1
- import {fireEvent, screen, waitFor} from '@testing-library/react'
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {fireEvent, render, screen, waitFor} from '@testing-library/react'
5
+ import React from 'react'
2
6
  import {describe, expect, it, vi} from 'vitest'
3
7
 
8
+ import {SanityProvider} from '../context/SanityProvider'
4
9
  import {AuthError} from './AuthError'
5
- import {renderWithWrappers} from './authTestHelpers'
6
10
  import {LoginError} from './LoginError'
7
11
 
8
12
  vi.mock('../../hooks/auth/useLogOut', () => ({
9
13
  useLogOut: vi.fn(() => async () => {}),
10
14
  }))
11
15
 
16
+ const theme = buildTheme({})
17
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
18
+
19
+ const renderWithWrappers = (ui: React.ReactElement) => {
20
+ return render(
21
+ <ThemeProvider theme={theme}>
22
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
23
+ </ThemeProvider>,
24
+ )
25
+ }
26
+
12
27
  describe('LoginError', () => {
13
28
  it('shows authentication error and retry button', async () => {
14
29
  const mockReset = vi.fn()
@@ -1,3 +1,4 @@
1
+ import {Button, Flex, Text} from '@sanity/ui'
1
2
  import {useCallback} from 'react'
2
3
  import {type FallbackProps} from 'react-error-boundary'
3
4
 
@@ -32,18 +33,17 @@ export function LoginError({
32
33
 
33
34
  return (
34
35
  <LoginLayout header={header} footer={footer}>
35
- <div className="sc-login-error">
36
- <div className="sc-login-error__content">
37
- <h2 className="sc-login-error__title">Authentication Error</h2>
38
- <p className="sc-login-error__description">
36
+ <Flex direction="column" gap={4} style={{margin: 'auto'}}>
37
+ <Flex direction="column" gap={3}>
38
+ <Text as="h2" align="center" weight="bold" size={3}>
39
+ Authentication Error
40
+ </Text>
41
+ <Text size={1} align="center">
39
42
  Please try again or contact support if the problem persists.
40
- </p>
41
- </div>
42
-
43
- <button className="sc-login-error__button" onClick={handleRetry}>
44
- Retry
45
- </button>
46
- </div>
43
+ </Text>
44
+ </Flex>
45
+ <Button text="Retry" tone="primary" onClick={handleRetry} />
46
+ </Flex>
47
47
  </LoginLayout>
48
48
  )
49
49
  }
@@ -1,9 +1,23 @@
1
- import {screen} from '@testing-library/react'
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {render, screen} from '@testing-library/react'
5
+ import React from 'react'
2
6
  import {describe, expect, it} from 'vitest'
3
7
 
4
- import {renderWithWrappers} from './authTestHelpers'
8
+ import {SanityProvider} from '../context/SanityProvider'
5
9
  import {LoginFooter} from './LoginFooter'
6
10
 
11
+ const theme = buildTheme({})
12
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
13
+ const renderWithWrappers = (ui: React.ReactElement) => {
14
+ return render(
15
+ <ThemeProvider theme={theme}>
16
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
17
+ </ThemeProvider>,
18
+ )
19
+ }
20
+
7
21
  describe('LoginFooter', () => {
8
22
  it('renders footer links', () => {
9
23
  renderWithWrappers(<LoginFooter />)
@@ -1,4 +1,5 @@
1
1
  import {SanityLogo} from '@sanity/logos'
2
+ import {Flex, Text} from '@sanity/ui'
2
3
  import {Fragment} from 'react'
3
4
 
4
5
  const LINKS = [
@@ -32,20 +33,33 @@ const LINKS = [
32
33
  */
33
34
  export function LoginFooter(): React.ReactNode {
34
35
  return (
35
- <div className="sc-login-footer">
36
- <SanityLogo className="sc-login-footer__logo" />
36
+ <Flex direction="column" gap={4} justify="center" align="center" paddingTop={2}>
37
+ <Text size={3}>
38
+ <SanityLogo />
39
+ </Text>
37
40
 
38
- <ul className="sc-login-footer__links">
39
- {LINKS.map((link) => (
41
+ <Flex align="center" gap={2}>
42
+ {LINKS.map((link, index) => (
40
43
  <Fragment key={link.title}>
41
- <li className="sc-login-footer__link">
42
- <a href={link.url} target="_blank" rel="noopener noreferrer">
44
+ <Text muted size={1}>
45
+ <a
46
+ href={link.url}
47
+ target="_blank"
48
+ rel="noopener noreferrer"
49
+ style={{color: 'inherit'}}
50
+ >
43
51
  {link.title}
44
52
  </a>
45
- </li>
53
+ </Text>
54
+
55
+ {index < LINKS.length - 1 && (
56
+ <Text size={1} muted>
57
+
58
+ </Text>
59
+ )}
46
60
  </Fragment>
47
61
  ))}
48
- </ul>
49
- </div>
62
+ </Flex>
63
+ </Flex>
50
64
  )
51
65
  }
@@ -1,9 +1,23 @@
1
- import {screen} from '@testing-library/react'
1
+ import {createSanityInstance} from '@sanity/sdk'
2
+ import {ThemeProvider} from '@sanity/ui'
3
+ import {buildTheme} from '@sanity/ui/theme'
4
+ import {render, screen} from '@testing-library/react'
5
+ import React from 'react'
2
6
  import {describe, expect, it} from 'vitest'
3
7
 
4
- import {renderWithWrappers} from './authTestHelpers'
8
+ import {SanityProvider} from '../context/SanityProvider'
5
9
  import {LoginLayout} from './LoginLayout'
6
10
 
11
+ const theme = buildTheme({})
12
+ const sanityInstance = createSanityInstance({projectId: 'test-project-id', dataset: 'production'})
13
+ const renderWithWrappers = (ui: React.ReactElement) => {
14
+ return render(
15
+ <ThemeProvider theme={theme}>
16
+ <SanityProvider sanityInstance={sanityInstance}>{ui}</SanityProvider>
17
+ </ThemeProvider>,
18
+ )
19
+ }
20
+
7
21
  describe('LoginLayout', () => {
8
22
  it('renders header, children, and footer', () => {
9
23
  renderWithWrappers(
@@ -1,3 +1,5 @@
1
+ import {Card, Flex} from '@sanity/ui'
2
+
1
3
  import {LoginFooter} from './LoginFooter'
2
4
 
3
5
  /**
@@ -54,16 +56,26 @@ export function LoginLayout({
54
56
  header,
55
57
  }: LoginLayoutProps): React.ReactNode {
56
58
  return (
57
- <div className="sc-login-layout">
58
- <div className="sc-login-layout__container">
59
- <div className="sc-login-layout__card">
60
- {header && <div className="sc-login-layout__card-header">{header}</div>}
59
+ <div style={{width: '100%', display: 'flex'}}>
60
+ <Flex direction="column" gap={4} style={{width: '320px', margin: 'auto', display: 'flex'}}>
61
+ <Card border radius={2} paddingY={4}>
62
+ <Flex direction="column" gap={4}>
63
+ {header && (
64
+ <Card borderBottom paddingX={4} paddingBottom={3}>
65
+ {header}
66
+ </Card>
67
+ )}
61
68
 
62
- {children && <div className="sc-login-layout__card-body">{children}</div>}
63
- </div>
69
+ {children && (
70
+ <Flex paddingX={4} direction="column" style={{minHeight: '154px'}}>
71
+ {children}
72
+ </Flex>
73
+ )}
74
+ </Flex>
75
+ </Card>
64
76
 
65
77
  {footer}
66
- </div>
78
+ </Flex>
67
79
  </div>
68
80
  )
69
81
  }
@@ -2,7 +2,7 @@ import {createSanityInstance} from '@sanity/sdk'
2
2
  import {render} from '@testing-library/react'
3
3
  import {describe, expect, it} from 'vitest'
4
4
 
5
- import {useSanityInstance} from '../hooks/context/useSanityInstance'
5
+ import {useSanityInstance} from '../../hooks/context/useSanityInstance'
6
6
  import {SanityProvider} from './SanityProvider'
7
7
 
8
8
  describe('SanityProvider', () => {
@@ -15,7 +15,7 @@ describe('SanityProvider', () => {
15
15
  }
16
16
 
17
17
  const {getByTestId} = render(
18
- <SanityProvider sanityInstances={[sanityInstance]}>
18
+ <SanityProvider sanityInstance={sanityInstance}>
19
19
  <TestComponent />
20
20
  </SanityProvider>,
21
21
  )
@@ -0,0 +1,42 @@
1
+ import {type SanityInstance} from '@sanity/sdk'
2
+ import {createContext, type ReactElement} from 'react'
3
+
4
+ /**
5
+ * @public
6
+ */
7
+ export interface SanityProviderProps {
8
+ children: React.ReactNode
9
+ sanityInstance: SanityInstance
10
+ }
11
+
12
+ export const SanityInstanceContext = createContext<SanityInstance | null>(null)
13
+
14
+ /**
15
+ * Top-level context provider that provides a Sanity configuration instance.
16
+ * This must wrap any Sanity SDK React component.
17
+ * @public
18
+ * @param props - Sanity project and dataset configuration
19
+ * @returns Rendered component
20
+ * @example
21
+ * ```tsx
22
+ * import {createSanityInstance} from '@sanity/sdk'
23
+ * import {ExampleComponent, SanityProvider} from '@sanity/sdk-react'
24
+ *
25
+ * const sanityInstance = createSanityInstance({projectId: 'your-project-id', dataset: 'production'})
26
+ *
27
+ * export default function MyApp() {
28
+ * return (
29
+ * <SanityProvider sanityInstance={sanityInstance}>
30
+ * <ExampleComponent />
31
+ * </SanityProvider>
32
+ * )
33
+ * }
34
+ * ```
35
+ */
36
+ export const SanityProvider = ({children, sanityInstance}: SanityProviderProps): ReactElement => {
37
+ return (
38
+ <SanityInstanceContext.Provider value={sanityInstance}>
39
+ {children}
40
+ </SanityInstanceContext.Provider>
41
+ )
42
+ }