@redocly/theme 0.67.0 → 0.68.0-next.1

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 (64) hide show
  1. package/lib/components/Buttons/ConnectMCPButton.d.ts +1 -1
  2. package/lib/components/Buttons/ConnectMCPButton.js +50 -17
  3. package/lib/components/Buttons/variables.js +3 -0
  4. package/lib/components/Catalog/CatalogEntities.js +2 -11
  5. package/lib/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.js +3 -16
  6. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.d.ts +1 -1
  7. package/lib/components/Catalog/CatalogEntity/CatalogEntitySchema.js +3 -9
  8. package/lib/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.js +1 -7
  9. package/lib/components/Feedback/Feedback.js +4 -1
  10. package/lib/components/Feedback/Reasons.js +2 -3
  11. package/lib/components/Menu/MenuItem.js +2 -1
  12. package/lib/components/Search/SearchAiDialog.js +2 -1
  13. package/lib/components/Search/SearchAiResponse.js +2 -1
  14. package/lib/components/Search/SearchTrigger.js +3 -3
  15. package/lib/core/constants/common.d.ts +1 -0
  16. package/lib/core/constants/common.js +2 -1
  17. package/lib/core/constants/search.d.ts +1 -0
  18. package/lib/core/constants/search.js +2 -1
  19. package/lib/core/hooks/search/use-search-dialog.js +2 -1
  20. package/lib/core/hooks/use-active-heading.js +5 -2
  21. package/lib/core/hooks/use-telemetry-fallback.d.ts +1 -1
  22. package/lib/core/hooks/use-telemetry-fallback.js +1 -1
  23. package/lib/core/styles/dark.js +11 -0
  24. package/lib/core/styles/global.js +36 -34
  25. package/lib/markdoc/components/NumberedList/NumberedItem.d.ts +25 -0
  26. package/lib/markdoc/components/NumberedList/NumberedItem.js +217 -0
  27. package/lib/markdoc/components/NumberedList/NumberedList.d.ts +5 -0
  28. package/lib/markdoc/components/NumberedList/NumberedList.js +28 -0
  29. package/lib/markdoc/components/NumberedList/variables.d.ts +1 -0
  30. package/lib/markdoc/components/NumberedList/variables.js +42 -0
  31. package/lib/markdoc/components/default.d.ts +2 -0
  32. package/lib/markdoc/components/default.js +2 -0
  33. package/lib/markdoc/default.js +4 -0
  34. package/lib/markdoc/tags/numbered-item.d.ts +2 -0
  35. package/lib/markdoc/tags/numbered-item.js +35 -0
  36. package/lib/markdoc/tags/numbered-list.d.ts +2 -0
  37. package/lib/markdoc/tags/numbered-list.js +28 -0
  38. package/package.json +3 -3
  39. package/src/components/Buttons/ConnectMCPButton.tsx +110 -63
  40. package/src/components/Buttons/variables.ts +3 -0
  41. package/src/components/Catalog/CatalogEntities.tsx +7 -11
  42. package/src/components/Catalog/CatalogEntity/CatalogEntityRelations/CatalogEntityRelationsTable.tsx +8 -9
  43. package/src/components/Catalog/CatalogEntity/CatalogEntitySchema.tsx +6 -8
  44. package/src/components/Catalog/CatalogFilter/CatalogFilterCheckboxes.tsx +2 -4
  45. package/src/components/Feedback/Feedback.tsx +11 -1
  46. package/src/components/Feedback/Reasons.tsx +2 -4
  47. package/src/components/Menu/MenuItem.tsx +5 -2
  48. package/src/components/Search/SearchAiDialog.tsx +1 -1
  49. package/src/components/Search/SearchAiResponse.tsx +1 -1
  50. package/src/components/Search/SearchTrigger.tsx +3 -3
  51. package/src/core/constants/common.ts +2 -0
  52. package/src/core/constants/search.ts +2 -0
  53. package/src/core/hooks/search/use-search-dialog.ts +2 -1
  54. package/src/core/hooks/use-active-heading.ts +7 -2
  55. package/src/core/hooks/use-telemetry-fallback.ts +1 -1
  56. package/src/core/styles/dark.ts +12 -0
  57. package/src/core/styles/global.ts +2 -0
  58. package/src/markdoc/components/NumberedList/NumberedItem.tsx +274 -0
  59. package/src/markdoc/components/NumberedList/NumberedList.tsx +37 -0
  60. package/src/markdoc/components/NumberedList/variables.ts +39 -0
  61. package/src/markdoc/components/default.ts +2 -0
  62. package/src/markdoc/default.ts +4 -0
  63. package/src/markdoc/tags/numbered-item.ts +46 -0
  64. package/src/markdoc/tags/numbered-list.ts +34 -0
@@ -0,0 +1,274 @@
1
+ import React, { createElement } from 'react';
2
+ import styled, { css } from 'styled-components';
3
+
4
+ import type { JSX, PropsWithChildren, ReactNode } from 'react';
5
+
6
+ import { GenericIcon } from '@redocly/theme/icons/GenericIcon/GenericIcon';
7
+ import { LinkIcon } from '@redocly/theme/icons/LinkIcon/LinkIcon';
8
+
9
+ export const NumberedListType = {
10
+ ICON: 'icon',
11
+ NUMBER: 'number',
12
+ DOT: 'dot',
13
+ } as const;
14
+
15
+ export type NumberedListType = (typeof NumberedListType)[keyof typeof NumberedListType];
16
+
17
+ export const NumberedListSize = {
18
+ SMALL: 'small',
19
+ MEDIUM: 'medium',
20
+ } as const;
21
+
22
+ export type NumberedListSize = (typeof NumberedListSize)[keyof typeof NumberedListSize];
23
+
24
+ export type NumberedItemProps = PropsWithChildren<{
25
+ headline?: ReactNode;
26
+ anchorId?: string;
27
+ headlineLevel?: number;
28
+ icon?: string | ReactNode;
29
+ /* Internal use only: raw SVG content resolved for relative `.svg` icons */
30
+ iconRawContent?: string;
31
+ className?: string;
32
+ /* Injected by the parent NumberedList component */
33
+ type?: NumberedListType;
34
+ size?: NumberedListSize;
35
+ index?: number;
36
+ isLast?: boolean;
37
+ }>;
38
+
39
+ export function NumberedItem({
40
+ headline,
41
+ anchorId,
42
+ headlineLevel,
43
+ icon,
44
+ iconRawContent,
45
+ className,
46
+ type = NumberedListType.NUMBER,
47
+ size = NumberedListSize.MEDIUM,
48
+ index = 1,
49
+ isLast = true,
50
+ children,
51
+ }: NumberedItemProps): JSX.Element {
52
+ const isDot = type === NumberedListType.DOT;
53
+ const headlineTextId = anchorId ? `${anchorId}-heading-text` : undefined;
54
+
55
+ const marker = (
56
+ <Marker $type={type} $size={size} data-dot={isDot || undefined}>
57
+ {type === NumberedListType.ICON && (
58
+ <MarkerContent className="numbered-item-marker-content">
59
+ <GenericIcon icon={icon} rawContent={iconRawContent} />
60
+ </MarkerContent>
61
+ )}
62
+ {type === NumberedListType.NUMBER && (
63
+ <MarkerContent className="numbered-item-marker-content">{index}</MarkerContent>
64
+ )}
65
+ {anchorId && (
66
+ <MarkerLink className="numbered-item-marker-link" $isDot={isDot}>
67
+ <MarkerLinkIcon
68
+ aria-hidden="true"
69
+ focusable="false"
70
+ color="--md-numbered-list-marker-text-color"
71
+ />
72
+ </MarkerLink>
73
+ )}
74
+ </Marker>
75
+ );
76
+
77
+ return (
78
+ <NumberedItemWrapper
79
+ data-component-name="Markdoc/NumberedList/NumberedItem"
80
+ className={className}
81
+ id={anchorId}
82
+ $size={size}
83
+ $isDot={isDot}
84
+ >
85
+ <MarkerRail>
86
+ {anchorId ? (
87
+ <a
88
+ href={`#${anchorId}`}
89
+ {...(headline
90
+ ? { 'aria-labelledby': headlineTextId }
91
+ : { 'aria-label': 'Link to this item' })}
92
+ >
93
+ {marker}
94
+ </a>
95
+ ) : (
96
+ marker
97
+ )}
98
+ <Tail data-testid="numbered-item-tail" $isLast={isLast} />
99
+ </MarkerRail>
100
+ <NumberedItemContent>
101
+ {headline &&
102
+ createElement(
103
+ NumberedItemHeadline,
104
+ { as: `h${headlineLevel ?? 3}` as keyof JSX.IntrinsicElements, id: headlineTextId },
105
+ headline,
106
+ )}
107
+ <NumberedItemBody>{children}</NumberedItemBody>
108
+ </NumberedItemContent>
109
+ </NumberedItemWrapper>
110
+ );
111
+ }
112
+
113
+ const markerSize = css<{ $size?: string }>`
114
+ ${({ $size }) =>
115
+ $size === NumberedListSize.SMALL
116
+ ? css`
117
+ width: var(--md-numbered-list-marker-small-size);
118
+ height: var(--md-numbered-list-marker-small-size);
119
+ --icon-width: var(--md-numbered-list-icon-small-size);
120
+ --icon-height: var(--md-numbered-list-icon-small-size);
121
+ `
122
+ : css`
123
+ width: var(--md-numbered-list-marker-medium-size);
124
+ height: var(--md-numbered-list-marker-medium-size);
125
+ --icon-width: var(--md-numbered-list-icon-medium-size);
126
+ --icon-height: var(--md-numbered-list-icon-medium-size);
127
+ `}
128
+ `;
129
+
130
+ const Marker = styled.span<{ $type: string; $size: string }>`
131
+ position: relative;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ flex-shrink: 0;
136
+ border-radius: 50%;
137
+ color: var(--md-numbered-list-marker-text-color);
138
+ font-size: var(--md-numbered-list-marker-font-size);
139
+
140
+ ${({ $type }) =>
141
+ $type === NumberedListType.DOT
142
+ ? css`
143
+ width: var(--md-numbered-list-dot-size);
144
+ height: var(--md-numbered-list-dot-size);
145
+ background-color: var(--text-color-primary);
146
+ `
147
+ : css`
148
+ ${markerSize}
149
+ background-color: var(--md-numbered-list-marker-bg-color);
150
+ `}
151
+ `;
152
+
153
+ const MarkerContent = styled.span`
154
+ display: flex;
155
+ align-items: center;
156
+ justify-content: center;
157
+ `;
158
+
159
+ const MarkerLink = styled.span<{ $isDot?: boolean }>`
160
+ display: none;
161
+ align-items: center;
162
+ justify-content: center;
163
+
164
+ svg {
165
+ width: var(--icon-width, 16px);
166
+ height: var(--icon-height, 16px);
167
+ }
168
+
169
+ ${({ $isDot }) =>
170
+ $isDot &&
171
+ css`
172
+ position: absolute;
173
+ inset-inline-end: calc(100% + var(--md-numbered-list-dot-link-gap));
174
+ `}
175
+ `;
176
+
177
+ const MarkerLinkIcon = styled(LinkIcon)`
178
+ path:first-of-type {
179
+ fill: var(--md-numbered-list-marker-icon-bg-color);
180
+ }
181
+ `;
182
+
183
+ const MarkerRail = styled.span`
184
+ display: flex;
185
+ flex-direction: column;
186
+ align-items: center;
187
+ align-self: stretch;
188
+ flex-shrink: 0;
189
+
190
+ a {
191
+ display: flex;
192
+ border-radius: 50%;
193
+ /* Overrides the global markdown link rule a:not([role='button']), which is more specific. */
194
+ text-decoration: none !important;
195
+
196
+ &:hover,
197
+ &:focus {
198
+ text-decoration: none !important;
199
+ }
200
+ }
201
+ `;
202
+
203
+ const Tail = styled.span<{ $isLast: boolean }>`
204
+ flex: 1 0 0;
205
+ min-height: var(--spacing-xs);
206
+ width: var(--md-numbered-list-tail-width);
207
+ background: ${({ $isLast }) =>
208
+ $isLast
209
+ ? 'var(--md-numbered-list-tail-fade-gradient)'
210
+ : 'var(--md-numbered-list-tail-bg-color)'};
211
+ `;
212
+
213
+ const NumberedItemHeadline = styled.h3`
214
+ margin: 0;
215
+ color: var(--md-numbered-list-headline-text-color);
216
+ font-size: var(--md-numbered-list-headline-font-size);
217
+ font-weight: var(--md-numbered-list-headline-font-weight);
218
+ line-height: var(--md-numbered-list-headline-line-height);
219
+ `;
220
+
221
+ const NumberedItemBody = styled.div`
222
+ display: flex;
223
+ flex-direction: column;
224
+ gap: var(--md-numbered-list-body-gap);
225
+ color: var(--md-numbered-list-body-text-color);
226
+ font-size: var(--md-numbered-list-body-font-size);
227
+
228
+ > p {
229
+ margin: 0;
230
+ }
231
+ `;
232
+
233
+ const NumberedItemContent = styled.div`
234
+ display: flex;
235
+ flex-direction: column;
236
+ gap: var(--spacing-unit);
237
+ flex: 1;
238
+ min-width: 0;
239
+ padding-bottom: var(--spacing-sm);
240
+ `;
241
+
242
+ const NumberedItemWrapper = styled.li<{ $size?: string; $isDot?: boolean }>`
243
+ display: flex;
244
+ gap: var(--md-numbered-list-gap);
245
+ align-items: stretch;
246
+
247
+ ${({ $isDot }) =>
248
+ $isDot &&
249
+ css`
250
+ ${MarkerRail} {
251
+ padding-top: var(--md-numbered-list-dot-rail-padding-top);
252
+ }
253
+ `}
254
+
255
+ &:last-child ${NumberedItemContent} {
256
+ padding-bottom: 0;
257
+ }
258
+
259
+ &:hover,
260
+ &:focus-within {
261
+ ${Marker} {
262
+ background-color: ${({ $isDot }) =>
263
+ $isDot ? 'var(--text-color-primary)' : 'var(--md-numbered-list-marker-bg-color-hover)'};
264
+ }
265
+
266
+ a ${Marker}:not([data-dot]) .numbered-item-marker-content {
267
+ display: none;
268
+ }
269
+
270
+ a ${Marker} .numbered-item-marker-link {
271
+ display: flex;
272
+ }
273
+ }
274
+ `;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import type { JSX, PropsWithChildren } from 'react';
5
+
6
+ export type NumberedListProps = PropsWithChildren<{
7
+ className?: string;
8
+ }>;
9
+
10
+ export function NumberedList({ className, children }: NumberedListProps): JSX.Element | null {
11
+ if (React.Children.count(children) === 0) {
12
+ return null;
13
+ }
14
+
15
+ return (
16
+ <NumberedListWrapper
17
+ data-component-name="Markdoc/NumberedList/NumberedList"
18
+ className={className}
19
+ >
20
+ {children}
21
+ </NumberedListWrapper>
22
+ );
23
+ }
24
+
25
+ const NumberedListWrapper = styled.ol`
26
+ display: flex;
27
+ flex-direction: column;
28
+ margin: var(--md-numbered-list-margin);
29
+ padding: 0;
30
+ list-style: none;
31
+
32
+ && {
33
+ & > li:not(:last-child) {
34
+ margin-bottom: 0;
35
+ }
36
+ }
37
+ `;
@@ -0,0 +1,39 @@
1
+ import { css } from 'styled-components';
2
+
3
+ export const markdownNumberedList = css`
4
+ /**
5
+ * @tokens Markdown Numbered List
6
+ */
7
+
8
+ --md-numbered-list-margin: var(--spacing-sm) 0; // @presenter Spacing
9
+ --md-numbered-list-gap: var(--spacing-base); // @presenter Spacing
10
+
11
+ --md-numbered-list-marker-bg-color: var(--color-warm-grey-2); // @presenter Color
12
+ --md-numbered-list-marker-bg-color-hover: var(--color-warm-grey-3); // @presenter Color
13
+ --md-numbered-list-marker-icon-bg-color: transparent; // @presenter Color
14
+ --md-numbered-list-marker-text-color: var(--text-color-primary); // @presenter Color
15
+ --md-numbered-list-marker-font-size: var(--font-size-base); // @presenter FontSize
16
+
17
+ --md-numbered-list-marker-medium-size: 28px; // @presenter Spacing
18
+ --md-numbered-list-icon-medium-size: 16px; // @presenter Spacing
19
+ --md-numbered-list-tail-width: 1px; // @presenter Spacing
20
+ --md-numbered-list-marker-small-size: 24px; // @presenter Spacing
21
+ --md-numbered-list-icon-small-size: 12px; // @presenter Spacing
22
+ --md-numbered-list-dot-size: 10px; // @presenter Spacing
23
+ --md-numbered-list-dot-rail-padding-top: 7px; // @presenter Spacing
24
+ --md-numbered-list-dot-link-gap: 6px; // @presenter Spacing
25
+
26
+ --md-numbered-list-tail-bg-color: var(--md-numbered-list-marker-bg-color); // @presenter Color
27
+ --md-numbered-list-tail-fade-gradient: linear-gradient(to bottom, var(--md-numbered-list-tail-bg-color), transparent); // @presenter Color
28
+
29
+ --md-numbered-list-headline-text-color: var(--text-color-primary); // @presenter Color
30
+ --md-numbered-list-headline-font-size: var(--font-size-base); // @presenter FontSize
31
+ --md-numbered-list-headline-font-weight: var(--font-weight-medium); // @presenter FontWeight
32
+ --md-numbered-list-headline-line-height: var(--line-height-base); // @presenter LineHeight
33
+
34
+ --md-numbered-list-body-text-color: var(--text-color-secondary); // @presenter Color
35
+ --md-numbered-list-body-gap: var(--spacing-xs); // @presenter Spacing
36
+ --md-numbered-list-body-font-size: var(--font-size-base); // @presenter FontSize
37
+
38
+ // @tokens End
39
+ `;
@@ -8,6 +8,8 @@ export * from '@redocly/theme/markdoc/components/Tabs/TabItemFragment';
8
8
  export * from '@redocly/theme/markdoc/components/Tabs/Tab';
9
9
  export * from '@redocly/theme/markdoc/components/Tabs/TabList';
10
10
  export * from '@redocly/theme/markdoc/components/Tabs/Tabs';
11
+ export * from '@redocly/theme/markdoc/components/NumberedList/NumberedItem';
12
+ export * from '@redocly/theme/markdoc/components/NumberedList/NumberedList';
11
13
  export * from '@redocly/theme/markdoc/components/CodeBlock/CodeBlock';
12
14
  export * from '@redocly/theme/markdoc/components/Cards/Cards';
13
15
  export * from '@redocly/theme/markdoc/components/Cards/Card';
@@ -14,6 +14,8 @@ import { markdocExample } from '@redocly/theme/markdoc/tags/markdoc-example';
14
14
  import { partial } from '@redocly/theme/markdoc/tags/partial';
15
15
  import { tab } from '@redocly/theme/markdoc/tags/tab';
16
16
  import { tabs } from '@redocly/theme/markdoc/tags/tabs';
17
+ import { numberedItem } from '@redocly/theme/markdoc/tags/numbered-item';
18
+ import { numberedList } from '@redocly/theme/markdoc/tags/numbered-list';
17
19
  import { debug } from '@redocly/theme/markdoc/tags/debug';
18
20
  import { codeSnippet } from '@redocly/theme/markdoc/tags/code-snippet';
19
21
  import { inlineSvg } from '@redocly/theme/markdoc/tags/inline-svg';
@@ -38,6 +40,8 @@ export const tags = {
38
40
  [partial.tagName]: partial.schema,
39
41
  [tab.tagName]: tab.schema,
40
42
  [tabs.tagName]: tabs.schema,
43
+ [numberedItem.tagName]: numberedItem.schema,
44
+ [numberedList.tagName]: numberedList.schema,
41
45
  [codeSnippet.tagName]: codeSnippet.schema,
42
46
  [inlineSvg.tagName]: inlineSvg.schema,
43
47
  [cards.tagName]: cards.schema,
@@ -0,0 +1,46 @@
1
+ import markdoc from '@markdoc/markdoc';
2
+
3
+ import type { MarkdocSchemaWrapper } from '@redocly/theme/markdoc/tags/types';
4
+
5
+ import { isTag } from '@redocly/theme/core/utils';
6
+
7
+ const HEADING_TAG_NAME = /^(Heading|h[1-6])$/;
8
+
9
+ export const numberedItem: MarkdocSchemaWrapper = {
10
+ schema: {
11
+ transform(node, config) {
12
+ const attributes = node.transformAttributes(config);
13
+ const children = node.transformChildren(config);
14
+ const [first, ...body] = children;
15
+
16
+ if (isTag(first) && HEADING_TAG_NAME.test(String(first.name))) {
17
+ const headlineLevel =
18
+ typeof first.attributes.level === 'number'
19
+ ? first.attributes.level
20
+ : Number(String(first.name).slice(1)) || undefined;
21
+
22
+ return new markdoc.Tag(
23
+ 'NumberedItem',
24
+ {
25
+ ...attributes,
26
+ headline: first.children,
27
+ anchorId: first.attributes.id,
28
+ headlineLevel,
29
+ },
30
+ body,
31
+ );
32
+ }
33
+
34
+ return new markdoc.Tag('NumberedItem', attributes, children);
35
+ },
36
+ attributes: {
37
+ icon: { type: String, resolver: 'relativeOrCdnIcon' },
38
+ iconRawContent: {
39
+ // internal use only
40
+ type: String,
41
+ render: true,
42
+ },
43
+ },
44
+ },
45
+ tagName: 'numbered-item',
46
+ };
@@ -0,0 +1,34 @@
1
+ import markdoc from '@markdoc/markdoc';
2
+
3
+ import type { Tag } from '@markdoc/markdoc';
4
+ import type { MarkdocSchemaWrapper } from '@redocly/theme/markdoc/tags/types';
5
+
6
+ import { isTag } from '@redocly/theme/core/utils';
7
+
8
+ export const numberedList: MarkdocSchemaWrapper = {
9
+ schema: {
10
+ transform(node, config) {
11
+ const attributes = node.transformAttributes(config);
12
+ const items = node
13
+ .transformChildren(config)
14
+ .filter((child): child is Tag => isTag(child) && child.name === 'NumberedItem');
15
+
16
+ items.forEach((item, index) => {
17
+ item.attributes = {
18
+ ...item.attributes,
19
+ type: attributes.type,
20
+ size: attributes.size,
21
+ index: index + 1,
22
+ isLast: index === items.length - 1,
23
+ };
24
+ });
25
+
26
+ return new markdoc.Tag('NumberedList', attributes, items);
27
+ },
28
+ attributes: {
29
+ type: { type: String, matches: ['icon', 'number', 'dot'], default: 'number' },
30
+ size: { type: String, matches: ['small', 'medium'], default: 'medium' },
31
+ },
32
+ },
33
+ tagName: 'numbered-list',
34
+ };