@shipfox/client-integrations 17.0.0 → 22.0.0

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 (106) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +39 -0
  3. package/dist/components/callback-status-shell.d.ts.map +1 -1
  4. package/dist/components/callback-status-shell.js +4 -3
  5. package/dist/components/callback-status-shell.js.map +1 -1
  6. package/dist/components/connection-picker.js +2 -2
  7. package/dist/components/connection-picker.js.map +1 -1
  8. package/dist/components/installed-integrations-section.d.ts.map +1 -1
  9. package/dist/components/installed-integrations-section.js +155 -141
  10. package/dist/components/installed-integrations-section.js.map +1 -1
  11. package/dist/components/integration-gallery.stories.d.ts.map +1 -1
  12. package/dist/components/integration-gallery.stories.js +8 -3
  13. package/dist/components/integration-gallery.stories.js.map +1 -1
  14. package/dist/components/provider-grid.d.ts +0 -2
  15. package/dist/components/provider-grid.d.ts.map +1 -1
  16. package/dist/components/provider-grid.js +88 -104
  17. package/dist/components/provider-grid.js.map +1 -1
  18. package/dist/components/redirect-install-page.d.ts.map +1 -1
  19. package/dist/components/redirect-install-page.js +3 -2
  20. package/dist/components/redirect-install-page.js.map +1 -1
  21. package/dist/components/repository-picker.d.ts +1 -4
  22. package/dist/components/repository-picker.d.ts.map +1 -1
  23. package/dist/components/repository-picker.js +24 -37
  24. package/dist/components/repository-picker.js.map +1 -1
  25. package/dist/components/webhook/webhook-modals.stories.js +1 -1
  26. package/dist/components/webhook/webhook-modals.stories.js.map +1 -1
  27. package/dist/pages/gitea-install-page.js +1 -1
  28. package/dist/pages/gitea-install-page.js.map +1 -1
  29. package/dist/pages/jira-callback-page.js +6 -6
  30. package/dist/pages/jira-callback-page.js.map +1 -1
  31. package/dist/pages/sentry-callback-page.js +6 -6
  32. package/dist/pages/sentry-callback-page.js.map +1 -1
  33. package/dist/pages/source-control-onboarding-page.js +1 -1
  34. package/dist/pages/source-control-onboarding-page.js.map +1 -1
  35. package/dist/routes/gitea.d.ts +3 -0
  36. package/dist/routes/gitea.js +3 -0
  37. package/dist/routes/gitea.js.map +1 -1
  38. package/dist/routes/github-callback.d.ts +3 -0
  39. package/dist/routes/github-callback.d.ts.map +1 -1
  40. package/dist/routes/github-callback.js +3 -0
  41. package/dist/routes/github-callback.js.map +1 -1
  42. package/dist/routes/github.d.ts +3 -0
  43. package/dist/routes/github.js +3 -0
  44. package/dist/routes/github.js.map +1 -1
  45. package/dist/routes/integrations-settings.d.ts +3 -0
  46. package/dist/routes/integrations-settings.js +3 -0
  47. package/dist/routes/integrations-settings.js.map +1 -1
  48. package/dist/routes/integrations.d.ts +3 -0
  49. package/dist/routes/integrations.js +3 -0
  50. package/dist/routes/integrations.js.map +1 -1
  51. package/dist/routes/jira-callback.d.ts +3 -0
  52. package/dist/routes/jira-callback.js +3 -0
  53. package/dist/routes/jira-callback.js.map +1 -1
  54. package/dist/routes/jira.d.ts +3 -0
  55. package/dist/routes/jira.js +3 -0
  56. package/dist/routes/jira.js.map +1 -1
  57. package/dist/routes/linear-callback.d.ts +3 -0
  58. package/dist/routes/linear-callback.js +3 -0
  59. package/dist/routes/linear-callback.js.map +1 -1
  60. package/dist/routes/linear.d.ts +3 -0
  61. package/dist/routes/linear.js +3 -0
  62. package/dist/routes/linear.js.map +1 -1
  63. package/dist/routes/sentry-callback.d.ts +3 -0
  64. package/dist/routes/sentry-callback.js +3 -0
  65. package/dist/routes/sentry-callback.js.map +1 -1
  66. package/dist/routes/sentry.d.ts +3 -0
  67. package/dist/routes/sentry.js +3 -0
  68. package/dist/routes/sentry.js.map +1 -1
  69. package/dist/routes/slack-callback.d.ts +3 -0
  70. package/dist/routes/slack-callback.js +3 -0
  71. package/dist/routes/slack-callback.js.map +1 -1
  72. package/dist/routes/slack.d.ts +3 -0
  73. package/dist/routes/slack.js +3 -0
  74. package/dist/routes/slack.js.map +1 -1
  75. package/dist/tsconfig.test.tsbuildinfo +1 -1
  76. package/package.json +8 -8
  77. package/src/components/callback-status-shell.tsx +4 -3
  78. package/src/components/connection-picker.tsx +2 -2
  79. package/src/components/installed-integrations-section.tsx +110 -98
  80. package/src/components/integration-gallery.stories.tsx +8 -3
  81. package/src/components/integration-gallery.test.tsx +3 -1
  82. package/src/components/provider-grid.tsx +69 -79
  83. package/src/components/redirect-install-page.test.tsx +4 -0
  84. package/src/components/redirect-install-page.tsx +3 -2
  85. package/src/components/repository-picker.test.tsx +27 -13
  86. package/src/components/repository-picker.tsx +22 -47
  87. package/src/components/webhook/webhook-modals.stories.tsx +1 -1
  88. package/src/pages/gitea-install-page.tsx +1 -1
  89. package/src/pages/jira-callback-page.tsx +7 -7
  90. package/src/pages/sentry-callback-page.tsx +6 -8
  91. package/src/pages/slack-callback-page.test.tsx +7 -0
  92. package/src/pages/source-control-onboarding-page.tsx +1 -1
  93. package/src/routes/gitea.tsx +4 -1
  94. package/src/routes/github-callback.tsx +1 -0
  95. package/src/routes/github.tsx +4 -1
  96. package/src/routes/integrations-settings.tsx +4 -1
  97. package/src/routes/integrations.tsx +4 -1
  98. package/src/routes/jira-callback.tsx +1 -0
  99. package/src/routes/jira.tsx +4 -1
  100. package/src/routes/linear-callback.tsx +1 -0
  101. package/src/routes/linear.tsx +4 -1
  102. package/src/routes/sentry-callback.tsx +1 -0
  103. package/src/routes/sentry.tsx +4 -1
  104. package/src/routes/slack-callback.tsx +1 -0
  105. package/src/routes/slack.tsx +4 -1
  106. package/tsconfig.build.tsbuildinfo +1 -1
@@ -17,6 +17,19 @@ afterEach(() => {
17
17
  });
18
18
 
19
19
  describe('RepositoryPicker', () => {
20
+ test('renders the default empty message without an internal search control', () => {
21
+ renderPicker();
22
+
23
+ expect(screen.getByText('No repositories found.')).toBeInTheDocument();
24
+ expect(screen.queryByRole('searchbox')).not.toBeInTheDocument();
25
+ });
26
+
27
+ test('renders a custom empty message', () => {
28
+ renderPicker({emptyMessage: 'No repositories visible to this connection.'});
29
+
30
+ expect(screen.getByText('No repositories visible to this connection.')).toBeInTheDocument();
31
+ });
32
+
20
33
  test('renders repository names without owner or default branch metadata', () => {
21
34
  renderPicker({
22
35
  repositories: [
@@ -65,27 +78,28 @@ describe('RepositoryPicker', () => {
65
78
  const {container} = renderPicker({
66
79
  repositories: [],
67
80
  isLoading: true,
68
- searchValue: '',
69
- onSearchChange: () => undefined,
70
81
  });
71
82
 
72
83
  expect(screen.getByRole('status')).toHaveTextContent('Loading repositories.');
73
- expect(screen.getByRole('searchbox')).toBeInTheDocument();
84
+ expect(screen.queryByRole('searchbox')).not.toBeInTheDocument();
74
85
 
75
86
  const loadingGrid = container.querySelector('[aria-hidden="true"]');
76
87
  if (!loadingGrid) throw new Error('Repository loading grid was not rendered');
77
88
 
78
- expect(loadingGrid).toHaveClass('grid', 'grid-cols-2', 'gap-inline', 'max-[760px]:grid-cols-1');
89
+ // The placeholders sit in the same hairline cell grid as the loaded cards,
90
+ // so the list does not change shape when the fetch resolves.
91
+ expect(loadingGrid).toHaveClass('grid', 'grid-cols-2', 'max-[760px]:grid-cols-1');
92
+ expect(loadingGrid).toHaveClass('min-[760px]:[&>*:nth-child(2n_of_:not(input))]:border-l');
93
+ expect(loadingGrid).not.toHaveClass('gap-inline');
79
94
  expect(loadingGrid.querySelectorAll('[data-slot="skeleton"]')).toHaveLength(4);
80
- for (const placeholder of loadingGrid.querySelectorAll(':scope > div')) {
81
- expect(placeholder).toHaveClass(
82
- 'h-50',
83
- 'rounded-8',
84
- 'border',
85
- 'border-border-neutral-base',
86
- 'bg-background-neutral-base',
87
- 'p-[14px]',
88
- );
95
+ // The placeholder box belongs to `RadioGroupItemSkeleton`, so this only
96
+ // checks that each slot carries the indicator and one bar. react-ui owns
97
+ // keeping that surface identical to a real item.
98
+ const placeholders = loadingGrid.querySelectorAll(':scope > div');
99
+ expect(placeholders).toHaveLength(4);
100
+ for (const placeholder of placeholders) {
101
+ expect(placeholder.querySelector('[data-slot="radio-indicator"]')).not.toBeNull();
102
+ expect(placeholder.querySelector('[data-slot="skeleton"]')).not.toBeNull();
89
103
  }
90
104
  });
91
105
  });
@@ -1,15 +1,13 @@
1
1
  import {Button} from '@shipfox/react-ui/button';
2
2
  import {useIsTextTruncated} from '@shipfox/react-ui/hooks';
3
- import {Input} from '@shipfox/react-ui/input';
4
3
  import {Label} from '@shipfox/react-ui/label';
5
- import {RadioGroup, RadioGroupItem} from '@shipfox/react-ui/radio-group';
6
- import {Skeleton} from '@shipfox/react-ui/skeleton';
4
+ import {PanelGrid} from '@shipfox/react-ui/panel';
5
+ import {RadioGroup, RadioGroupItem, RadioGroupItemSkeleton} from '@shipfox/react-ui/radio-group';
7
6
  import {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';
8
7
  import {Text} from '@shipfox/react-ui/typography';
9
8
  import {useId} from 'react';
10
9
  import type {Repository} from '#core/models.js';
11
10
 
12
- const REPOSITORY_GRID_CLASS_NAME = 'grid grid-cols-2 gap-inline max-[760px]:grid-cols-1';
13
11
  const REPOSITORY_SKELETON_WIDTHS = ['w-64', 'w-96', 'w-80', 'w-112'] as const;
14
12
 
15
13
  export function RepositoryPicker({
@@ -21,9 +19,6 @@ export function RepositoryPicker({
21
19
  hasNextPage,
22
20
  onLoadMore,
23
21
  emptyMessage = 'No repositories found.',
24
- searchValue,
25
- onSearchChange,
26
- searchDisabled,
27
22
  }: {
28
23
  repositories: Repository[];
29
24
  selectedRepositoryId: string | undefined;
@@ -33,44 +28,29 @@ export function RepositoryPicker({
33
28
  hasNextPage?: boolean;
34
29
  onLoadMore?: () => void;
35
30
  emptyMessage?: string;
36
- searchValue?: string;
37
- onSearchChange?: (value: string) => void;
38
- searchDisabled?: boolean;
39
31
  }) {
40
32
  const labelId = useId();
41
- const showSearch = onSearchChange !== undefined;
42
33
 
43
34
  return (
44
- <div className="flex flex-col gap-inline">
35
+ <div className="flex min-w-0 flex-col">
45
36
  <Label id={labelId} className="sr-only">
46
37
  Repository
47
38
  </Label>
48
39
 
49
- {showSearch ? (
50
- <Input
51
- type="search"
52
- placeholder="Search repositories…"
53
- aria-label="Search repositories"
54
- value={searchValue ?? ''}
55
- onChange={(event) => onSearchChange?.(event.target.value)}
56
- disabled={searchDisabled}
57
- />
58
- ) : null}
59
-
60
40
  {isLoading ? <RepositoryLoadingState /> : null}
61
41
 
62
42
  {!isLoading && repositories.length === 0 ? (
63
- <div className="rounded-8 border border-border-neutral-base bg-background-subtle-base p-panel-compact">
64
- <Text size="sm">{emptyMessage}</Text>
65
- </div>
43
+ <Text size="sm" className="px-row py-row">
44
+ {emptyMessage}
45
+ </Text>
66
46
  ) : null}
67
47
 
68
48
  {repositories.length > 0 ? (
69
49
  <RadioGroup
50
+ variant="cell"
70
51
  aria-labelledby={labelId}
71
52
  value={selectedRepositoryId ?? ''}
72
53
  onValueChange={onSelect}
73
- className={REPOSITORY_GRID_CLASS_NAME}
74
54
  >
75
55
  {repositories.map((repository) => (
76
56
  <RepositoryCard key={repository.externalRepositoryId} repository={repository} />
@@ -79,15 +59,17 @@ export function RepositoryPicker({
79
59
  ) : null}
80
60
 
81
61
  {hasNextPage && onLoadMore ? (
82
- <Button
83
- type="button"
84
- variant="secondary"
85
- size="sm"
86
- isLoading={isFetchingNextPage ?? false}
87
- onClick={onLoadMore}
88
- >
89
- Load more
90
- </Button>
62
+ <div className="flex justify-center border-t border-border-neutral-base p-panel-compact">
63
+ <Button
64
+ type="button"
65
+ variant="secondary"
66
+ size="sm"
67
+ isLoading={isFetchingNextPage ?? false}
68
+ onClick={onLoadMore}
69
+ >
70
+ Load more
71
+ </Button>
72
+ </div>
91
73
  ) : null}
92
74
  </div>
93
75
  );
@@ -99,7 +81,7 @@ function RepositoryCard({repository}: {repository: Repository}) {
99
81
  return (
100
82
  <Tooltip>
101
83
  <TooltipTrigger asChild>
102
- <RadioGroupItem value={repository.externalRepositoryId} className="min-w-0">
84
+ <RadioGroupItem value={repository.externalRepositoryId}>
103
85
  <span ref={nameRef} className="block min-w-0 truncate">
104
86
  <Text as="span" size="sm" bold>
105
87
  {repository.name}
@@ -118,18 +100,11 @@ function RepositoryLoadingState() {
118
100
  <div role="status" className="sr-only">
119
101
  Loading repositories.
120
102
  </div>
121
- <div aria-hidden="true" className={REPOSITORY_GRID_CLASS_NAME}>
122
- {/* The skeleton mirrors RadioGroupItem's own 14px padding contract so the
123
- placeholder and the loaded card stay the same height. */}
103
+ <PanelGrid as="div" aria-hidden="true">
124
104
  {REPOSITORY_SKELETON_WIDTHS.map((width) => (
125
- <div
126
- key={width}
127
- className="h-50 min-w-0 rounded-8 border border-border-neutral-base bg-background-neutral-base p-[14px]"
128
- >
129
- <Skeleton className={`h-20 ${width}`} />
130
- </div>
105
+ <RadioGroupItemSkeleton key={width} variant="cell" labelClassName={width} />
131
106
  ))}
132
- </div>
107
+ </PanelGrid>
133
108
  </>
134
109
  );
135
110
  }
@@ -126,7 +126,7 @@ export const CopyableValueState: Story = {
126
126
 
127
127
  function StorySurface({scenario}: {scenario: Scenario}) {
128
128
  return (
129
- <div className="min-h-screen bg-background-neutral-background p-24">
129
+ <div className="min-h-screen bg-background-subtle-base p-24">
130
130
  {scenario === 'create-form' ? (
131
131
  <WebhookCreateModal
132
132
  workspaceId={WORKSPACE_ID}
@@ -40,7 +40,7 @@ export function GiteaInstallPage() {
40
40
  });
41
41
 
42
42
  return (
43
- <div className="mx-auto flex w-full max-w-[480px] flex-col gap-section">
43
+ <div className="flex w-full flex-col gap-section">
44
44
  <header className="flex flex-col gap-inline">
45
45
  <Header variant="h1">Install Gitea</Header>
46
46
  <Text size="md" className="text-foreground-neutral-muted">
@@ -1,10 +1,10 @@
1
1
  import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';
2
- import {useRouteSearch} from '@shipfox/client-shell/runtime';
2
+ import {FocusedFrame, useRouteSearch} from '@shipfox/client-shell/runtime';
3
3
  import {sessionStorageOrUndefined} from '@shipfox/client-ui';
4
4
  import {Button, ButtonLink} from '@shipfox/react-ui/button';
5
5
  import {Callout} from '@shipfox/react-ui/callout';
6
- import {Card} from '@shipfox/react-ui/card';
7
6
  import {FullPageLoader} from '@shipfox/react-ui/loader';
7
+ import {Panel} from '@shipfox/react-ui/panel';
8
8
  import {toast} from '@shipfox/react-ui/toast';
9
9
  import {Header, Text} from '@shipfox/react-ui/typography';
10
10
  import {useQueryClient} from '@tanstack/react-query';
@@ -300,8 +300,8 @@ function JiraSiteSelectionPage({
300
300
  onSelect: (site: JiraSite) => void;
301
301
  }) {
302
302
  return (
303
- <main className="flex min-h-screen bg-background-subtle-base px-row py-frame">
304
- <div className="mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section">
303
+ <main className="flex min-h-screen px-frame py-frame">
304
+ <FocusedFrame className="flex flex-col justify-center gap-section">
305
305
  <header className="flex flex-col gap-inline">
306
306
  <Header variant="h2">Choose a Jira site</Header>
307
307
  <Text size="sm" className="text-foreground-neutral-muted">
@@ -317,7 +317,7 @@ function JiraSiteSelectionPage({
317
317
 
318
318
  <section className="flex flex-col gap-inline" aria-label="Choose a Jira site">
319
319
  {sites.map((site) => (
320
- <Card key={site.cloudId} className="p-panel-compact">
320
+ <Panel key={site.cloudId} className="p-panel-compact">
321
321
  <div className="flex items-center justify-between gap-cluster">
322
322
  <div className="min-w-0">
323
323
  <Text size="md" bold className="truncate">
@@ -336,7 +336,7 @@ function JiraSiteSelectionPage({
336
336
  Connect
337
337
  </Button>
338
338
  </div>
339
- </Card>
339
+ </Panel>
340
340
  ))}
341
341
  </section>
342
342
 
@@ -360,7 +360,7 @@ function JiraSiteSelectionPage({
360
360
  </ButtonLink>
361
361
  )}
362
362
  </div>
363
- </div>
363
+ </FocusedFrame>
364
364
  </main>
365
365
  );
366
366
  }
@@ -1,10 +1,10 @@
1
1
  import {useAuthState, useRefreshAuth} from '@shipfox/client-auth';
2
- import {useRouteSearch} from '@shipfox/client-shell/runtime';
2
+ import {FocusedFrame, useRouteSearch} from '@shipfox/client-shell/runtime';
3
3
  import {createSingleFlight, sessionStorageOrUndefined} from '@shipfox/client-ui';
4
4
  import {Button, ButtonLink} from '@shipfox/react-ui/button';
5
5
  import {Callout} from '@shipfox/react-ui/callout';
6
- import {Card} from '@shipfox/react-ui/card';
7
6
  import {FullPageLoader} from '@shipfox/react-ui/loader';
7
+ import {Panel} from '@shipfox/react-ui/panel';
8
8
  import {toast} from '@shipfox/react-ui/toast';
9
9
  import {Header, Text} from '@shipfox/react-ui/typography';
10
10
  import {useQueryClient} from '@tanstack/react-query';
@@ -212,7 +212,7 @@ export function SentryCallbackPage() {
212
212
 
213
213
  <section className="flex flex-col gap-inline" aria-label="Choose a workspace">
214
214
  {orderedWorkspaces.map((workspace) => (
215
- <Card key={workspace.id} className="p-panel-compact">
215
+ <Panel key={workspace.id} className="p-panel-compact">
216
216
  <div className="flex items-center justify-between gap-cluster">
217
217
  <Text size="md" bold className="truncate">
218
218
  {workspace.name}
@@ -226,7 +226,7 @@ export function SentryCallbackPage() {
226
226
  Install
227
227
  </Button>
228
228
  </div>
229
- </Card>
229
+ </Panel>
230
230
  ))}
231
231
  </section>
232
232
 
@@ -246,10 +246,8 @@ export function SentryCallbackPage() {
246
246
 
247
247
  function CallbackColumn({children}: {children: React.ReactNode}) {
248
248
  return (
249
- <main className="flex min-h-screen bg-background-subtle-base px-row py-frame">
250
- <div className="mx-auto flex w-full max-w-[480px] flex-col justify-center gap-section">
251
- {children}
252
- </div>
249
+ <main className="flex min-h-screen px-frame py-frame">
250
+ <FocusedFrame className="flex flex-col justify-center gap-section">{children}</FocusedFrame>
253
251
  </main>
254
252
  );
255
253
  }
@@ -1,5 +1,6 @@
1
1
  // @vitest-environment jsdom
2
2
  import '@testing-library/jest-dom/vitest';
3
+ import {configureApiClient} from '@shipfox/client-api';
3
4
  import {screen, waitFor} from '@testing-library/react';
4
5
  import {StrictMode} from 'react';
5
6
  import {SLACK_INSTALL_WORKSPACE_KEY} from '#slack-callback.js';
@@ -27,6 +28,12 @@ vi.mock('#hooks/api/integrations.js', async (importOriginal) => {
27
28
  beforeEach(() => {
28
29
  window.sessionStorage.clear();
29
30
  completeCallbackMock.mockReset();
31
+ configureApiClient({
32
+ baseUrl: 'https://api.example.test',
33
+ fetchImpl: vi.fn((_input: RequestInfo | URL) =>
34
+ Promise.reject(new Error('Workspace list unavailable')),
35
+ ),
36
+ });
30
37
  });
31
38
 
32
39
  describe('SlackCallbackPage', () => {
@@ -8,7 +8,7 @@ export function SourceControlOnboardingPage() {
8
8
  const providersQuery = useIntegrationProvidersQuery({capability: 'source_control'});
9
9
 
10
10
  return (
11
- <div className="mx-auto flex w-full max-w-[640px] flex-col gap-section">
11
+ <div className="flex w-full flex-col gap-section">
12
12
  <header className="flex flex-col gap-inline">
13
13
  <Header variant="h1">Install source control</Header>
14
14
  <Text size="md" className="text-foreground-neutral-muted">
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {GiteaInstallPage} from '#pages/gitea-install-page.js';
3
3
 
4
- export default defineRoute({component: GiteaInstallPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: GiteaInstallPage,
7
+ });
@@ -29,6 +29,7 @@ const callbackRequests = createSingleFlight<string, void>({maxTerminalResults: 3
29
29
  const toastedCallbacks = new Set<string>();
30
30
 
31
31
  export default defineRoute({
32
+ staticData: {frame: 'focused'},
32
33
  validateSearch: validateGithubCallbackSearch,
33
34
  component: GithubCallbackRoute,
34
35
  });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {GithubInstallPage} from '#pages/github-install-page.js';
3
3
 
4
- export default defineRoute({component: GithubInstallPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: GithubInstallPage,
7
+ });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {IntegrationGallery} from '#index.js';
3
3
 
4
- export default defineRoute({component: IntegrationGallery});
4
+ export default defineRoute({
5
+ staticData: {frame: 'content'},
6
+ component: IntegrationGallery,
7
+ });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {SourceControlOnboardingPage} from '#pages/source-control-onboarding-page.js';
3
3
 
4
- export default defineRoute({component: SourceControlOnboardingPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: SourceControlOnboardingPage,
7
+ });
@@ -3,6 +3,7 @@ import {JiraCallbackPage} from '#pages/jira-callback-page.js';
3
3
  import {parseJiraCallbackQuery} from '../jira-callback.js';
4
4
 
5
5
  export default defineRoute({
6
+ staticData: {frame: 'focused'},
6
7
  validateSearch: parseJiraCallbackQuery,
7
8
  component: JiraCallbackPage,
8
9
  });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {JiraInstallPage} from '#pages/jira-install-page.js';
3
3
 
4
- export default defineRoute({component: JiraInstallPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: JiraInstallPage,
7
+ });
@@ -3,6 +3,7 @@ import {LinearCallbackPage} from '#pages/linear-callback-page.js';
3
3
  import {parseLinearCallbackQuery} from '../linear-callback.js';
4
4
 
5
5
  export default defineRoute({
6
+ staticData: {frame: 'focused'},
6
7
  validateSearch: parseLinearCallbackQuery,
7
8
  component: LinearCallbackPage,
8
9
  });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {LinearInstallPage} from '#pages/linear-install-page.js';
3
3
 
4
- export default defineRoute({component: LinearInstallPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: LinearInstallPage,
7
+ });
@@ -3,6 +3,7 @@ import {SentryCallbackPage} from '#pages/sentry-callback-page.js';
3
3
  import {parseSentryCallbackParams} from '../sentry-callback.js';
4
4
 
5
5
  export default defineRoute({
6
+ staticData: {frame: 'focused'},
6
7
  validateSearch: parseSentryCallbackParams,
7
8
  component: SentryCallbackPage,
8
9
  });
@@ -1,4 +1,7 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {SentryInstallPage} from '#pages/sentry-install-page.js';
3
3
 
4
- export default defineRoute({component: SentryInstallPage});
4
+ export default defineRoute({
5
+ staticData: {frame: 'focused'},
6
+ component: SentryInstallPage,
7
+ });
@@ -3,6 +3,7 @@ import {SlackCallbackPage} from '#pages/slack-callback-page.js';
3
3
  import {parseSlackCallbackQuery} from '../slack-callback.js';
4
4
 
5
5
  export default defineRoute({
6
+ staticData: {frame: 'focused'},
6
7
  validateSearch: parseSlackCallbackQuery,
7
8
  component: SlackCallbackPage,
8
9
  });
@@ -1,3 +1,6 @@
1
1
  import {defineRoute} from '@shipfox/client-shell/runtime';
2
2
  import {SlackInstallPage} from '#pages/slack-install-page.js';
3
- export default defineRoute({component: SlackInstallPage});
3
+ export default defineRoute({
4
+ staticData: {frame: 'focused'},
5
+ component: SlackInstallPage,
6
+ });