@redocly/theme 0.68.0-next.3 → 0.68.0-next.5

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 (71) hide show
  1. package/lib/components/Button/ShowMoreToggleButton.d.ts +11 -0
  2. package/lib/components/Button/ShowMoreToggleButton.js +21 -0
  3. package/lib/components/CodeBlock/CodeBlock.d.ts +7 -1
  4. package/lib/components/CodeBlock/CodeBlock.js +30 -7
  5. package/lib/components/Dropdown/Dropdown.d.ts +2 -0
  6. package/lib/components/Dropdown/Dropdown.js +59 -14
  7. package/lib/components/Dropdown/variables.js +3 -1
  8. package/lib/components/Feedback/Feedback.js +1 -3
  9. package/lib/components/Feedback/Stars.js +1 -1
  10. package/lib/components/Footer/FooterItem.js +1 -1
  11. package/lib/components/JsonViewer/Helpers.d.ts +1 -0
  12. package/lib/components/JsonViewer/Helpers.js +20 -7
  13. package/lib/components/JsonViewer/JsonViewer.d.ts +2 -0
  14. package/lib/components/JsonViewer/JsonViewer.js +2 -2
  15. package/lib/components/LanguagePicker/LanguagePicker.js +3 -2
  16. package/lib/components/Markdown/Markdown.js +13 -6
  17. package/lib/components/Menu/MenuItem.d.ts +7 -1
  18. package/lib/components/Menu/MenuItem.js +43 -2
  19. package/lib/components/Navbar/NavbarItem.js +8 -3
  20. package/lib/components/PageActions/PageActions.js +1 -4
  21. package/lib/components/Panel/Panel.js +1 -1
  22. package/lib/components/Panel/variables.js +1 -0
  23. package/lib/components/ReplayGate/ReplayGate.d.ts +12 -0
  24. package/lib/components/ReplayGate/ReplayGate.js +11 -0
  25. package/lib/components/ReplayTopBarActions/ReplayTopBarActions.d.ts +13 -0
  26. package/lib/components/ReplayTopBarActions/ReplayTopBarActions.js +7 -0
  27. package/lib/components/Search/SearchAiConversationInput.js +6 -0
  28. package/lib/components/Search/SearchDialog.js +4 -4
  29. package/lib/components/Search/SearchInput.js +5 -0
  30. package/lib/core/hooks/use-active-section-id.d.ts +2 -0
  31. package/lib/core/hooks/use-active-section-id.js +11 -1
  32. package/lib/core/hooks/use-page-actions.js +10 -9
  33. package/lib/core/hooks/use-theme-hooks.js +1 -0
  34. package/lib/core/openapi/index.d.ts +1 -1
  35. package/lib/core/openapi/index.js +2 -1
  36. package/lib/core/styles/global.js +8 -0
  37. package/lib/core/types/hooks.d.ts +1 -0
  38. package/lib/core/types/l10n.d.ts +1 -1
  39. package/lib/core/types/sidebar.d.ts +1 -0
  40. package/lib/layouts/ThreePanelLayout.d.ts +5 -2
  41. package/package.json +2 -2
  42. package/src/components/Button/ShowMoreToggleButton.tsx +33 -0
  43. package/src/components/CodeBlock/CodeBlock.tsx +56 -12
  44. package/src/components/Dropdown/Dropdown.tsx +93 -21
  45. package/src/components/Dropdown/variables.ts +3 -1
  46. package/src/components/Feedback/Feedback.tsx +1 -3
  47. package/src/components/Feedback/Stars.tsx +1 -0
  48. package/src/components/Footer/FooterItem.tsx +3 -0
  49. package/src/components/JsonViewer/Helpers.tsx +41 -3
  50. package/src/components/JsonViewer/JsonViewer.tsx +4 -0
  51. package/src/components/LanguagePicker/LanguagePicker.tsx +3 -1
  52. package/src/components/Markdown/Markdown.tsx +13 -6
  53. package/src/components/Menu/MenuItem.tsx +47 -2
  54. package/src/components/Navbar/NavbarItem.tsx +10 -4
  55. package/src/components/PageActions/PageActions.tsx +3 -6
  56. package/src/components/Panel/Panel.tsx +1 -1
  57. package/src/components/Panel/variables.ts +1 -0
  58. package/src/components/ReplayGate/ReplayGate.tsx +18 -0
  59. package/src/components/ReplayTopBarActions/ReplayTopBarActions.tsx +14 -0
  60. package/src/components/Search/SearchAiConversationInput.tsx +6 -0
  61. package/src/components/Search/SearchDialog.tsx +4 -4
  62. package/src/components/Search/SearchInput.tsx +6 -1
  63. package/src/core/hooks/use-active-section-id.ts +13 -1
  64. package/src/core/hooks/use-page-actions.ts +13 -11
  65. package/src/core/hooks/use-theme-hooks.ts +1 -0
  66. package/src/core/openapi/index.ts +1 -1
  67. package/src/core/styles/global.ts +8 -0
  68. package/src/core/types/hooks.ts +1 -0
  69. package/src/core/types/l10n.ts +39 -1
  70. package/src/core/types/sidebar.ts +1 -0
  71. package/src/layouts/ThreePanelLayout.tsx +1 -0
@@ -9,7 +9,7 @@ import { Button } from '@redocly/theme/components/Button/Button';
9
9
  import { useInputKeyCommands, useRecentSearches, useThemeHooks } from '@redocly/theme/core/hooks';
10
10
  import { CloseFilledIcon } from '@redocly/theme/icons/CloseFilledIcon/CloseFilledIcon';
11
11
  import { ChevronLeftIcon } from '@redocly/theme/icons/ChevronLeftIcon/ChevronLeftIcon';
12
- import { getBaseDataAttributes } from '@redocly/theme/core/utils';
12
+ import { breakpoints, getBaseDataAttributes } from '@redocly/theme/core/utils';
13
13
 
14
14
  export type SearchInputProps = {
15
15
  placeholder?: string;
@@ -110,6 +110,11 @@ const SearchInputField = styled.input`
110
110
  &::placeholder {
111
111
  color: var(--search-input-placeholder-color);
112
112
  }
113
+
114
+ // Keep at least 16px on mobile so iOS Safari doesn't auto-zoom the viewport on focus.
115
+ @media screen and (max-width: ${breakpoints.small}) {
116
+ font-size: max(16px, var(--search-input-font-size));
117
+ }
113
118
  `;
114
119
 
115
120
  const ResetButton = styled(Button)`
@@ -4,14 +4,18 @@ import throttle from 'lodash.throttle';
4
4
  import type { Location } from 'react-router-dom';
5
5
 
6
6
  import { useNavbarHeight } from './use-navbar-height';
7
+ import { IS_BROWSER } from '../utils/dom';
7
8
 
8
9
  export type UseActiveSectionIdReturnType = string;
9
10
 
11
+ /** Px below the top where the active section is read (accounts for next-section visibility). */
12
+ export const SECTION_READING_LINE_OFFSET = 150;
13
+
10
14
  export function useActiveSectionId(
11
15
  location: Location,
12
16
  hasOverviewPage = false,
13
17
  withNavbar = true,
14
- sectionOffset = 150, // use 150px to account next section visibility;
18
+ sectionOffset = SECTION_READING_LINE_OFFSET,
15
19
  ): UseActiveSectionIdReturnType {
16
20
  const [itemId, setItemId] = useState<string>('');
17
21
  const navbarHeight = useNavbarHeight(location);
@@ -20,6 +24,10 @@ export function useActiveSectionId(
20
24
  const scrollListener = useMemo(
21
25
  () =>
22
26
  throttle(() => {
27
+ if (!IS_BROWSER) {
28
+ return;
29
+ }
30
+
23
31
  const sections = document.querySelectorAll('[data-section-id]');
24
32
  if (sections.length < 2) {
25
33
  setItemId('');
@@ -47,6 +55,10 @@ export function useActiveSectionId(
47
55
  );
48
56
 
49
57
  useEffect(() => {
58
+ if (!IS_BROWSER) {
59
+ return;
60
+ }
61
+
50
62
  window.addEventListener('scroll', scrollListener, { capture: false });
51
63
  setTimeout(() => {
52
64
  scrollListener();
@@ -55,10 +55,11 @@ export function usePageActions(
55
55
  const themeConfig = useThemeConfig();
56
56
  const pageProps = usePageProps();
57
57
  const telemetry = useTelemetry();
58
- const openApiSharedData = usePageSharedData<
58
+ const apiDocsSharedData = usePageSharedData<
59
59
  { options: { excludeFromSearch: boolean } } | undefined
60
- >('openAPIDocsStore');
61
- const openapiExcludeFromSearch = openApiSharedData?.options?.excludeFromSearch;
60
+ >('apiDocsStore');
61
+ const apiDocsExcludeFromSearch = apiDocsSharedData?.options?.excludeFromSearch;
62
+ const isApiDocsPage = Boolean(apiDocsSharedData);
62
63
  const mcpConfig = useMCPConfig();
63
64
 
64
65
  const { isPublic } = usePageData() || {};
@@ -94,7 +95,8 @@ export function usePageActions(
94
95
  const hideActionContext: ShouldHideActionContext = {
95
96
  pageProps,
96
97
  themeConfig,
97
- openapiExcludeFromSearch,
98
+ apiDocsExcludeFromSearch,
99
+ isApiDocsPage,
98
100
  isPublic,
99
101
  mcpUrl,
100
102
  isMcpDisabled: mcpConfig.isMcpDisabled,
@@ -203,7 +205,8 @@ export function usePageActions(
203
205
  }, [
204
206
  pageProps,
205
207
  themeConfig,
206
- openapiExcludeFromSearch,
208
+ apiDocsExcludeFromSearch,
209
+ isApiDocsPage,
207
210
  isPublic,
208
211
  mcpUrl,
209
212
  mcpConfig.isMcpDisabled,
@@ -273,7 +276,8 @@ function createMCPAction({
273
276
  type ShouldHideActionContext = {
274
277
  pageProps: PageProps;
275
278
  themeConfig: UiAccessibleConfig;
276
- openapiExcludeFromSearch?: boolean;
279
+ apiDocsExcludeFromSearch?: boolean;
280
+ isApiDocsPage: boolean;
277
281
  isPublic?: boolean;
278
282
  mcpUrl?: string;
279
283
  isMcpDisabled: boolean;
@@ -284,7 +288,8 @@ function shouldHideAction(
284
288
  {
285
289
  pageProps,
286
290
  themeConfig,
287
- openapiExcludeFromSearch,
291
+ apiDocsExcludeFromSearch,
292
+ isApiDocsPage,
288
293
  isPublic,
289
294
  mcpUrl,
290
295
  isMcpDisabled,
@@ -307,11 +312,8 @@ function shouldHideAction(
307
312
  return true;
308
313
  }
309
314
 
310
- const isOpenApiPage =
311
- pageProps?.metadata?.type === 'openapi' ||
312
- pageProps?.metadata?.subType === 'openapi-operation';
313
315
  const isPageExcludedFromSearch =
314
- pageProps?.frontmatter?.excludeFromSearch || (isOpenApiPage && openapiExcludeFromSearch);
316
+ pageProps?.frontmatter?.excludeFromSearch || (isApiDocsPage && apiDocsExcludeFromSearch);
315
317
 
316
318
  if (isPageExcludedFromSearch) {
317
319
  return true;
@@ -11,6 +11,7 @@ const fallbacks = {
11
11
  translate: (value?: string, options?: { defaultValue: string } | string) =>
12
12
  (typeof options === 'string' ? options : options?.defaultValue) || value || '',
13
13
  }),
14
+ useTranslationKeys: () => [],
14
15
  useSubmitFeedback: () => ({ submitFeedback: () => {} }),
15
16
  useTelemetry: useTelemetryFallback,
16
17
  /**
@@ -30,7 +30,7 @@ export { getUserAgent } from '../utils/get-user-agent';
30
30
  export { useFocusTrap } from '../hooks/use-focus-trap';
31
31
  export { useThemeHooks } from '../hooks/use-theme-hooks';
32
32
  export { useOutsideClick } from '../hooks/use-outside-click';
33
- export { useActiveSectionId } from '../hooks/use-active-section-id';
33
+ export { useActiveSectionId, SECTION_READING_LINE_OFFSET } from '../hooks/use-active-section-id';
34
34
  export { useModalScrollLock } from '../hooks/use-modal-scroll-lock';
35
35
  export { useSearchDialog } from '../hooks/search/use-search-dialog';
36
36
  export { useDialogHotKeys } from '../hooks/use-dialog-hotkeys';
@@ -833,6 +833,14 @@ const badges = css`
833
833
  --badge-deprecated-bg-color: var(--color-warning-base); // @presenter Color
834
834
  --badge-deprecated-border-radius: var(--border-radius); // @presenter BorderRadius
835
835
 
836
+ /**
837
+ * @tokens Webhook Badge
838
+ */
839
+
840
+ --badge-webhook-text-color: var(--color-warm-grey-1); // @presenter Color
841
+ --badge-webhook-bg-color: var(--color-purple-7); // @presenter Color
842
+ --badge-webhook-border-radius: var(--border-radius); // @presenter BorderRadius
843
+
836
844
  /**
837
845
  * @tokens Audience Badge
838
846
  */
@@ -44,6 +44,7 @@ import { AiSearchError } from '../constants/search';
44
44
  export type ThemeHooks = {
45
45
  useAnchorPositioning: () => { isSupported: boolean };
46
46
  useTranslate: () => { translate: TFunction };
47
+ useTranslationKeys: () => string[];
47
48
  /**
48
49
  * @deprecated use `useL10n` instead
49
50
  * */
@@ -239,6 +239,8 @@ export type TranslationKey =
239
239
  | 'codeSnippet.report.label'
240
240
  | 'codeSnippet.expand.tooltipText'
241
241
  | 'codeSnippet.collapse.tooltipText'
242
+ | 'jsonViewer.showMore'
243
+ | 'jsonViewer.showLess'
242
244
  | 'userMenu.login'
243
245
  | 'userMenu.logout'
244
246
  | 'userMenu.devOnboardingLabel'
@@ -292,6 +294,7 @@ export type TranslationKey =
292
294
  | 'openapi.languages.moreButton.tooltipText'
293
295
  | 'openapi.servers.title'
294
296
  | 'openapi.operations'
297
+ | 'openapi.schemas'
295
298
  | 'openapi.webhooks'
296
299
  | 'openapi.description'
297
300
  | 'openapi.badges.deprecated'
@@ -300,6 +303,7 @@ export type TranslationKey =
300
303
  | 'openapi.request'
301
304
  | 'openapi.path'
302
305
  | 'openapi.query'
306
+ | 'openapi.querystring'
303
307
  | 'openapi.cookie'
304
308
  | 'openapi.header'
305
309
  | 'openapi.body'
@@ -320,6 +324,9 @@ export type TranslationKey =
320
324
  | 'openapi.required'
321
325
  | 'openapi.recursive'
322
326
  | 'openapi.complex'
327
+ | 'openapi.property'
328
+ | 'openapi.properties'
329
+ | 'openapi.details'
323
330
  | 'openapi.hideExample'
324
331
  | 'openapi.showExample'
325
332
  | 'openapi.expandAll'
@@ -332,6 +339,7 @@ export type TranslationKey =
332
339
  | 'openapi.discriminator.defaultMappingTooltip'
333
340
  | 'openapi.noResponseContent'
334
341
  | 'openapi.noRequestPayload'
342
+ | 'openapi.noRequestData'
335
343
  | 'openapi.hidePattern'
336
344
  | 'openapi.showPattern'
337
345
  | 'openapi.authorizationUrl'
@@ -363,6 +371,16 @@ export type TranslationKey =
363
371
  | 'openapi.mcp.outputExample'
364
372
  | 'asyncapi.download.description.title'
365
373
  | 'asyncapi.info.title'
374
+ | 'asyncapi.info.contact.url'
375
+ | 'asyncapi.info.contact.name'
376
+ | 'asyncapi.info.license'
377
+ | 'asyncapi.info.termsOfService'
378
+ | 'asyncapi.key'
379
+ | 'asyncapi.value'
380
+ | 'asyncapi.variables'
381
+ | 'asyncapi.required'
382
+ | 'asyncapi.requiredScopes'
383
+ | 'asyncapi.viewSecurityDetails'
366
384
  | 'graphql.download.description.title'
367
385
  | 'graphql.info.title'
368
386
  | 'graphql.info.contact.url'
@@ -383,6 +401,12 @@ export type TranslationKey =
383
401
  | 'graphql.enums'
384
402
  | 'graphql.inputs'
385
403
  | 'graphql.scalars'
404
+ | 'graphql.actions.show'
405
+ | 'graphql.actions.hide'
406
+ | 'graphql.actions.more'
407
+ | 'graphql.fields'
408
+ | 'graphql.inputFields'
409
+ | 'graphql.values'
386
410
  | 'graphql.arguments.label'
387
411
  | 'graphql.arguments.show'
388
412
  | 'graphql.arguments.hide'
@@ -401,7 +425,21 @@ export type TranslationKey =
401
425
  | 'graphql.implementedBy'
402
426
  | 'graphql.nonNull'
403
427
  | 'graphql.required'
404
- | 'graphql.deprecated'
428
+ | 'asyncapi.badges.deprecated'
429
+ | 'graphql.badges.deprecated'
430
+ | 'asyncapi.actions.show'
431
+ | 'asyncapi.actions.hide'
432
+ | 'asyncapi.actions.more'
433
+ | 'asyncapi.payload'
434
+ | 'asyncapi.parameters'
435
+ | 'asyncapi.messages'
436
+ | 'asyncapi.contentType'
437
+ | 'asyncapi.moreDetails'
438
+ | 'asyncapi.property'
439
+ | 'asyncapi.properties'
440
+ | 'asyncapi.details'
441
+ | 'asyncapi.reply'
442
+ | 'asyncapi.servers.title'
405
443
  | 'graphql.variables'
406
444
  | 'graphql.querySample'
407
445
  | 'graphql.mutationSample'
@@ -40,6 +40,7 @@ export type SidebarNavItem = {
40
40
  linePosition?: 'top' | 'bottom';
41
41
  version?: string;
42
42
  variant?: 'primary' | 'secondary';
43
+ hideWhenEmpty?: boolean;
43
44
  badges?: ItemBadge[];
44
45
  };
45
46
 
@@ -9,6 +9,7 @@ export type ThreePanelLayoutProps = PropsWithChildren<{
9
9
  collapsedSidebar?: boolean;
10
10
  id?: string;
11
11
  className?: string;
12
+ onClickCapture?: React.MouseEventHandler<HTMLDivElement>;
12
13
  }>;
13
14
 
14
15
  export function ThreePanelLayout({