@redocly/theme 0.48.0 → 0.48.2

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 (98) hide show
  1. package/lib/components/DatePicker/variables.js +1 -1
  2. package/lib/components/Feedback/Mood.js +14 -9
  3. package/lib/components/Search/SearchDialog.js +9 -3
  4. package/lib/components/Search/variables.js +4 -0
  5. package/lib/components/Segmented/Segmented.d.ts +4 -4
  6. package/lib/components/Segmented/Segmented.js +4 -7
  7. package/lib/components/Tag/Tag.d.ts +1 -0
  8. package/lib/components/Tag/Tag.js +3 -2
  9. package/lib/core/contexts/CodeWalkthrough/CodeWalkthroughControlsContext.js +2 -6
  10. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.d.ts +7 -10
  11. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +63 -97
  12. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.d.ts +1 -2
  13. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-steps.js +20 -15
  14. package/lib/core/hooks/code-walkthrough/use-code-walkthrough.d.ts +2 -7
  15. package/lib/core/hooks/code-walkthrough/use-code-walkthrough.js +10 -3
  16. package/lib/core/hooks/code-walkthrough/use-renderable-files.d.ts +9 -0
  17. package/lib/core/hooks/code-walkthrough/use-renderable-files.js +28 -0
  18. package/lib/core/hooks/index.d.ts +1 -0
  19. package/lib/core/hooks/index.js +1 -0
  20. package/lib/core/styles/global.js +18 -0
  21. package/lib/core/types/l10n.d.ts +1 -1
  22. package/lib/core/utils/download-code-walkthrough.d.ts +4 -2
  23. package/lib/core/utils/download-code-walkthrough.js +9 -1
  24. package/lib/core/utils/find-closest-common-directory.d.ts +6 -0
  25. package/lib/core/utils/find-closest-common-directory.js +51 -0
  26. package/lib/core/utils/get-code-walkthrough-file-text.d.ts +4 -2
  27. package/lib/core/utils/get-file-icon.js +6 -0
  28. package/lib/core/utils/index.d.ts +1 -0
  29. package/lib/core/utils/index.js +1 -0
  30. package/lib/core/utils/replace-inputs-with-value.d.ts +1 -1
  31. package/lib/core/utils/replace-inputs-with-value.js +9 -10
  32. package/lib/icons/DocumentJavaIcon/DocumentJavaIcon.d.ts +9 -0
  33. package/lib/icons/DocumentJavaIcon/DocumentJavaIcon.js +22 -0
  34. package/lib/icons/DocumentJavaIcon/index.d.ts +1 -0
  35. package/lib/icons/DocumentJavaIcon/index.js +6 -0
  36. package/lib/icons/DocumentPythonIcon/DocumentPythonIcon.d.ts +9 -0
  37. package/lib/icons/DocumentPythonIcon/DocumentPythonIcon.js +23 -0
  38. package/lib/icons/DocumentPythonIcon/index.d.ts +1 -0
  39. package/lib/icons/DocumentPythonIcon/index.js +6 -0
  40. package/lib/icons/DocumentShellIcon/DocumentShellIcon.d.ts +9 -0
  41. package/lib/icons/DocumentShellIcon/DocumentShellIcon.js +22 -0
  42. package/lib/icons/DocumentShellIcon/index.d.ts +1 -0
  43. package/lib/icons/DocumentShellIcon/index.js +6 -0
  44. package/lib/icons/__tests__/IconTestUtils.d.ts +7 -0
  45. package/lib/icons/__tests__/IconTestUtils.js +33 -0
  46. package/lib/layouts/CodeWalkthroughLayout.js +4 -1
  47. package/lib/markdoc/components/CodeWalkthrough/CodeContainer.js +25 -4
  48. package/lib/markdoc/components/CodeWalkthrough/CodeFilters.d.ts +5 -4
  49. package/lib/markdoc/components/CodeWalkthrough/CodeFilters.js +15 -2
  50. package/lib/markdoc/components/CodeWalkthrough/CodePanel.js +1 -1
  51. package/lib/markdoc/components/CodeWalkthrough/CodePanelHeader.js +29 -23
  52. package/lib/markdoc/components/CodeWalkthrough/CodePanelPreview.js +1 -1
  53. package/lib/markdoc/components/CodeWalkthrough/CodePanelToolbar.js +1 -1
  54. package/lib/markdoc/components/CodeWalkthrough/CodeStep.js +5 -2
  55. package/lib/markdoc/components/CodeWalkthrough/CodeToggle.js +5 -5
  56. package/lib/markdoc/components/CodeWalkthrough/CodeWalkthrough.js +3 -3
  57. package/lib/markdoc/components/CodeWalkthrough/Input.js +7 -5
  58. package/lib/markdoc/tags/code-walkthrough.js +5 -0
  59. package/package.json +3 -3
  60. package/src/components/DatePicker/variables.ts +1 -1
  61. package/src/components/Feedback/Mood.tsx +16 -7
  62. package/src/components/Search/SearchDialog.tsx +52 -36
  63. package/src/components/Search/variables.ts +4 -0
  64. package/src/components/Segmented/Segmented.tsx +10 -10
  65. package/src/components/Tag/Tag.tsx +1 -1
  66. package/src/core/contexts/CodeWalkthrough/CodeWalkthroughControlsContext.tsx +2 -8
  67. package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +90 -142
  68. package/src/core/hooks/code-walkthrough/use-code-walkthrough-steps.ts +30 -18
  69. package/src/core/hooks/code-walkthrough/use-code-walkthrough.ts +13 -13
  70. package/src/core/hooks/code-walkthrough/use-renderable-files.ts +51 -0
  71. package/src/core/hooks/index.ts +1 -0
  72. package/src/core/styles/global.ts +18 -0
  73. package/src/core/types/l10n.ts +3 -1
  74. package/src/core/utils/download-code-walkthrough.ts +16 -4
  75. package/src/core/utils/find-closest-common-directory.ts +51 -0
  76. package/src/core/utils/get-code-walkthrough-file-text.ts +3 -3
  77. package/src/core/utils/get-file-icon.ts +7 -0
  78. package/src/core/utils/index.ts +1 -0
  79. package/src/core/utils/replace-inputs-with-value.ts +12 -9
  80. package/src/icons/DocumentJavaIcon/DocumentJavaIcon.tsx +33 -0
  81. package/src/icons/DocumentJavaIcon/index.ts +1 -0
  82. package/src/icons/DocumentPythonIcon/DocumentPythonIcon.tsx +37 -0
  83. package/src/icons/DocumentPythonIcon/index.ts +1 -0
  84. package/src/icons/DocumentShellIcon/DocumentShellIcon.tsx +33 -0
  85. package/src/icons/DocumentShellIcon/index.ts +1 -0
  86. package/src/icons/__tests__/IconTestUtils.tsx +31 -0
  87. package/src/layouts/CodeWalkthroughLayout.tsx +5 -1
  88. package/src/markdoc/components/CodeWalkthrough/CodeContainer.tsx +28 -3
  89. package/src/markdoc/components/CodeWalkthrough/CodeFilters.tsx +21 -4
  90. package/src/markdoc/components/CodeWalkthrough/CodePanel.tsx +1 -1
  91. package/src/markdoc/components/CodeWalkthrough/CodePanelHeader.tsx +64 -47
  92. package/src/markdoc/components/CodeWalkthrough/CodePanelPreview.tsx +1 -1
  93. package/src/markdoc/components/CodeWalkthrough/CodePanelToolbar.tsx +1 -1
  94. package/src/markdoc/components/CodeWalkthrough/CodeStep.tsx +5 -1
  95. package/src/markdoc/components/CodeWalkthrough/CodeToggle.tsx +5 -5
  96. package/src/markdoc/components/CodeWalkthrough/CodeWalkthrough.tsx +11 -5
  97. package/src/markdoc/components/CodeWalkthrough/Input.tsx +8 -6
  98. package/src/markdoc/tags/code-walkthrough.ts +5 -0
@@ -27,7 +27,6 @@ exports.CodePanelHeader = CodePanelHeader;
27
27
  const react_1 = __importStar(require("react"));
28
28
  const styled_components_1 = __importStar(require("styled-components"));
29
29
  const hooks_1 = require("../../../core/hooks");
30
- const utils_1 = require("../../../core/utils");
31
30
  const OverflowMenuVerticalIcon_1 = require("../../../icons/OverflowMenuVerticalIcon/OverflowMenuVerticalIcon");
32
31
  const Dropdown_1 = require("../../../components/Dropdown/Dropdown");
33
32
  const DropdownMenu_1 = require("../../../components/Dropdown/DropdownMenu");
@@ -35,6 +34,7 @@ const DropdownMenuItem_1 = require("../../../components/Dropdown/DropdownMenuIte
35
34
  const DownloadIcon_1 = require("../../../icons/DownloadIcon/DownloadIcon");
36
35
  const Button_1 = require("../../../components/Button/Button");
37
36
  function CodePanelHeader({ files, handleTabSwitch, activeTabName, onDownloadCode, }) {
37
+ const renderableFiles = (0, hooks_1.useRenderableFiles)(files);
38
38
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
39
39
  const { translate } = useTranslate();
40
40
  const tabRefs = (0, react_1.useRef)([]);
@@ -42,47 +42,49 @@ function CodePanelHeader({ files, handleTabSwitch, activeTabName, onDownloadCode
42
42
  const [hiddenFiles, setHiddenFiles] = (0, react_1.useState)([]);
43
43
  (0, react_1.useEffect)(() => {
44
44
  const activeTab = tabRefs.current.find((tab) => (tab === null || tab === void 0 ? void 0 : tab.dataset.name) === activeTabName);
45
- if (activeTab) {
46
- activeTab.scrollIntoView({ block: 'nearest', inline: 'center' });
45
+ const tabsWrapper = tabsWrapperRef.current;
46
+ if (activeTab && tabsWrapper) {
47
+ const { left: wrapperLeft, right: wrapperRight } = tabsWrapper.getBoundingClientRect();
48
+ const { left: tabLeft, right: tabRight } = activeTab.getBoundingClientRect();
49
+ const tabHidden = tabLeft < wrapperLeft || tabRight > wrapperRight;
50
+ if (tabHidden) {
51
+ activeTab.scrollIntoView({ block: 'nearest', inline: 'nearest' });
52
+ }
47
53
  }
48
- }, [activeTabName]);
49
- (0, react_1.useEffect)(() => {
50
54
  const calculateHiddenFiles = () => {
51
55
  if (!tabsWrapperRef.current)
52
56
  return;
53
57
  const { left: wrapperLeft, right: wrapperRight } = tabsWrapperRef.current.getBoundingClientRect();
54
- const hidden = files.filter((_, i) => {
58
+ const hidden = [];
59
+ for (let i = 0; i < renderableFiles.length; i++) {
55
60
  const tab = tabRefs.current[i];
56
61
  if (!tab)
57
- return false;
62
+ continue;
58
63
  const { left: tabLeft, right: tabRight } = tab.getBoundingClientRect();
59
- return tabLeft < wrapperLeft || tabRight > wrapperRight;
60
- });
64
+ const visible = tabLeft > wrapperLeft && tabRight < wrapperRight;
65
+ if (!visible) {
66
+ hidden.push(renderableFiles[i]);
67
+ }
68
+ }
61
69
  setHiddenFiles(hidden);
62
70
  };
63
71
  calculateHiddenFiles();
64
72
  window.addEventListener('resize', calculateHiddenFiles);
65
73
  return () => window.removeEventListener('resize', calculateHiddenFiles);
66
- }, [files]);
67
- const getFileTypeIcon = (0, react_1.useCallback)((basename) => {
68
- var _a;
69
- const extension = ((_a = basename.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
70
- return (0, utils_1.getFileIconByExt)(extension);
71
- }, []);
74
+ }, [activeTabName, files, renderableFiles]);
72
75
  return (react_1.default.createElement(CodePanelHeaderWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelHeader" },
73
76
  react_1.default.createElement(TabsWrapper, { ref: tabsWrapperRef },
74
- react_1.default.createElement(Tabs, null, files.map(({ path, basename }, i) => {
75
- const FileIcon = getFileTypeIcon(basename);
77
+ react_1.default.createElement(Tabs, null, renderableFiles.map(({ path, basename, FileIcon, parentFolder, isNameDuplicate, inRootDir }, i) => {
76
78
  return (react_1.default.createElement(Tab, { ref: (el) => (tabRefs.current[i] = el), "data-name": path, active: path === activeTabName, key: i, onClick: () => handleTabSwitch(path) },
77
79
  react_1.default.createElement(FileIcon, null),
78
- basename));
80
+ basename,
81
+ isNameDuplicate && !inRootDir ? react_1.default.createElement(Dirname, null, parentFolder) : null));
79
82
  })),
80
83
  react_1.default.createElement(Gradient, null)),
81
84
  react_1.default.createElement(ActionBar, null,
82
85
  hiddenFiles.length ? (react_1.default.createElement(Dropdown_1.Dropdown, { trigger: react_1.default.createElement(StyledOverflowMenuVerticalIcon, { size: "14px" }), alignment: "end" },
83
- react_1.default.createElement(StyledDropdownMenu, null, hiddenFiles.map(({ path, basename }, i) => {
84
- const FileIcon = getFileTypeIcon(basename);
85
- return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { active: path === activeTabName, key: i, onAction: () => handleTabSwitch(path), prefix: react_1.default.createElement(FileIcon, null), content: basename }));
86
+ react_1.default.createElement(StyledDropdownMenu, null, hiddenFiles.map(({ path, basename, FileIcon, isNameDuplicate, inRootDir, parentFolder }, i) => {
87
+ return (react_1.default.createElement(DropdownMenuItem_1.DropdownMenuItem, { active: path === activeTabName, key: i, onAction: () => handleTabSwitch(path), prefix: react_1.default.createElement(FileIcon, null), content: isNameDuplicate && !inRootDir ? `${parentFolder}/${basename}` : basename }));
86
88
  })))) : null,
87
89
  react_1.default.createElement(Button_1.Button, { variant: "text", icon: react_1.default.createElement(DownloadIcon_1.DownloadIcon, null), onClick: onDownloadCode, size: "small" }, translate('codeWalkthrough.download', 'Download')))));
88
90
  }
@@ -108,13 +110,17 @@ const Gradient = styled_components_1.default.div `
108
110
  `;
109
111
  const Tabs = styled_components_1.default.div `
110
112
  display: flex;
111
- overflow-x: auto;
113
+ overflow-x: hidden;
112
114
  padding-right: var(--spacing-base);
113
115
 
114
116
  &::-webkit-scrollbar {
115
117
  display: none;
116
118
  }
117
119
  `;
120
+ const Dirname = styled_components_1.default.span `
121
+ font-size: var(--font-size-sm);
122
+ color: var(--text-color-description);
123
+ `;
118
124
  const ActionBar = styled_components_1.default.div `
119
125
  display: flex;
120
126
  `;
@@ -129,7 +135,7 @@ const Tab = styled_components_1.default.button `
129
135
  gap: var(--spacing-xs);
130
136
  color: var(--text-color-secondary);
131
137
  white-space: nowrap;
132
-
138
+ scroll-margin-right: var(--spacing-base);
133
139
  ${({ active }) => active
134
140
  ? (0, styled_components_1.css) `
135
141
  color: var(--text-color-primary);
@@ -36,7 +36,7 @@ function CodePanelPreview({ children }) {
36
36
  const [isOpen, setIsOpen] = (0, react_1.useState)(false);
37
37
  const { useTranslate } = (0, hooks_1.useThemeHooks)();
38
38
  const { translate } = useTranslate();
39
- return (react_1.default.createElement(CodePanelPreviewWrapper, null,
39
+ return (react_1.default.createElement(CodePanelPreviewWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelPreview" },
40
40
  react_1.default.createElement(PreviewDropdown, { onClick: () => setIsOpen(!isOpen) },
41
41
  translate('codeWalkthrough.preview', 'Preview'),
42
42
  isOpen ? react_1.default.createElement(ChevronUpIcon_1.ChevronUpIcon, null) : react_1.default.createElement(ChevronDownIcon_1.ChevronDownIcon, null)),
@@ -34,7 +34,7 @@ const CopyButton_1 = require("../../../components/Buttons/CopyButton");
34
34
  function CodePanelToolbar({ file }) {
35
35
  const { getFileText } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
36
36
  const fileContent = getFileText(file);
37
- return (react_1.default.createElement(CodeToolbarWrapper, null,
37
+ return (react_1.default.createElement(CodeToolbarWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodePanelToolbar" },
38
38
  react_1.default.createElement(CopyButton_1.CopyButton, { data: fileContent, type: "compound", variant: "secondary", size: "medium" })));
39
39
  }
40
40
  const CodeToolbarWrapper = styled_components_1.default.div `
@@ -71,7 +71,7 @@ function CodeStep({ id, heading, stepKey, when, unless, children, }) {
71
71
  }
72
72
  const filtersElementHeight = ((_a = filtersElementRef === null || filtersElementRef === void 0 ? void 0 : filtersElementRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight) || 0;
73
73
  const navbarHeight = ((_b = document.querySelector('nav')) === null || _b === void 0 ? void 0 : _b.clientHeight) || 0;
74
- setScrollMarginTop(filtersElementHeight + navbarHeight);
74
+ setScrollMarginTop(filtersElementHeight + navbarHeight + 10);
75
75
  return () => {
76
76
  if (currentCompRef) {
77
77
  unregister(currentCompRef);
@@ -79,9 +79,12 @@ function CodeStep({ id, heading, stepKey, when, unless, children, }) {
79
79
  };
80
80
  }, [activeStep, register, unregister, filtersElementRef]);
81
81
  if (!areConditionsMet({ when, unless })) {
82
+ if (isActive) {
83
+ setActiveStep(null);
84
+ }
82
85
  return null;
83
86
  }
84
- return (react_1.default.createElement(exports.StepWrapper, { ref: compRef, isActive: isActive, scrollMarginTop: scrollMarginTop, "data-step-key": stepKey, "data-step-active": isActive, onClick: handleActivateStep, onFocus: handleActivateStep, tabIndex: 0 },
87
+ return (react_1.default.createElement(exports.StepWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodeStep", ref: compRef, isActive: isActive, scrollMarginTop: scrollMarginTop, "data-step-key": stepKey, "data-step-active": isActive, onClick: handleActivateStep, onFocus: handleActivateStep, tabIndex: 0 },
85
88
  react_1.default.createElement(StepContent, { isActive: isActive },
86
89
  heading ? react_1.default.createElement(StepHeading, null, heading) : null,
87
90
  children)));
@@ -35,16 +35,16 @@ const CodeStep_1 = require("../../../markdoc/components/CodeWalkthrough/CodeStep
35
35
  const Switch_1 = require("../../../components/Switch/Switch");
36
36
  function CodeToggle(props) {
37
37
  const { id, label, description, children } = props;
38
- const { getToggleState, changeToggleState } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
39
- const toggleState = getToggleState(id);
40
- if (!(toggleState && toggleState.render)) {
38
+ const { getControlState, changeControlState } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
39
+ const toggleState = getControlState(id);
40
+ if (!(toggleState && toggleState.render && typeof toggleState.value === 'boolean')) {
41
41
  return null;
42
42
  }
43
43
  const checked = toggleState.value;
44
- return (react_1.default.createElement(exports.ToggleWrapper, null,
44
+ return (react_1.default.createElement(exports.ToggleWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/CodeToggle" },
45
45
  react_1.default.createElement(ToggleContentWrapper, null,
46
46
  react_1.default.createElement(exports.ToggleSubtitle, null,
47
- react_1.default.createElement(Switch_1.Switch, { value: checked, onChange: (newValue) => changeToggleState(id, newValue) }),
47
+ react_1.default.createElement(Switch_1.Switch, { value: checked, onChange: (newValue) => changeControlState(id, newValue) }),
48
48
  react_1.default.createElement("div", null, label)),
49
49
  description ? (react_1.default.createElement("div", null, description.map((paragraph, idx) => (react_1.default.createElement(react_1.default.Fragment, { key: idx }, paragraph))))) : null),
50
50
  checked ? children : null));
@@ -51,13 +51,13 @@ function CodeWalkthrough(_a) {
51
51
  // This is a workaround to prevent the observer from being recreated
52
52
  const [initialSteps] = (0, react_1.useState)([...steps]);
53
53
  const { controlsState, stepsState, files, downloadAssociatedFiles } = (0, hooks_1.useCodeWalkthrough)(initialSteps, attributes);
54
- const { activeFilters, getFilterState, changeFilterState } = controlsState;
54
+ const { activeFilters, getControlState, changeControlState } = controlsState;
55
55
  const { filtersElementRef } = stepsState;
56
56
  return (react_1.default.createElement(contexts_1.CodeWalkthroughStepsContext.Provider, { value: stepsState },
57
57
  react_1.default.createElement(contexts_1.CodeWalkthroughControlsStateContext.Provider, { value: controlsState },
58
- react_1.default.createElement(CodeWalkthroughWrapper, { className: "code-walkthrough" },
58
+ react_1.default.createElement(CodeWalkthroughWrapper, { className: "code-walkthrough", "data-component-name": "Markdoc/CodeWalkthrough/CodeWalkthrough" },
59
59
  react_1.default.createElement(DocsPanel, null,
60
- react_1.default.createElement(CodeFilters_1.CodeFilters, { filters: activeFilters, getFilterState: getFilterState, handleFilterSelect: changeFilterState, filtersElementRef: filtersElementRef }),
60
+ react_1.default.createElement(CodeFilters_1.CodeFilters, { filters: activeFilters, getFilterState: getControlState, handleFilterSelect: changeControlState, filtersElementRef: filtersElementRef }),
61
61
  react_1.default.createElement(ContentWrapper, null, children)),
62
62
  react_1.default.createElement(CodePanel_1.CodePanel, { files: files, downloadAssociatedFiles: downloadAssociatedFiles, preview: preview })))));
63
63
  }
@@ -34,12 +34,12 @@ const contexts_1 = require("../../../core/contexts");
34
34
  const DEBOUNCE_TIME = 500;
35
35
  function Input(props) {
36
36
  const { id, label, placeholder } = props;
37
- const { getInputState, changeInputState } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
38
- const inputState = getInputState(id);
37
+ const { getControlState, changeControlState } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext);
38
+ const inputState = getControlState(id);
39
39
  const [value, setValue] = (0, react_1.useState)((inputState === null || inputState === void 0 ? void 0 : inputState.value) || '');
40
40
  // eslint-disable-next-line react-hooks/exhaustive-deps
41
41
  const debouncedSave = (0, react_1.useCallback)((0, lodash_debounce_1.default)((id, value) => {
42
- changeInputState(id, value);
42
+ changeControlState(id, value);
43
43
  }, DEBOUNCE_TIME), []);
44
44
  if (!(inputState === null || inputState === void 0 ? void 0 : inputState.render)) {
45
45
  return null;
@@ -49,14 +49,15 @@ function Input(props) {
49
49
  setValue(inputValue);
50
50
  debouncedSave(id, inputValue);
51
51
  };
52
- return (react_1.default.createElement(InputWrapper, null,
52
+ return (react_1.default.createElement(InputWrapper, { "data-component-name": "Markdoc/CodeWalkthrough/Input" },
53
53
  label && react_1.default.createElement(Label, null, label),
54
54
  react_1.default.createElement(StyledInput, { id: id, value: value, onChange: handleChange, "aria-label": label, placeholder: placeholder })));
55
55
  }
56
56
  const InputWrapper = styled_components_1.default.div `
57
57
  display: flex;
58
58
  flex-direction: column;
59
- margin: var(--md-paragraph-margin);
59
+ margin-top: var(--spacing-base);
60
+ margin-bottom: var(--spacing-base);
60
61
  `;
61
62
  const Label = styled_components_1.default.p `
62
63
  color: var(--text-color-secondary);
@@ -64,6 +65,7 @@ const Label = styled_components_1.default.p `
64
65
  line-height: var(--line-height-base);
65
66
  font-family: var(--font-family-base);
66
67
  font-weight: var(--font-weight-medium);
68
+ margin-bottom: var(--spacing-xxs) !important;
67
69
  `;
68
70
  const StyledInput = styled_components_1.default.input `
69
71
  border: 1px solid var(--border-color-primary);
@@ -41,6 +41,11 @@ exports.codeWalkthrough = {
41
41
  render: false,
42
42
  required: false,
43
43
  },
44
+ __idx: {
45
+ type: Number,
46
+ render: true,
47
+ required: false,
48
+ },
44
49
  },
45
50
  slots: {
46
51
  preview: { required: false, render: true },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.48.0",
3
+ "version": "0.48.2",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -46,7 +46,7 @@
46
46
  "@types/jest-when": "3.5.5",
47
47
  "@types/lodash.debounce": "4.0.9",
48
48
  "@types/lodash.throttle": "4.1.9",
49
- "@types/node": "18.19.3",
49
+ "@types/node": "22.10.5",
50
50
  "@types/react": "18.3.9",
51
51
  "@types/react-dom": "18.3.5",
52
52
  "@types/styled-components": "5.1.34",
@@ -86,7 +86,7 @@
86
86
  "timeago.js": "4.0.2",
87
87
  "i18next": "22.4.15",
88
88
  "nprogress": "0.2.0",
89
- "@redocly/config": "0.20.0"
89
+ "@redocly/config": "0.20.2"
90
90
  },
91
91
  "scripts": {
92
92
  "watch": "tsc -p tsconfig.build.json && (concurrently \"tsc -w -p tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\")",
@@ -4,7 +4,7 @@ export const datePicker = css`
4
4
  --date-picker-nav-color: #000000;
5
5
  --date-picker-tile-bg-color: var(--color-blue-2);
6
6
  --date-picker-tile-color: var(--text-color-primary);
7
- --date-picker-tile-bg-color-hover: var(--color-blue-3)
7
+ --date-picker-tile-bg-color-hover: var(--color-blue-3);
8
8
  --date-picker-tile-color-hover: var(--text-color-primary);
9
9
  --date-picker-input-width: var(--spacing-md);
10
10
  --date-picker-invalid-input-bg-color: var(--bg-color-raised);
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { useEffect } from 'react';
3
- import styled from 'styled-components';
3
+ import styled, { css } from 'styled-components';
4
4
 
5
5
  import type { OptionalEmailSettings, ReasonsSettingsSchema } from '@redocly/config';
6
6
  import type { ReasonsProps } from '@redocly/theme/components/Feedback/Reasons';
@@ -161,7 +161,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
161
161
  return (
162
162
  <MoodWrapper data-component-name="Feedback/Mood">
163
163
  <StyledFormMandatoryFields>
164
- <Label data-translation-key="feedback.settings.submitText">
164
+ <Label standAlone={true} data-translation-key="feedback.settings.submitText">
165
165
  {submitText ||
166
166
  translate(
167
167
  'feedback.settings.submitText',
@@ -178,7 +178,7 @@ export function Mood({ settings, onSubmit, className }: MoodProps): JSX.Element
178
178
  <MoodWrapper data-component-name="Feedback/Mood" className={className}>
179
179
  <StyledForm onSubmit={onSubmitMoodForm}>
180
180
  <StyledFormMandatoryFields>
181
- <Label data-translation-key="feedback.settings.label">
181
+ <Label standAlone={true} data-translation-key="feedback.settings.label">
182
182
  {label || translate('feedback.settings.label', 'Was this helpful?')}
183
183
  </Label>
184
184
  <StyledMandatoryFieldContainer>
@@ -294,12 +294,21 @@ const MoodWrapper = styled.div`
294
294
  align-items: center;
295
295
  `;
296
296
 
297
- const Label = styled.h4`
297
+ const Label = styled.h4<{ standAlone?: boolean }>`
298
298
  font-family: var(--feedback-font-family);
299
299
  font-weight: var(--font-weight-regular);
300
- font-size: var(--feedback-header-font-size);
301
- line-height: var(--feedback-header-line-height);
302
- color: var(--feedback-header-text-color);
300
+ font-size: var(--feedback-font-size);
301
+ line-height: var(--feedback-line-height);
302
+ color: var(--feedback-text-color);
303
+
304
+ ${({ standAlone = false }) =>
305
+ standAlone &&
306
+ css`
307
+ font-size: var(--feedback-header-font-size);
308
+ line-height: var(--feedback-header-line-height);
309
+ color: var(--feedback-header-text-color);
310
+ `}
311
+
303
312
  margin: 0;
304
313
  `;
305
314
 
@@ -153,7 +153,7 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
153
153
  }
154
154
  }}
155
155
  >
156
- {translate('search.aiButton', 'Search with AI')}
156
+ {translate('search.ai.button', 'Search with AI')}
157
157
  </SearchAiButton>
158
158
  ) : null}
159
159
  {showSearchFilterButton && (
@@ -236,41 +236,50 @@ export function SearchDialog({ onClose, className }: SearchDialogProps): JSX.Ele
236
236
  />
237
237
  )}
238
238
  </SearchDialogBody>
239
- {mode === 'search' && (
240
- <SearchDialogFooter>
241
- <SearchShortcuts>
242
- <SearchShortcut
243
- data-translation-key="search.keys.navigate"
244
- combination="Tab"
245
- text={translate('search.keys.navigate', 'to navigate')}
246
- />
247
- <SearchShortcut
248
- data-translation-key="search.keys.select"
249
- combination="⏎"
250
- text={translate('search.keys.select', 'to select')}
251
- />
252
- <SearchShortcut
253
- data-translation-key="search.keys.exit"
254
- combination="Esc"
255
- text={translate('search.keys.exit', 'to exit')}
256
- />
257
- </SearchShortcuts>
258
- {isSearchLoading && (
259
- <SearchLoading>
260
- <SpinnerLoader size="16px" color="var(--search-input-icon-color)" />
261
- {translate('search.loading', 'Loading...')}
262
- </SearchLoading>
263
- )}
264
- <SearchCancelButton
265
- data-translation-key="search.cancel"
266
- variant="secondary"
267
- size="small"
268
- onClick={onClose}
269
- >
270
- {translate('search.cancel', 'Cancel')}
271
- </SearchCancelButton>
272
- </SearchDialogFooter>
273
- )}
239
+ <SearchDialogFooter>
240
+ {mode === 'ai-dialog' ? (
241
+ <AiDisclaimer>
242
+ {translate(
243
+ 'search.ai.disclaimer',
244
+ 'AI search might provide incomplete or incorrect results. Verify important information.',
245
+ )}
246
+ </AiDisclaimer>
247
+ ) : (
248
+ <>
249
+ <SearchShortcuts>
250
+ <SearchShortcut
251
+ data-translation-key="search.keys.navigate"
252
+ combination="Tab"
253
+ text={translate('search.keys.navigate', 'to navigate')}
254
+ />
255
+ <SearchShortcut
256
+ data-translation-key="search.keys.select"
257
+ combination="⏎"
258
+ text={translate('search.keys.select', 'to select')}
259
+ />
260
+ <SearchShortcut
261
+ data-translation-key="search.keys.exit"
262
+ combination="Esc"
263
+ text={translate('search.keys.exit', 'to exit')}
264
+ />
265
+ </SearchShortcuts>
266
+ {isSearchLoading && (
267
+ <SearchLoading>
268
+ <SpinnerLoader size="16px" color="var(--search-input-icon-color)" />
269
+ {translate('search.loading', 'Loading...')}
270
+ </SearchLoading>
271
+ )}
272
+ <SearchCancelButton
273
+ data-translation-key="search.cancel"
274
+ variant="secondary"
275
+ size="small"
276
+ onClick={onClose}
277
+ >
278
+ {translate('search.cancel', 'Cancel')}
279
+ </SearchCancelButton>
280
+ </>
281
+ )}
282
+ </SearchDialogFooter>
274
283
  </SearchDialogWrapper>
275
284
  </SearchOverlay>
276
285
  );
@@ -439,3 +448,10 @@ const SearchHeaderButtons = styled.div`
439
448
  padding-left: var(--search-header-buttons-padding-left);
440
449
  border-left: var(--search-header-buttons-border-left);
441
450
  `;
451
+
452
+ const AiDisclaimer = styled.div`
453
+ font-size: var(--search-ai-disclaimer-font-size);
454
+ line-height: var(--search-ai-disclaimer-line-height);
455
+ color: var(--search-ai-disclaimer-text-color);
456
+ margin: 0 auto;
457
+ `;
@@ -176,5 +176,9 @@ export const search = css`
176
176
  --search-ai-resource-tag-text-color: var(--text-color-secondary);
177
177
  --search-ai-resource-tag-icon-color: var(--text-color-secondary);
178
178
 
179
+ --search-ai-disclaimer-font-size: var(--font-size-sm);
180
+ --search-ai-disclaimer-line-height: var(--line-height-sm);
181
+ --search-ai-disclaimer-text-color: var(--text-color-secondary);
182
+
179
183
  // @tokens End
180
184
  `;
@@ -1,7 +1,7 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
 
4
- import type { ReactElement } from 'react';
4
+ import type { ForwardedRef, ReactElement } from 'react';
5
5
  import type { SelectOption } from '@redocly/theme/core/types/select';
6
6
 
7
7
  import { typedMemo } from '@redocly/theme/core/hoc/typedMemo';
@@ -14,15 +14,13 @@ export type SegmentedProps<T> = {
14
14
  size?: 'regular' | 'small';
15
15
  };
16
16
 
17
- function SegmentedComponent<T>({
18
- options,
19
- onChange,
20
- value,
21
- className = '',
22
- size = 'regular',
23
- }: SegmentedProps<T>): ReactElement {
17
+ function SegmentedComponent<T>(
18
+ { options, onChange, value, className = '', size = 'regular' }: SegmentedProps<T>,
19
+ ref?: ForwardedRef<HTMLDivElement>,
20
+ ): ReactElement {
24
21
  return (
25
22
  <SegmentedGroup
23
+ ref={ref}
26
24
  data-component-name="Segmented/Segmented"
27
25
  className={`tag-grey ${size} ${className}`}
28
26
  role="tablist"
@@ -43,7 +41,9 @@ function SegmentedComponent<T>({
43
41
  );
44
42
  }
45
43
 
46
- export const Segmented = typedMemo(SegmentedComponent);
44
+ export const Segmented = typedMemo(forwardRef(SegmentedComponent)) as <T>(
45
+ props: SegmentedProps<T> & { ref?: ForwardedRef<HTMLDivElement> },
46
+ ) => ReactElement;
47
47
 
48
48
  const SegmentedGroup = styled.div`
49
49
  display: flex;
@@ -83,7 +83,7 @@ export function Tag({
83
83
  );
84
84
  }
85
85
 
86
- const ContentWrapper = styled.div`
86
+ export const ContentWrapper = styled.div`
87
87
  display: inline-flex;
88
88
  align-items: center;
89
89
  justify-content: center;
@@ -5,14 +5,8 @@ import type { WalkthroughControlsState } from '@redocly/theme/core/hooks';
5
5
  export const CodeWalkthroughControlsStateContext = createContext<WalkthroughControlsState>({
6
6
  activeFilters: [],
7
7
 
8
- getToggleState: () => null,
9
- changeToggleState: () => {},
10
-
11
- getInputState: () => null,
12
- changeInputState: () => {},
13
-
14
- getFilterState: () => null,
15
- changeFilterState: () => {},
8
+ getControlState: () => null,
9
+ changeControlState: () => {},
16
10
 
17
11
  getFileText: () => '',
18
12
  areConditionsMet: () => false,