@jpmorganchase/elemental-dev-portal 1.0.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. package/components/BranchSelector/BranchSelector.d.ts +7 -0
  2. package/components/BranchSelector/BranchSelector.spec.d.ts +15 -0
  3. package/components/BranchSelector/BranchSelector.stories.d.ts +29 -0
  4. package/components/DevPortalProvider/index.d.ts +7 -0
  5. package/components/Forbidden.d.ts +1 -0
  6. package/components/Loading.d.ts +1 -0
  7. package/components/NodeContent/NodeContent.d.ts +17 -0
  8. package/components/NodeContent/NodeContent.spec.d.ts +1 -0
  9. package/components/NodeContent/NodeContent.stories.d.ts +43 -0
  10. package/components/NotFound.d.ts +1 -0
  11. package/components/Search/Search.d.ts +13 -0
  12. package/components/Search/Search.stories.d.ts +33 -0
  13. package/components/TableOfContents/TableOfContents.d.ts +12 -0
  14. package/components/TableOfContents/TableOfContents.stories.d.ts +36 -0
  15. package/components/UpgradeToStarter.d.ts +1 -0
  16. package/consts.d.ts +28 -0
  17. package/containers/StoplightProject.d.ts +13 -0
  18. package/containers/StoplightProject.spec.d.ts +1 -0
  19. package/containers/StoplightProject.stories.d.ts +45 -0
  20. package/handlers/getBranches.d.ts +6 -0
  21. package/handlers/getNodeContent.d.ts +12 -0
  22. package/handlers/getNodes.d.ts +9 -0
  23. package/handlers/getTableOfContents.d.ts +7 -0
  24. package/handlers/getWorkspace.d.ts +6 -0
  25. package/hooks/useGetBranches.d.ts +3 -0
  26. package/hooks/useGetNodeContent.d.ts +5 -0
  27. package/hooks/useGetNodes.d.ts +7 -0
  28. package/hooks/useGetTableOfContents.d.ts +4 -0
  29. package/hooks/useGetWorkspace.d.ts +3 -0
  30. package/index.esm.js +682 -0
  31. package/index.js +726 -0
  32. package/index.mjs +682 -0
  33. package/package.json +17 -70
  34. package/styles.min.css +1 -0
  35. package/types.d.ts +65 -0
  36. package/version.d.ts +1 -0
  37. package/web-components/components.d.ts +1 -0
  38. package/web-components/index.d.ts +1 -0
  39. package/web-components.min.js +2 -0
  40. package/web-components.min.js.LICENSE.txt +187 -0
  41. package/.storybook/main.js +0 -1
  42. package/.storybook/manager.js +0 -1
  43. package/.storybook/preview.jsx +0 -46
  44. package/jest.config.js +0 -10
  45. package/src/__fixtures__/branches.json +0 -26
  46. package/src/__fixtures__/node-content.json +0 -257
  47. package/src/__fixtures__/table-of-contents.json +0 -144
  48. package/src/components/BranchSelector/BranchSelector.spec.tsx +0 -63
  49. package/src/components/BranchSelector/BranchSelector.stories.tsx +0 -41
  50. package/src/components/BranchSelector/BranchSelector.tsx +0 -50
  51. package/src/components/DevPortalProvider/index.tsx +0 -19
  52. package/src/components/Forbidden.tsx +0 -11
  53. package/src/components/Loading.tsx +0 -9
  54. package/src/components/NodeContent/NodeContent.spec.tsx +0 -54
  55. package/src/components/NodeContent/NodeContent.stories.tsx +0 -60
  56. package/src/components/NodeContent/NodeContent.tsx +0 -171
  57. package/src/components/NotFound.tsx +0 -11
  58. package/src/components/Search/Search.stories.tsx +0 -73
  59. package/src/components/Search/Search.tsx +0 -133
  60. package/src/components/TableOfContents/TableOfContents.stories.tsx +0 -54
  61. package/src/components/TableOfContents/TableOfContents.tsx +0 -51
  62. package/src/components/UpgradeToStarter.tsx +0 -22
  63. package/src/consts.ts +0 -32
  64. package/src/containers/StoplightProject.spec.tsx +0 -78
  65. package/src/containers/StoplightProject.stories.tsx +0 -28
  66. package/src/containers/StoplightProject.tsx +0 -213
  67. package/src/handlers/__tests__/getBranches.test.ts +0 -30
  68. package/src/handlers/__tests__/getNodeContent.test.ts +0 -35
  69. package/src/handlers/__tests__/getNodes.test.ts +0 -38
  70. package/src/handlers/__tests__/getTableOfContents.test.ts +0 -34
  71. package/src/handlers/__tests__/getWorkspace.test.ts +0 -30
  72. package/src/handlers/getBranches.ts +0 -27
  73. package/src/handlers/getNodeContent.ts +0 -53
  74. package/src/handlers/getNodes.ts +0 -69
  75. package/src/handlers/getTableOfContents.ts +0 -30
  76. package/src/handlers/getWorkspace.ts +0 -27
  77. package/src/hooks/__tests__/dataFetching.spec.tsx +0 -42
  78. package/src/hooks/useGetBranches.ts +0 -17
  79. package/src/hooks/useGetNodeContent.ts +0 -24
  80. package/src/hooks/useGetNodes.ts +0 -34
  81. package/src/hooks/useGetTableOfContents.ts +0 -15
  82. package/src/hooks/useGetWorkspace.tsx +0 -13
  83. package/src/styles.css +0 -1
  84. package/src/types.ts +0 -81
  85. package/src/version.ts +0 -2
  86. package/src/web-components/__stories__/StoplightProject.stories.tsx +0 -33
  87. package/src/web-components/components.ts +0 -17
  88. package/src/web-components/index.ts +0 -3
  89. package/tsconfig.build.json +0 -18
  90. package/tsconfig.json +0 -7
  91. package/web-components.config.js +0 -1
  92. /package/{src/components/BranchSelector/index.tsx → components/BranchSelector/index.d.ts} +0 -0
  93. /package/{src/components/NodeContent/index.tsx → components/NodeContent/index.d.ts} +0 -0
  94. /package/{src/components/Search/index.tsx → components/Search/index.d.ts} +0 -0
  95. /package/{src/components/TableOfContents/index.tsx → components/TableOfContents/index.d.ts} +0 -0
  96. /package/{src/index.ts → index.d.ts} +0 -0
@@ -1,63 +0,0 @@
1
- import { Provider as MosaicProvider } from '@stoplight/mosaic';
2
- import { screen } from '@testing-library/dom';
3
- import { render } from '@testing-library/react';
4
- import userEvent from '@testing-library/user-event';
5
- import * as React from 'react';
6
-
7
- import { BranchSelector } from './BranchSelector';
8
-
9
- export const branches = [
10
- {
11
- id: 0,
12
- slug: 'main',
13
- is_default: true,
14
- is_published: false,
15
- projectId: 123,
16
- name: 'main-name',
17
- },
18
- {
19
- id: 1,
20
- slug: 'beta',
21
- is_default: false,
22
- is_published: false,
23
- projectId: 123,
24
- },
25
- {
26
- id: 2,
27
- slug: 'feature-branch',
28
- is_default: false,
29
- is_published: false,
30
- projectId: 123,
31
- },
32
- ];
33
-
34
- const BranchSelectorWrapper: React.FC = () => {
35
- const [branchSlug, setBranchSlug] = React.useState('main');
36
-
37
- return (
38
- <MosaicProvider>
39
- <BranchSelector branchSlug={branchSlug} branches={branches} onChange={branch => setBranchSlug(branch.slug)} />
40
- </MosaicProvider>
41
- );
42
- };
43
-
44
- function getBranchSelector() {
45
- return screen.getByRole('button');
46
- }
47
-
48
- describe('Branch selector', () => {
49
- it('shows the default branch by default', () => {
50
- render(<BranchSelectorWrapper />);
51
-
52
- expect(getBranchSelector()).toHaveTextContent('main-name');
53
- });
54
-
55
- it('selects a branch', () => {
56
- render(<BranchSelectorWrapper />);
57
-
58
- userEvent.click(getBranchSelector());
59
- userEvent.click(screen.getByRole('menuitemradio', { name: 'beta' }));
60
-
61
- expect(getBranchSelector()).toHaveTextContent('beta');
62
- });
63
- });
@@ -1,41 +0,0 @@
1
- import { Box } from '@stoplight/mosaic';
2
- import { Story } from '@storybook/react';
3
- import * as React from 'react';
4
-
5
- import { useGetBranches } from '../../hooks/useGetBranches';
6
- import { BranchSelector } from './';
7
-
8
- // Wrapper to show how to use the node content hook
9
- const BranchSelectorWrapper = ({ projectId }: { projectId: string }) => {
10
- const [branchSlug, setBranchSlug] = React.useState('master');
11
- const { data } = useGetBranches({ projectId });
12
-
13
- if (data) {
14
- return (
15
- <Box mt={10} w={40}>
16
- <BranchSelector branchSlug={branchSlug} branches={data} onChange={branch => setBranchSlug(branch.slug)} />
17
- </Box>
18
- );
19
- }
20
-
21
- return <Box>Loading</Box>;
22
- };
23
-
24
- export default {
25
- title: 'Public/BranchSelector',
26
- component: BranchSelectorWrapper,
27
- argTypes: {
28
- projectId: { table: { category: 'Input' } },
29
- platformUrl: { table: { category: 'Input' } },
30
- },
31
- args: {
32
- projectId: 'cHJqOjYwNjYx',
33
- platformUrl: 'https://stoplight.io',
34
- },
35
- };
36
-
37
- export const Playground: Story<{ nodeSlug: string; projectId: string; branchSlug?: string }> = args => (
38
- <BranchSelectorWrapper {...args} />
39
- );
40
-
41
- Playground.storyName = 'Studio Demo';
@@ -1,50 +0,0 @@
1
- import { FieldButton, Menu } from '@stoplight/mosaic';
2
- import * as React from 'react';
3
-
4
- import { Branch } from '../../types';
5
-
6
- export type BranchSelectorProps = {
7
- branchSlug: string;
8
- branches: Branch[];
9
- onChange: (branch: Branch) => void;
10
- };
11
-
12
- export const BranchSelector = ({ branchSlug, branches, onChange }: BranchSelectorProps) => {
13
- const currentBranch = branches.find(branch => (!branchSlug ? branch.is_default : branch.slug === branchSlug));
14
- const handleChange = React.useCallback(
15
- (selectedSlug: React.ReactText) => {
16
- const selectedBranch = branches.find(branch => branch.slug === selectedSlug);
17
- if (selectedBranch) {
18
- onChange(selectedBranch);
19
- }
20
- },
21
- [onChange, branches],
22
- );
23
-
24
- return (
25
- <Menu
26
- aria-label="Versions"
27
- placement="bottom left"
28
- closeOnPress
29
- matchTriggerWidth
30
- renderTrigger={({ isOpen }) => (
31
- <FieldButton w="full" icon="layer-group" px={4} h="md" active={isOpen} borderR={0} roundedR="none">
32
- {currentBranch?.name || currentBranch?.slug || 'Choose a version'}
33
- </FieldButton>
34
- )}
35
- items={[
36
- {
37
- type: 'option_group',
38
- title: 'Versions',
39
- onChange: handleChange,
40
- value: currentBranch?.slug || '',
41
- children: branches.map(branch => ({
42
- label: branch.name || branch.slug,
43
- value: branch.slug,
44
- meta: branch.is_default ? 'Default' : undefined,
45
- })),
46
- },
47
- ]}
48
- />
49
- );
50
- };
@@ -1,19 +0,0 @@
1
- import { withMosaicProvider, withPersistenceBoundary, withQueryClientProvider } from '@stoplight/elements-core';
2
- import * as React from 'react';
3
-
4
- export type DevPortalProviderProps = {
5
- platformUrl?: string;
6
- platformAuthToken?: string;
7
- };
8
-
9
- export const PlatformContext = React.createContext<DevPortalProviderProps>({ platformUrl: 'https://stoplight.io' });
10
-
11
- const PlatformProvider: React.FC<DevPortalProviderProps> = ({
12
- platformUrl = 'https://stoplight.io',
13
- platformAuthToken,
14
- children,
15
- }) => {
16
- return <PlatformContext.Provider value={{ platformUrl, platformAuthToken }}>{children}</PlatformContext.Provider>;
17
- };
18
-
19
- export const DevPortalProvider = withPersistenceBoundary(withQueryClientProvider(withMosaicProvider(PlatformProvider)));
@@ -1,11 +0,0 @@
1
- import { Box, Flex, Heading, VStack } from '@stoplight/mosaic';
2
- import React from 'react';
3
-
4
- export const Forbidden = () => (
5
- <Flex align="center" justify="center" flexGrow>
6
- <VStack spacing={4} align="center">
7
- <Heading size={1}>Forbidden</Heading>
8
- <Box as="p">You don't have permission to access this resource</Box>
9
- </VStack>
10
- </Flex>
11
- );
@@ -1,9 +0,0 @@
1
- import { faCircleNotch } from '@fortawesome/free-solid-svg-icons';
2
- import { Flex, Icon } from '@stoplight/mosaic';
3
- import React from 'react';
4
-
5
- export const Loading = () => (
6
- <Flex justify="center" alignItems="center" w="full" minH="screen" color="muted">
7
- <Icon icon={faCircleNotch} size="3x" spin />
8
- </Flex>
9
- );
@@ -1,54 +0,0 @@
1
- import { CustomLinkComponent } from '@stoplight/elements-core';
2
- import { render, screen } from '@testing-library/react';
3
- import * as React from 'react';
4
- import { MemoryRouter } from 'react-router-dom';
5
-
6
- import nodeContent from '../../__fixtures__/node-content.json';
7
- import { NodeContent } from './NodeContent';
8
-
9
- const DummyLink: CustomLinkComponent = ({ children, ...propsRest }) => {
10
- return <a {...propsRest}>{children}</a>;
11
- };
12
-
13
- describe(NodeContent.name, () => {
14
- it('renders correctly', async () => {
15
- const { unmount } = render(
16
- <MemoryRouter>
17
- <NodeContent node={nodeContent} Link={DummyLink} />
18
- </MemoryRouter>,
19
- );
20
-
21
- expect(screen.getByRole('heading', { name: /create todo/i })).toBeInTheDocument();
22
- expect(
23
- await screen.findByText(
24
- 'Markdown is supported in descriptions. Add information here for users to get accustomed to endpoints',
25
- ),
26
- ).toBeInTheDocument();
27
-
28
- unmount();
29
- });
30
-
31
- it('shows TryIt by default', () => {
32
- const { unmount } = render(
33
- <MemoryRouter>
34
- <NodeContent node={nodeContent} Link={DummyLink} />
35
- </MemoryRouter>,
36
- );
37
-
38
- expect(screen.getByText(/send api request/i)).toBeInTheDocument();
39
-
40
- unmount();
41
- });
42
-
43
- it('can hide TryIt', () => {
44
- const { unmount } = render(
45
- <MemoryRouter>
46
- <NodeContent node={nodeContent} Link={DummyLink} hideTryIt />
47
- </MemoryRouter>,
48
- );
49
-
50
- expect(screen.queryByText(/send api request/i)).not.toBeInTheDocument();
51
-
52
- unmount();
53
- });
54
- });
@@ -1,60 +0,0 @@
1
- import { Story } from '@storybook/react';
2
- import * as React from 'react';
3
-
4
- import { useGetNodeContent } from '../../hooks/useGetNodeContent';
5
- import { NodeContent } from './';
6
-
7
- // Wrapper to show how to use the node content hook
8
- const NodeContentWrapper = ({
9
- nodeSlug,
10
- projectId,
11
- branchSlug,
12
- }: {
13
- nodeSlug: string;
14
- projectId: string;
15
- branchSlug?: string;
16
- }) => {
17
- const { data } = useGetNodeContent({ nodeSlug, projectId, branchSlug });
18
-
19
- return data ? (
20
- <NodeContent
21
- node={data}
22
- Link={({ children, ...props }) => {
23
- return (
24
- <a
25
- onClick={() => {
26
- console.log('Link clicked!', props);
27
- }}
28
- >
29
- {children}
30
- </a>
31
- );
32
- }}
33
- />
34
- ) : (
35
- <>Loading</>
36
- );
37
- };
38
-
39
- export default {
40
- title: 'Public/NodeContent',
41
- component: NodeContentWrapper,
42
- argTypes: {
43
- nodeSlug: { table: { category: 'Input' } },
44
- projectId: { table: { category: 'Input' } },
45
- branchSlug: { table: { category: 'Input' } },
46
- platformUrl: { table: { category: 'Input' } },
47
- },
48
- args: {
49
- nodeSlug: 'b3A6Mzg5NDM2-create-todo',
50
- projectId: 'cHJqOjYwNjYx',
51
- branchSlug: '',
52
- platformUrl: 'https://stoplight.io',
53
- },
54
- };
55
-
56
- export const Playground: Story<{ nodeSlug: string; projectId: string; branchSlug?: string }> = args => (
57
- <NodeContentWrapper {...args} />
58
- );
59
-
60
- Playground.storyName = 'Create Todo';
@@ -1,171 +0,0 @@
1
- import {
2
- CustomLinkComponent,
3
- Docs,
4
- DocsProps,
5
- MarkdownComponentsProvider,
6
- MockingProvider,
7
- ReferenceResolver,
8
- } from '@stoplight/elements-core';
9
- import { CustomComponentMapping } from '@stoplight/markdown-viewer';
10
- import { dirname, resolve } from '@stoplight/path';
11
- import { NodeType } from '@stoplight/types';
12
- import * as React from 'react';
13
-
14
- import { Node } from '../../types';
15
-
16
- // Props shared with elements-core Docs component
17
- type DocsBaseProps = Pick<DocsProps, 'tryItCorsProxy' | 'tryItCredentialsPolicy' | 'nodeHasChanged'>;
18
- type DocsLayoutProps = Pick<
19
- Required<DocsProps>['layoutOptions'],
20
- 'compact' | 'hideTryIt' | 'hideTryItPanel' | 'hideExport'
21
- >;
22
-
23
- export type NodeContentProps = {
24
- node: Node;
25
- Link: CustomLinkComponent;
26
-
27
- /**
28
- * Allows to hide mocking button
29
- */
30
- hideMocking?: boolean;
31
-
32
- /**
33
- * Support for custom reference resolver
34
- */
35
- refResolver?: ReferenceResolver;
36
-
37
- onExportRequest?: (type: 'original' | 'bundled') => void;
38
- } & DocsBaseProps &
39
- DocsLayoutProps;
40
-
41
- export const NodeContent = ({
42
- node,
43
- Link,
44
- hideMocking,
45
- refResolver,
46
-
47
- // Docs base props
48
- tryItCorsProxy,
49
- tryItCredentialsPolicy,
50
- nodeHasChanged,
51
-
52
- // Docs layout props
53
- compact,
54
- hideTryIt,
55
- hideTryItPanel,
56
-
57
- // Exporting
58
- hideExport,
59
- onExportRequest,
60
- }: NodeContentProps) => {
61
- return (
62
- <NodeLinkContext.Provider value={[node, Link]}>
63
- <MarkdownComponentsProvider value={{ a: LinkComponent }}>
64
- <MockingProvider mockUrl={node.links.mock_url} hideMocking={hideMocking}>
65
- <Docs
66
- nodeType={node.type as NodeType}
67
- nodeData={node.data}
68
- nodeTitle={node.title}
69
- layoutOptions={{
70
- compact,
71
- hideTryIt: hideTryIt,
72
- hideTryItPanel: hideTryItPanel,
73
- hideExport:
74
- hideExport ||
75
- (node.links.export_url ?? node.links.export_original_file_url ?? node.links.export_bundled_file_url) ===
76
- undefined,
77
- }}
78
- useNodeForRefResolving
79
- refResolver={refResolver}
80
- tryItCorsProxy={tryItCorsProxy}
81
- exportProps={
82
- [NodeType.HttpService, NodeType.Model].includes(node.type as NodeType)
83
- ? {
84
- original: onExportRequest
85
- ? { onPress: () => onExportRequest('original') }
86
- : { href: node.links.export_original_file_url ?? node.links.export_url },
87
- bundled: onExportRequest
88
- ? { onPress: () => onExportRequest('bundled') }
89
- : { href: node.links.export_bundled_file_url ?? getBundledUrl(node.links.export_url) },
90
- }
91
- : undefined
92
- }
93
- tryItCredentialsPolicy={tryItCredentialsPolicy}
94
- nodeHasChanged={nodeHasChanged}
95
- />
96
- </MockingProvider>
97
- </MarkdownComponentsProvider>
98
- </NodeLinkContext.Provider>
99
- );
100
- };
101
-
102
- const NodeLinkContext = React.createContext<[Node, CustomLinkComponent] | undefined>(undefined);
103
-
104
- const externalRegex = new RegExp('^(?:[a-z]+:)?//', 'i');
105
- const LinkComponent: CustomComponentMapping['a'] = ({ children, href, title }) => {
106
- const ctx = React.useContext(NodeLinkContext);
107
-
108
- if (href && externalRegex.test(href)) {
109
- // Open external URL in a new tab
110
- return (
111
- <a href={href} target="_blank" rel="noreferrer" title={title ? title : undefined}>
112
- {children}
113
- </a>
114
- );
115
- }
116
-
117
- if (href && ctx) {
118
- const [node, Link] = ctx;
119
- // Resolve relative file URI with
120
- const { fileUri } = getNodeUriParts(node.uri);
121
- const { fileUri: hrefFileUri } = getNodeUriParts(href);
122
-
123
- let resolvedUri;
124
- if (hrefFileUri) {
125
- // if the href is targeting another file, resolve it against the dir path of current file
126
- resolvedUri = resolve(dirname(fileUri), href);
127
- } else {
128
- // If the href does not include a file, resolve it relative to the current file
129
- resolvedUri = resolve(fileUri, href);
130
- }
131
-
132
- const [resolvedUriWithoutAnchor, hash] = resolvedUri.split('#');
133
- const decodedUrl = decodeURIComponent(href);
134
- const decodedResolvedUriWithoutAnchor = decodeURIComponent(resolvedUriWithoutAnchor);
135
- const edge = node.outbound_edges.find(
136
- edge => edge.uri === decodedUrl || edge.uri === decodedResolvedUriWithoutAnchor,
137
- );
138
-
139
- if (edge) {
140
- return <Link to={`${edge.slug}${hash ? `#${hash}` : ''}`}>{children}</Link>;
141
- }
142
- }
143
-
144
- return <a href={href}>{children}</a>;
145
- };
146
-
147
- function getBundledUrl(url: string | undefined) {
148
- if (url === undefined) return undefined;
149
- const bundledUrl = new URL(url);
150
- const searchParams = new URLSearchParams(bundledUrl.search);
151
- searchParams.append('deref', 'optimizedBundle');
152
- bundledUrl.search = searchParams.toString();
153
- return bundledUrl.toString();
154
- }
155
-
156
- // Extract out just the file portion of the node URI
157
- // This handles cases such as links to http_operation node uris, which include both the file + encoded pointer, e.g.
158
- //
159
- // /reference/openapi.json/paths/~1v2~1contact~1last_change/post#heading-anchor
160
- // fileUri = /reference/openapi.json
161
- // pointer = /paths/~1v2~1contact~1last_change/post#heading-anchor
162
- export const getNodeUriParts = (uri: string): { fileUri: string; pointer: string } => {
163
- const parts = uri.split(/(\.yaml|\.yml|\.json|\.md)/);
164
- if (parts.length === 1) {
165
- return { fileUri: '', pointer: parts[0] || '' };
166
- }
167
-
168
- const fileUri = `${parts[0] || ''}${parts[1] || ''}`;
169
-
170
- return { fileUri, pointer: parts[2] || '' };
171
- };
@@ -1,11 +0,0 @@
1
- import { Box, Flex, Heading, VStack } from '@stoplight/mosaic';
2
- import React from 'react';
3
-
4
- export const NotFound = () => (
5
- <Flex align="center" justify="center" flexGrow>
6
- <VStack spacing={4} align="center">
7
- <Heading size={1}>Not Found</Heading>
8
- <Box as="p">Could not find what you are looking for</Box>
9
- </VStack>
10
- </Flex>
11
- );
@@ -1,73 +0,0 @@
1
- import { Input, useModalState } from '@stoplight/mosaic';
2
- import { Story } from '@storybook/react';
3
- import * as React from 'react';
4
-
5
- import { useGetNodes } from '../../hooks/useGetNodes';
6
- import { useGetWorkspace } from '../../hooks/useGetWorkspace';
7
- import { NodeSearchResult } from '../../types';
8
- import { Search } from './';
9
-
10
- type SearchWrapperProps = { projectIds: string[]; workspaceId: string };
11
- // Wrapper to show how to use the node content hook
12
- const SearchWrapper = ({ projectIds, workspaceId }: SearchWrapperProps) => {
13
- const { isOpen, open, close } = useModalState();
14
- const [search, setSearch] = React.useState('');
15
- const { data, isFetching } = useGetNodes({
16
- search,
17
- projectIds,
18
- workspaceId,
19
- });
20
-
21
- const { data: workspace } = useGetWorkspace({
22
- projectIds,
23
- });
24
-
25
- const handleClose = () => {
26
- close();
27
- setSearch('');
28
- };
29
-
30
- const handleClick = (searchResult: NodeSearchResult) => {
31
- console.log('Search clicked', searchResult);
32
- window.open(
33
- `https://${workspace?.workspace.slug}.stoplight.io/docs/${searchResult.project_slug}${searchResult.uri}`,
34
- '_blank',
35
- );
36
-
37
- handleClose();
38
- };
39
-
40
- return (
41
- <>
42
- <Input placeholder="Search..." onClick={open} />
43
- <Search
44
- isLoading={isFetching}
45
- search={search}
46
- searchResults={data}
47
- onSearch={setSearch}
48
- isOpen={isOpen}
49
- onClose={handleClose}
50
- onClick={handleClick}
51
- />
52
- </>
53
- );
54
- };
55
-
56
- export default {
57
- title: 'Public/Search',
58
- component: SearchWrapper,
59
- argTypes: {
60
- workspaceId: { table: { category: 'Input' } },
61
- projectIds: { table: { category: 'Input' } },
62
- platformUrl: { table: { category: 'Input' } },
63
- },
64
- args: {
65
- projectIds: ['cHJqOjYwNjYx'],
66
- workspaceId: 'd2s6NDE1NTU',
67
- platformUrl: 'https://stoplight.io',
68
- },
69
- };
70
-
71
- export const Playground: Story<SearchWrapperProps> = args => <SearchWrapper {...args} />;
72
-
73
- Playground.storyName = 'Studio Demo';