@redocly/theme 0.70.0-next.0 → 0.70.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 (42) hide show
  1. package/lib/components/Button/Button.js +5 -2
  2. package/lib/components/Button/variables.js +14 -5
  3. package/lib/components/Dropdown/Dropdown.js +0 -7
  4. package/lib/components/ReplaySecuritySchemeActions/ReplaySecuritySchemeActions.d.ts +11 -0
  5. package/lib/components/ReplaySecuritySchemeActions/ReplaySecuritySchemeActions.js +7 -0
  6. package/lib/components/SplitButton/SplitButton.d.ts +1 -0
  7. package/lib/components/SplitButton/SplitButton.js +2 -2
  8. package/lib/components/Tooltip/AnchorTooltip.js +17 -27
  9. package/lib/components/Tooltip/JsTooltip.js +34 -46
  10. package/lib/components/Tooltip/Tooltip.js +1 -2
  11. package/lib/core/hooks/catalog/use-catalog-entity-schema.js +2 -2
  12. package/lib/core/hooks/code-walkthrough/use-code-walkthrough-controls.js +1 -1
  13. package/lib/core/hooks/index.d.ts +1 -0
  14. package/lib/core/hooks/index.js +1 -0
  15. package/lib/core/hooks/menu/use-nested-menu.js +2 -2
  16. package/lib/core/hooks/use-anchor-positioning.d.ts +3 -0
  17. package/lib/core/hooks/use-anchor-positioning.js +21 -0
  18. package/lib/core/hooks/use-theme-hooks.js +0 -1
  19. package/lib/core/types/hooks.d.ts +0 -3
  20. package/lib/core/utils/load-and-navigate.js +3 -3
  21. package/package.json +3 -3
  22. package/src/components/Button/Button.tsx +5 -2
  23. package/src/components/Button/variables.ts +14 -5
  24. package/src/components/Dropdown/Dropdown.tsx +0 -7
  25. package/src/components/ReplaySecuritySchemeActions/ReplaySecuritySchemeActions.tsx +19 -0
  26. package/src/components/SplitButton/SplitButton.tsx +3 -0
  27. package/src/components/Tooltip/AnchorTooltip.tsx +17 -27
  28. package/src/components/Tooltip/JsTooltip.tsx +55 -62
  29. package/src/components/Tooltip/Tooltip.tsx +1 -2
  30. package/src/core/hooks/__mocks__/index.ts +1 -0
  31. package/src/core/hooks/__mocks__/use-anchor-positioning.ts +3 -0
  32. package/src/core/hooks/__mocks__/use-theme-hooks.ts +0 -3
  33. package/src/core/hooks/catalog/use-catalog-entity-schema.ts +2 -2
  34. package/src/core/hooks/code-walkthrough/__mocks__/MockIntersectionObserver.ts +1 -1
  35. package/src/core/hooks/code-walkthrough/__mocks__/mock-intersection-observer.ts +1 -1
  36. package/src/core/hooks/code-walkthrough/use-code-walkthrough-controls.ts +1 -1
  37. package/src/core/hooks/index.ts +1 -0
  38. package/src/core/hooks/menu/use-nested-menu.ts +2 -2
  39. package/src/core/hooks/use-anchor-positioning.ts +22 -0
  40. package/src/core/hooks/use-theme-hooks.ts +0 -1
  41. package/src/core/types/hooks.ts +0 -1
  42. package/src/core/utils/load-and-navigate.ts +3 -3
@@ -118,7 +118,9 @@ const StyledButton = styled_components_1.default.button `
118
118
  height: var(--button-icon-size);
119
119
  }
120
120
 
121
- &:hover {
121
+ /* A button that owns an open menu keeps its hovered appearance. */
122
+ &:hover,
123
+ &[aria-expanded='true'] {
122
124
  background-color: var(--button-bg-color-hover);
123
125
  color: var(--button-color-hover);
124
126
  border-color: var(--button-border-color-hover);
@@ -140,7 +142,8 @@ const StyledButton = styled_components_1.default.button `
140
142
  border-color: var(--button-border-color-danger);
141
143
  background-color: var(--button-bg-color-danger);
142
144
 
143
- &:hover {
145
+ &:hover,
146
+ &[aria-expanded='true'] {
144
147
  color: var(--button-content-color-danger-hover);
145
148
  border-color: var(--button-border-color-danger-hover);
146
149
  background-color: var(--button-bg-color-danger-hover);
@@ -251,21 +251,30 @@ exports.button = (0, styled_components_1.css) `
251
251
  --button-group-divider-opacity: 1;
252
252
  --button-group-divider-color-disabled: var(--color-warm-grey-2); // @presenter Color
253
253
 
254
- .button-group-primary {
255
- --button-group-divider-color: var(--button-content-color-inverse); // @presenter Color
254
+ .button-group-primary .button {
255
+ --button-group-divider-color: var(--button-color); // @presenter Color
256
256
  --button-group-divider-opacity: 0.32;
257
257
  }
258
258
 
259
- .button-group-secondary {
260
- --button-group-divider-color: var(--button-content-color); // @presenter Color
259
+ .button-group-secondary .button {
260
+ --button-group-divider-color: var(--button-color); // @presenter Color
261
261
  --button-group-divider-opacity: 0.12;
262
262
  }
263
263
 
264
- .button-group-outlined {
264
+ .button-group-outlined .button {
265
265
  --button-group-divider-color: var(--button-border-color); // @presenter Color
266
266
  --button-group-divider-opacity: 1;
267
267
  }
268
268
 
269
+ .button-group-primary .button.button-tone-danger,
270
+ .button-group-secondary .button.button-tone-danger {
271
+ --button-group-divider-color: var(--button-content-color-danger); // @presenter Color
272
+ }
273
+
274
+ .button-group-outlined .button.button-tone-danger {
275
+ --button-group-divider-color: var(--button-border-color-danger); // @presenter Color
276
+ }
277
+
269
278
  // @tokens End
270
279
  `;
271
280
  //# sourceMappingURL=variables.js.map
@@ -142,13 +142,6 @@ const DropdownWrapper = styled_components_1.default.div `
142
142
  position: relative;
143
143
 
144
144
  text-decoration: none;
145
-
146
- /* The trigger keeps its hovered appearance while the menu is open. */
147
- > .button[aria-expanded='true'] {
148
- background-color: var(--button-bg-color-hover);
149
- color: var(--button-color-hover);
150
- border-color: var(--button-border-color-hover);
151
- }
152
145
  `;
153
146
  const ChildrenWrapper = styled_components_1.default.div `
154
147
  padding-top: var(--dropdown-menu-padding-top);
@@ -0,0 +1,11 @@
1
+ export type ReplaySecurityType = 'oauth2' | 'openIdConnect' | 'apiKey' | 'http-bearer';
2
+ export type ReplaySecuritySchemeActionsProps = {
3
+ schemeId: string | null;
4
+ securityType: ReplaySecurityType;
5
+ environment: string;
6
+ operationId?: string;
7
+ value: string;
8
+ setValue: (value: string) => void;
9
+ apiId?: string;
10
+ };
11
+ export declare function ReplaySecuritySchemeActions(_props: ReplaySecuritySchemeActionsProps): null;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplaySecuritySchemeActions = ReplaySecuritySchemeActions;
4
+ function ReplaySecuritySchemeActions(_props) {
5
+ return null;
6
+ }
7
+ //# sourceMappingURL=ReplaySecuritySchemeActions.js.map
@@ -8,6 +8,7 @@ export type SplitButtonProps = {
8
8
  children: ComponentProps<typeof Dropdown>['children'];
9
9
  variant?: ButtonGroupVariant;
10
10
  size?: ButtonGroupSize;
11
+ tone?: ButtonProps['tone'];
11
12
  placement?: 'top' | 'bottom';
12
13
  alignment?: 'start' | 'end';
13
14
  portalled?: boolean;
@@ -10,12 +10,12 @@ const Button_1 = require("../../components/Button/Button");
10
10
  const ButtonGroup_1 = require("../../components/Button/ButtonGroup");
11
11
  const Dropdown_1 = require("../../components/Dropdown/Dropdown");
12
12
  function SplitButton(props) {
13
- const { button, children, variant, size, placement = 'bottom', alignment = 'end', portalled, closeOnSelect = true, disabled, toggleAriaLabel, onOpen, onClose, className, } = props;
13
+ const { button, children, variant, size, tone, placement = 'bottom', alignment = 'end', portalled, closeOnSelect = true, disabled, toggleAriaLabel, onOpen, onClose, className, } = props;
14
14
  const hasMenu = typeof children === 'function' || react_1.default.Children.toArray(children).length > 0;
15
15
  return (react_1.default.createElement(SplitButtonWrapper, { "data-component-name": "SplitButton/SplitButton", className: className },
16
16
  react_1.default.createElement(ButtonGroup_1.ButtonGroup, { variant: variant, size: size },
17
17
  button,
18
- hasMenu ? (react_1.default.createElement(ToggleDropdown, { closeOnClick: closeOnSelect, placement: placement, alignment: alignment, portalled: portalled, withArrow: true, onOpen: onOpen, onClose: onClose, trigger: react_1.default.createElement(Button_1.Button, { "aria-label": toggleAriaLabel, "aria-haspopup": "menu", variant: variant, size: size, disabled: disabled }) }, children)) : null)));
18
+ hasMenu ? (react_1.default.createElement(ToggleDropdown, { closeOnClick: closeOnSelect, placement: placement, alignment: alignment, portalled: portalled, withArrow: true, onOpen: onOpen, onClose: onClose, trigger: react_1.default.createElement(Button_1.Button, { "aria-label": toggleAriaLabel, "aria-haspopup": "menu", variant: variant, size: size, tone: tone, disabled: disabled }) }, children)) : null)));
19
19
  }
20
20
  const SplitButtonWrapper = styled_components_1.default.div `
21
21
  position: relative;
@@ -103,15 +103,13 @@ const PLACEMENTS = {
103
103
  ${({ $withArrow, $arrowPosition }) => $withArrow &&
104
104
  (0, styled_components_1.css) `
105
105
  &::after {
106
- border-left: 14px solid transparent;
107
- border-right: 14px solid transparent;
108
- border-top-width: 8px;
109
- border-top-style: solid;
110
- border-radius: 2px;
106
+ width: 16px;
107
+ height: 8px;
108
+ clip-path: path('M0 0H16L9.414 6.586A2 2 0 0 1 6.586 6.586Z');
111
109
  bottom: 0;
112
- ${$arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
110
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(100%);'}
113
111
  ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
114
- ${$arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
112
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(100%);'}
115
113
  }
116
114
  `}
117
115
  `,
@@ -135,15 +133,13 @@ const PLACEMENTS = {
135
133
  ${({ $withArrow, $arrowPosition }) => $withArrow &&
136
134
  (0, styled_components_1.css) `
137
135
  &::after {
138
- border-left: 14px solid transparent;
139
- border-right: 14px solid transparent;
140
- border-bottom-width: 8px;
141
- border-bottom-style: solid;
142
- border-radius: 0 0 2px 2px;
136
+ width: 16px;
137
+ height: 8px;
138
+ clip-path: path('M0 8H16L9.414 1.414A2 2 0 0 0 6.586 1.414Z');
143
139
  top: 0;
144
- ${$arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
140
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(-100%);'}
145
141
  ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
146
- ${$arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
142
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(-100%);'}
147
143
  }
148
144
  `}
149
145
  `,
@@ -156,11 +152,9 @@ const PLACEMENTS = {
156
152
  ${({ $withArrow }) => $withArrow &&
157
153
  (0, styled_components_1.css) `
158
154
  &::after {
159
- border-top: 14px solid transparent;
160
- border-bottom: 14px solid transparent;
161
- border-left-width: 8px;
162
- border-left-style: solid;
163
- border-radius: 2px 0 0 2px;
155
+ width: 8px;
156
+ height: 16px;
157
+ clip-path: path('M0 0V16L6.586 9.414A2 2 0 0 0 6.586 6.586Z');
164
158
  right: -9px;
165
159
  top: 50%;
166
160
  transform: translateY(-50%);
@@ -176,11 +170,9 @@ const PLACEMENTS = {
176
170
  ${({ $withArrow }) => $withArrow &&
177
171
  (0, styled_components_1.css) `
178
172
  &::after {
179
- border-top: 14px solid transparent;
180
- border-bottom: 14px solid transparent;
181
- border-right-width: 8px;
182
- border-right-style: solid;
183
- border-radius: 0 2px 2px 0;
173
+ width: 8px;
174
+ height: 16px;
175
+ clip-path: path('M8 0V16L1.414 9.414A2 2 0 0 1 1.414 6.586Z');
184
176
  left: -9px;
185
177
  top: 50%;
186
178
  transform: translateY(-50%);
@@ -222,9 +214,7 @@ const TooltipBody = styled_components_1.default.span.attrs(({ $anchorName }) =>
222
214
 
223
215
  content: ' ';
224
216
  display: inline-block;
225
- width: 0;
226
- height: 0;
227
- border-color: var(--tooltip-arrow-color, var(--tooltip-bg-color));
217
+ background: var(--tooltip-arrow-color, var(--tooltip-bg-color));
228
218
  }
229
219
 
230
220
  background: var(--tooltip-bg-color);
@@ -112,12 +112,12 @@ function TooltipComponent({ children, isOpen, tip, withArrow = true, placement =
112
112
  exports.Tooltip = (0, react_1.memo)(TooltipComponent);
113
113
  const PLACEMENTS = {
114
114
  top: (0, styled_components_1.css) `
115
- ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
115
+ ${({ $withArrow, $arrowPosition }) => $withArrow && $arrowPosition === 'left'
116
116
  ? (0, styled_components_1.css) `
117
117
  transform: translate(0, -100%);
118
118
  margin-top: -10px;
119
119
  `
120
- : arrowPosition === 'right'
120
+ : $arrowPosition === 'right'
121
121
  ? (0, styled_components_1.css) `
122
122
  transform: translate(-100%, -100%);
123
123
  margin-top: -10px;
@@ -127,28 +127,26 @@ const PLACEMENTS = {
127
127
  margin-top: -10px;
128
128
  `}
129
129
 
130
- ${({ withArrow, arrowPosition }) => withArrow &&
130
+ ${({ $withArrow, $arrowPosition }) => $withArrow &&
131
131
  (0, styled_components_1.css) `
132
132
  &::after {
133
- border-left: 14px solid transparent;
134
- border-right: 14px solid transparent;
135
- border-top-width: 8px;
136
- border-top-style: solid;
137
- border-radius: 2px;
133
+ width: 16px;
134
+ height: 8px;
135
+ clip-path: path('M0 0H16L9.414 6.586A2 2 0 0 1 6.586 6.586Z');
138
136
  bottom: 0;
139
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(99%);'}
140
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
141
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(99%);'}
137
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(99%);'}
138
+ ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
139
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(99%);'}
142
140
  }
143
141
  `}
144
142
  `,
145
143
  bottom: (0, styled_components_1.css) `
146
- ${({ withArrow, arrowPosition }) => withArrow && arrowPosition === 'left'
144
+ ${({ $withArrow, $arrowPosition }) => $withArrow && $arrowPosition === 'left'
147
145
  ? (0, styled_components_1.css) `
148
146
  transform: translate(0, 10px);
149
147
  margin-top: 0;
150
148
  `
151
- : arrowPosition === 'right'
149
+ : $arrowPosition === 'right'
152
150
  ? (0, styled_components_1.css) `
153
151
  transform: translate(-100%, 10px);
154
152
  margin-top: 0;
@@ -158,18 +156,16 @@ const PLACEMENTS = {
158
156
  margin-top: 0;
159
157
  `}
160
158
 
161
- ${({ withArrow, arrowPosition }) => withArrow &&
159
+ ${({ $withArrow, $arrowPosition }) => $withArrow &&
162
160
  (0, styled_components_1.css) `
163
161
  &::after {
164
- border-left: 14px solid transparent;
165
- border-right: 14px solid transparent;
166
- border-bottom-width: 8px;
167
- border-bottom-style: solid;
168
- border-radius: 0 0 2px 2px;
162
+ width: 16px;
163
+ height: 8px;
164
+ clip-path: path('M0 8H16L9.414 1.414A2 2 0 0 0 6.586 1.414Z');
169
165
  top: 0;
170
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-99%);'}
171
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
172
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-99%);'}
166
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(-99%);'}
167
+ ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
168
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(-99%);'}
173
169
  }
174
170
  `}
175
171
  `,
@@ -177,19 +173,17 @@ const PLACEMENTS = {
177
173
  transform: translate(-100%, -50%);
178
174
  margin-left: -10px;
179
175
 
180
- ${({ withArrow, arrowPosition }) => withArrow &&
176
+ ${({ $withArrow, $arrowPosition }) => $withArrow &&
181
177
  (0, styled_components_1.css) `
182
178
  &::after {
183
- border-top: 14px solid transparent;
184
- border-bottom: 14px solid transparent;
185
- border-left-width: 8px;
186
- border-left-style: solid;
187
- border-radius: 2px 0 0 2px;
179
+ width: 8px;
180
+ height: 16px;
181
+ clip-path: path('M0 0V16L6.586 9.414A2 2 0 0 0 6.586 6.586Z');
188
182
  top: 50%;
189
183
  right: 0;
190
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
191
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
192
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
184
+ ${$arrowPosition === 'top' && 'top: 22px; transform: translateX(99%);'}
185
+ ${$arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
186
+ ${$arrowPosition === 'bottom' && 'bottom: 22px; transform: translateX(99%);'}
193
187
  }
194
188
  `}
195
189
  `,
@@ -197,19 +191,17 @@ const PLACEMENTS = {
197
191
  transform: translate(0, -50%);
198
192
  margin-left: 10px;
199
193
 
200
- ${({ withArrow, arrowPosition }) => withArrow &&
194
+ ${({ $withArrow, $arrowPosition }) => $withArrow &&
201
195
  (0, styled_components_1.css) `
202
196
  &::after {
203
- border-top: 14px solid transparent;
204
- border-bottom: 14px solid transparent;
205
- border-right-width: 8px;
206
- border-right-style: solid;
207
- border-radius: 0 2px 2px 0;
197
+ width: 8px;
198
+ height: 16px;
199
+ clip-path: path('M8 0V16L1.414 9.414A2 2 0 0 1 1.414 6.586Z');
208
200
  top: 50%;
209
201
  left: 0;
210
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
211
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
212
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
202
+ ${$arrowPosition === 'top' && 'top: 22px; transform: translateX(-99%);'}
203
+ ${$arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
204
+ ${$arrowPosition === 'bottom' && 'bottom: 22px; transform: translateX(-99%);'}
213
205
  }
214
206
  `}
215
207
  `,
@@ -240,9 +232,7 @@ const TooltipBody = styled_components_1.default.span `
240
232
 
241
233
  content: ' ';
242
234
  display: inline-block;
243
- width: 0;
244
- height: 0;
245
- border-color: var(--tooltip-arrow-color, var(--tooltip-bg-color));
235
+ background: var(--tooltip-arrow-color, var(--tooltip-bg-color));
246
236
  }
247
237
 
248
238
  background: var(--tooltip-bg-color);
@@ -252,8 +242,6 @@ const TooltipBody = styled_components_1.default.span `
252
242
  box-shadow: var(--bg-raised-shadow);
253
243
 
254
244
  width: ${({ $width }) => $width || 'max-content'};
255
- ${({ $placement }) => (0, styled_components_1.css) `
256
- ${PLACEMENTS[$placement]};
257
- `}
245
+ ${({ $placement }) => PLACEMENTS[$placement]}
258
246
  `;
259
247
  //# sourceMappingURL=JsTooltip.js.map
@@ -41,8 +41,7 @@ const hooks_1 = require("../../core/hooks");
41
41
  const utils_1 = require("../../core/utils");
42
42
  function TooltipComponent(props) {
43
43
  var _a, _b;
44
- const { useAnchorPositioning } = (0, hooks_1.useThemeHooks)();
45
- const { isSupported } = useAnchorPositioning();
44
+ const { isSupported } = (0, hooks_1.useAnchorPositioning)();
46
45
  const fallbackPlacements = (_a = props.fallbackPlacements) !== null && _a !== void 0 ? _a : (0, utils_1.getDefaultFallbackPlacements)((_b = props.placement) !== null && _b !== void 0 ? _b : 'top');
47
46
  if (isSupported) {
48
47
  return (react_1.default.createElement(AnchorTooltip_1.Tooltip, Object.assign({}, props, { fallbackPlacements: fallbackPlacements, arrowPosition: prepareArrowPosition(props.arrowPosition) })));
@@ -8,7 +8,7 @@ function useCatalogEntitySchema({ entity, relatedEntity }) {
8
8
  try {
9
9
  parsedSchema = JSON.parse(schema);
10
10
  }
11
- catch (error) {
11
+ catch (_c) {
12
12
  parsedSchema = undefined;
13
13
  }
14
14
  let parsedApiDefinition;
@@ -17,7 +17,7 @@ function useCatalogEntitySchema({ entity, relatedEntity }) {
17
17
  ? JSON.parse(relatedEntity.metadata.schema)
18
18
  : undefined;
19
19
  }
20
- catch (err) {
20
+ catch (_d) {
21
21
  parsedApiDefinition = undefined;
22
22
  }
23
23
  const definition = !parsedApiDefinition || ((_b = relatedEntity === null || relatedEntity === void 0 ? void 0 : relatedEntity.metadata) === null || _b === void 0 ? void 0 : _b.specType) !== 'openapi'
@@ -42,7 +42,7 @@ function useCodeWalkthroughControls(filters, inputs, toggles, enableDeepLink) {
42
42
  Object.entries(newState).forEach(([id, control]) => {
43
43
  const existingControl = controlsState[id];
44
44
  if (existingControl && existingControl.type === control.type) {
45
- // @ts-ignore
45
+ // @ts-expect-error
46
46
  newState[id] = Object.assign(Object.assign({}, control), { value: existingControl.value });
47
47
  }
48
48
  });
@@ -55,3 +55,4 @@ export * from './use-toast';
55
55
  export * from './use-toast-logic';
56
56
  export * from './use-banner-telemetry';
57
57
  export * from './use-tooltip-fallback-placement';
58
+ export * from './use-anchor-positioning';
@@ -71,4 +71,5 @@ __exportStar(require("./use-toast"), exports);
71
71
  __exportStar(require("./use-toast-logic"), exports);
72
72
  __exportStar(require("./use-banner-telemetry"), exports);
73
73
  __exportStar(require("./use-tooltip-fallback-placement"), exports);
74
+ __exportStar(require("./use-anchor-positioning"), exports);
74
75
  //# sourceMappingURL=index.js.map
@@ -46,9 +46,9 @@ function useNestedMenu({ item, labelRef, nestedMenuRef }) {
46
46
  rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
47
47
  rect.right <= (window.innerWidth || document.documentElement.clientWidth);
48
48
  // Only scroll if element is in viewport to prevent page jumping
49
- // @ts-ignore
49
+ // @ts-expect-error
50
50
  if (isInViewport && typeof el.scrollIntoViewIfNeeded === 'function') {
51
- // @ts-ignore
51
+ // @ts-expect-error
52
52
  el.scrollIntoViewIfNeeded(centerIfNeeded);
53
53
  }
54
54
  }
@@ -0,0 +1,3 @@
1
+ export declare const useAnchorPositioning: () => {
2
+ isSupported: boolean;
3
+ };
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAnchorPositioning = void 0;
4
+ const react_1 = require("react");
5
+ const useAnchorPositioning = () => {
6
+ const [isSupported, setIsSupported] = (0, react_1.useState)(false);
7
+ (0, react_1.useEffect)(() => {
8
+ setIsSupported(isAnchorPositioningSupported());
9
+ }, []);
10
+ return { isSupported };
11
+ };
12
+ exports.useAnchorPositioning = useAnchorPositioning;
13
+ function isAnchorPositioningSupported() {
14
+ if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
15
+ return false;
16
+ }
17
+ return (CSS.supports('anchor-name: --a') &&
18
+ CSS.supports('position-anchor: --a') &&
19
+ CSS.supports('top: anchor(top)'));
20
+ }
21
+ //# sourceMappingURL=use-anchor-positioning.js.map
@@ -5,7 +5,6 @@ const react_1 = require("react");
5
5
  const ThemeDataContext_1 = require("../contexts/ThemeDataContext");
6
6
  const use_telemetry_fallback_1 = require("./use-telemetry-fallback");
7
7
  const fallbacks = {
8
- useAnchorPositioning: () => ({ isSupported: false }),
9
8
  useTranslate: () => ({
10
9
  translate: (value, options) => (typeof options === 'string' ? options : options === null || options === void 0 ? void 0 : options.defaultValue) || value || '',
11
10
  }),
@@ -14,9 +14,6 @@ import type { TFunction } from './l10n';
14
14
  import type { BreadcrumbItem } from './breadcrumb';
15
15
  import type { AiSearchError } from '../constants/search';
16
16
  export type ThemeHooks = {
17
- useAnchorPositioning: () => {
18
- isSupported: boolean;
19
- };
20
17
  useTranslate: () => {
21
18
  translate: TFunction;
22
19
  };
@@ -24,9 +24,9 @@ function loadAndNavigate(_a) {
24
24
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
25
25
  const loader = window['__LOADER'];
26
26
  const result = yield (0, with_load_progress_1.withLoadProgress)(loader.tryLoad(pathname));
27
- // @ts-ignore
27
+ // @ts-expect-error
28
28
  if (result === null || result === void 0 ? void 0 : result.redirectTo) {
29
- // @ts-ignore
29
+ // @ts-expect-error
30
30
  return loadAndNavigate({ navigate, to: result.redirectTo, origin, options });
31
31
  }
32
32
  if (result && lastNavigatedPath === to) {
@@ -34,7 +34,7 @@ function loadAndNavigate(_a) {
34
34
  // origin is used to prevent infinite loop when navigating from post message (from wysiwyg)
35
35
  navigate({ pathname, search, hash }, Object.assign(Object.assign({}, options), { state: { origin }, unstable_flushSync: true }));
36
36
  }
37
- // @ts-ignore
37
+ // @ts-expect-error
38
38
  if ((_b = result.props) === null || _b === void 0 ? void 0 : _b.disableAutoScroll)
39
39
  return;
40
40
  if (hash) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/theme",
3
- "version": "0.70.0-next.0",
3
+ "version": "0.70.0-next.1",
4
4
  "description": "Shared UI components lib",
5
5
  "keywords": [
6
6
  "theme",
@@ -71,7 +71,7 @@
71
71
  "webpack": "5.105.2"
72
72
  },
73
73
  "dependencies": {
74
- "@redocly/config": "0.56.0",
74
+ "@redocly/config": "0.57.0",
75
75
  "@tanstack/react-query": "5.62.3",
76
76
  "@tanstack/react-virtual": "3.13.0",
77
77
  "@xyflow/react": "12.8.3",
@@ -84,7 +84,7 @@
84
84
  "lodash.debounce": "^4.0.8",
85
85
  "lodash.throttle": "4.1.1",
86
86
  "nprogress": "0.2.0",
87
- "openapi-sampler": "^1.7.5",
87
+ "openapi-sampler": "^1.7.6",
88
88
  "react-calendar": "5.1.0",
89
89
  "react-date-picker": "11.0.0"
90
90
  },
@@ -123,7 +123,9 @@ const StyledButton = styled.button<{
123
123
  height: var(--button-icon-size);
124
124
  }
125
125
 
126
- &:hover {
126
+ /* A button that owns an open menu keeps its hovered appearance. */
127
+ &:hover,
128
+ &[aria-expanded='true'] {
127
129
  background-color: var(--button-bg-color-hover);
128
130
  color: var(--button-color-hover);
129
131
  border-color: var(--button-border-color-hover);
@@ -145,7 +147,8 @@ const StyledButton = styled.button<{
145
147
  border-color: var(--button-border-color-danger);
146
148
  background-color: var(--button-bg-color-danger);
147
149
 
148
- &:hover {
150
+ &:hover,
151
+ &[aria-expanded='true'] {
149
152
  color: var(--button-content-color-danger-hover);
150
153
  border-color: var(--button-border-color-danger-hover);
151
154
  background-color: var(--button-bg-color-danger-hover);
@@ -249,20 +249,29 @@ export const button = css`
249
249
  --button-group-divider-opacity: 1;
250
250
  --button-group-divider-color-disabled: var(--color-warm-grey-2); // @presenter Color
251
251
 
252
- .button-group-primary {
253
- --button-group-divider-color: var(--button-content-color-inverse); // @presenter Color
252
+ .button-group-primary .button {
253
+ --button-group-divider-color: var(--button-color); // @presenter Color
254
254
  --button-group-divider-opacity: 0.32;
255
255
  }
256
256
 
257
- .button-group-secondary {
258
- --button-group-divider-color: var(--button-content-color); // @presenter Color
257
+ .button-group-secondary .button {
258
+ --button-group-divider-color: var(--button-color); // @presenter Color
259
259
  --button-group-divider-opacity: 0.12;
260
260
  }
261
261
 
262
- .button-group-outlined {
262
+ .button-group-outlined .button {
263
263
  --button-group-divider-color: var(--button-border-color); // @presenter Color
264
264
  --button-group-divider-opacity: 1;
265
265
  }
266
266
 
267
+ .button-group-primary .button.button-tone-danger,
268
+ .button-group-secondary .button.button-tone-danger {
269
+ --button-group-divider-color: var(--button-content-color-danger); // @presenter Color
270
+ }
271
+
272
+ .button-group-outlined .button.button-tone-danger {
273
+ --button-group-divider-color: var(--button-border-color-danger); // @presenter Color
274
+ }
275
+
267
276
  // @tokens End
268
277
  `;
@@ -216,13 +216,6 @@ const DropdownWrapper = styled.div`
216
216
  position: relative;
217
217
 
218
218
  text-decoration: none;
219
-
220
- /* The trigger keeps its hovered appearance while the menu is open. */
221
- > .button[aria-expanded='true'] {
222
- background-color: var(--button-bg-color-hover);
223
- color: var(--button-color-hover);
224
- border-color: var(--button-border-color-hover);
225
- }
226
219
  `;
227
220
 
228
221
  const ChildrenWrapper = styled.div<{
@@ -0,0 +1,19 @@
1
+ // Named after the OpenAPI fields, not the labels Replay shows, so renaming a label cannot
2
+ // silently change what a project matches on. Only schemes that take a single credential are
3
+ // here: Replay renders no slot for the rest, which `setValue` could not fill anyway.
4
+ export type ReplaySecurityType = 'oauth2' | 'openIdConnect' | 'apiKey' | 'http-bearer';
5
+
6
+ export type ReplaySecuritySchemeActionsProps = {
7
+ schemeId: string | null;
8
+ securityType: ReplaySecurityType;
9
+ environment: string;
10
+ // Undefined for an operation with no documented id, and in the workflow tab, which has no operation.
11
+ operationId?: string;
12
+ value: string;
13
+ setValue: (value: string) => void;
14
+ apiId?: string;
15
+ };
16
+
17
+ export function ReplaySecuritySchemeActions(_props: ReplaySecuritySchemeActionsProps) {
18
+ return null;
19
+ }
@@ -14,6 +14,7 @@ export type SplitButtonProps = {
14
14
  children: ComponentProps<typeof Dropdown>['children'];
15
15
  variant?: ButtonGroupVariant;
16
16
  size?: ButtonGroupSize;
17
+ tone?: ButtonProps['tone'];
17
18
  placement?: 'top' | 'bottom';
18
19
  alignment?: 'start' | 'end';
19
20
  portalled?: boolean;
@@ -31,6 +32,7 @@ export function SplitButton(props: SplitButtonProps): JSX.Element {
31
32
  children,
32
33
  variant,
33
34
  size,
35
+ tone,
34
36
  placement = 'bottom',
35
37
  alignment = 'end',
36
38
  portalled,
@@ -63,6 +65,7 @@ export function SplitButton(props: SplitButtonProps): JSX.Element {
63
65
  aria-haspopup="menu"
64
66
  variant={variant}
65
67
  size={size}
68
+ tone={tone}
66
69
  disabled={disabled}
67
70
  />
68
71
  }
@@ -132,15 +132,13 @@ const PLACEMENTS = {
132
132
  $withArrow &&
133
133
  css`
134
134
  &::after {
135
- border-left: 14px solid transparent;
136
- border-right: 14px solid transparent;
137
- border-top-width: 8px;
138
- border-top-style: solid;
139
- border-radius: 2px;
135
+ width: 16px;
136
+ height: 8px;
137
+ clip-path: path('M0 0H16L9.414 6.586A2 2 0 0 1 6.586 6.586Z');
140
138
  bottom: 0;
141
- ${$arrowPosition === 'left' && 'left: 16px; transform: translateY(100%);'}
139
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(100%);'}
142
140
  ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 100%);'}
143
- ${$arrowPosition === 'right' && 'right: 16px; transform: translateY(100%);'}
141
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(100%);'}
144
142
  }
145
143
  `}
146
144
  `,
@@ -166,15 +164,13 @@ const PLACEMENTS = {
166
164
  $withArrow &&
167
165
  css`
168
166
  &::after {
169
- border-left: 14px solid transparent;
170
- border-right: 14px solid transparent;
171
- border-bottom-width: 8px;
172
- border-bottom-style: solid;
173
- border-radius: 0 0 2px 2px;
167
+ width: 16px;
168
+ height: 8px;
169
+ clip-path: path('M0 8H16L9.414 1.414A2 2 0 0 0 6.586 1.414Z');
174
170
  top: 0;
175
- ${$arrowPosition === 'left' && 'left: 16px; transform: translateY(-100%);'}
171
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(-100%);'}
176
172
  ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -100%);'}
177
- ${$arrowPosition === 'right' && 'right: 16px; transform: translateY(-100%);'}
173
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(-100%);'}
178
174
  }
179
175
  `}
180
176
  `,
@@ -188,11 +184,9 @@ const PLACEMENTS = {
188
184
  $withArrow &&
189
185
  css`
190
186
  &::after {
191
- border-top: 14px solid transparent;
192
- border-bottom: 14px solid transparent;
193
- border-left-width: 8px;
194
- border-left-style: solid;
195
- border-radius: 2px 0 0 2px;
187
+ width: 8px;
188
+ height: 16px;
189
+ clip-path: path('M0 0V16L6.586 9.414A2 2 0 0 0 6.586 6.586Z');
196
190
  right: -9px;
197
191
  top: 50%;
198
192
  transform: translateY(-50%);
@@ -209,11 +203,9 @@ const PLACEMENTS = {
209
203
  $withArrow &&
210
204
  css`
211
205
  &::after {
212
- border-top: 14px solid transparent;
213
- border-bottom: 14px solid transparent;
214
- border-right-width: 8px;
215
- border-right-style: solid;
216
- border-radius: 0 2px 2px 0;
206
+ width: 8px;
207
+ height: 16px;
208
+ clip-path: path('M8 0V16L1.414 9.414A2 2 0 0 1 1.414 6.586Z');
217
209
  left: -9px;
218
210
  top: 50%;
219
211
  transform: translateY(-50%);
@@ -263,9 +255,7 @@ const TooltipBody = styled.span.attrs<{ $anchorName: string }>(({ $anchorName })
263
255
 
264
256
  content: ' ';
265
257
  display: inline-block;
266
- width: 0;
267
- height: 0;
268
- border-color: var(--tooltip-arrow-color, var(--tooltip-bg-color));
258
+ background: var(--tooltip-arrow-color, var(--tooltip-bg-color));
269
259
  }
270
260
 
271
261
  background: var(--tooltip-bg-color);
@@ -125,15 +125,20 @@ function TooltipComponent({
125
125
 
126
126
  export const Tooltip = memo<PropsWithChildren<TooltipProps>>(TooltipComponent);
127
127
 
128
+ type TooltipArrowProps = {
129
+ $withArrow: boolean;
130
+ $arrowPosition: NonNullable<TooltipProps['arrowPosition']>;
131
+ };
132
+
128
133
  const PLACEMENTS = {
129
- top: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
130
- ${({ withArrow, arrowPosition }) =>
131
- withArrow && arrowPosition === 'left'
134
+ top: css<TooltipArrowProps>`
135
+ ${({ $withArrow, $arrowPosition }) =>
136
+ $withArrow && $arrowPosition === 'left'
132
137
  ? css`
133
138
  transform: translate(0, -100%);
134
139
  margin-top: -10px;
135
140
  `
136
- : arrowPosition === 'right'
141
+ : $arrowPosition === 'right'
137
142
  ? css`
138
143
  transform: translate(-100%, -100%);
139
144
  margin-top: -10px;
@@ -143,30 +148,28 @@ const PLACEMENTS = {
143
148
  margin-top: -10px;
144
149
  `}
145
150
 
146
- ${({ withArrow, arrowPosition }) =>
147
- withArrow &&
151
+ ${({ $withArrow, $arrowPosition }) =>
152
+ $withArrow &&
148
153
  css`
149
154
  &::after {
150
- border-left: 14px solid transparent;
151
- border-right: 14px solid transparent;
152
- border-top-width: 8px;
153
- border-top-style: solid;
154
- border-radius: 2px;
155
+ width: 16px;
156
+ height: 8px;
157
+ clip-path: path('M0 0H16L9.414 6.586A2 2 0 0 1 6.586 6.586Z');
155
158
  bottom: 0;
156
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(99%);'}
157
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
158
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(99%);'}
159
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(99%);'}
160
+ ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, 99%);'}
161
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(99%);'}
159
162
  }
160
163
  `}
161
164
  `,
162
- bottom: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
163
- ${({ withArrow, arrowPosition }) =>
164
- withArrow && arrowPosition === 'left'
165
+ bottom: css<TooltipArrowProps>`
166
+ ${({ $withArrow, $arrowPosition }) =>
167
+ $withArrow && $arrowPosition === 'left'
165
168
  ? css`
166
169
  transform: translate(0, 10px);
167
170
  margin-top: 0;
168
171
  `
169
- : arrowPosition === 'right'
172
+ : $arrowPosition === 'right'
170
173
  ? css`
171
174
  transform: translate(-100%, 10px);
172
175
  margin-top: 0;
@@ -176,61 +179,55 @@ const PLACEMENTS = {
176
179
  margin-top: 0;
177
180
  `}
178
181
 
179
- ${({ withArrow, arrowPosition }) =>
180
- withArrow &&
182
+ ${({ $withArrow, $arrowPosition }) =>
183
+ $withArrow &&
181
184
  css`
182
185
  &::after {
183
- border-left: 14px solid transparent;
184
- border-right: 14px solid transparent;
185
- border-bottom-width: 8px;
186
- border-bottom-style: solid;
187
- border-radius: 0 0 2px 2px;
186
+ width: 16px;
187
+ height: 8px;
188
+ clip-path: path('M0 8H16L9.414 1.414A2 2 0 0 0 6.586 1.414Z');
188
189
  top: 0;
189
- ${arrowPosition === 'left' && 'left: 16px; transform: translateY(-99%);'}
190
- ${arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
191
- ${arrowPosition === 'right' && 'right: 16px; transform: translateY(-99%);'}
190
+ ${$arrowPosition === 'left' && 'left: 22px; transform: translateY(-99%);'}
191
+ ${$arrowPosition === 'center' && 'left: 50%; transform: translate(-50%, -99%);'}
192
+ ${$arrowPosition === 'right' && 'right: 22px; transform: translateY(-99%);'}
192
193
  }
193
194
  `}
194
195
  `,
195
- left: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
196
+ left: css<TooltipArrowProps>`
196
197
  transform: translate(-100%, -50%);
197
198
  margin-left: -10px;
198
199
 
199
- ${({ withArrow, arrowPosition }) =>
200
- withArrow &&
200
+ ${({ $withArrow, $arrowPosition }) =>
201
+ $withArrow &&
201
202
  css`
202
203
  &::after {
203
- border-top: 14px solid transparent;
204
- border-bottom: 14px solid transparent;
205
- border-left-width: 8px;
206
- border-left-style: solid;
207
- border-radius: 2px 0 0 2px;
204
+ width: 8px;
205
+ height: 16px;
206
+ clip-path: path('M0 0V16L6.586 9.414A2 2 0 0 0 6.586 6.586Z');
208
207
  top: 50%;
209
208
  right: 0;
210
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(99%);'}
211
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
212
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(99%);'}
209
+ ${$arrowPosition === 'top' && 'top: 22px; transform: translateX(99%);'}
210
+ ${$arrowPosition === 'center' && 'top: 50%; transform: translate(99%, -50%);'}
211
+ ${$arrowPosition === 'bottom' && 'bottom: 22px; transform: translateX(99%);'}
213
212
  }
214
213
  `}
215
214
  `,
216
- right: css<Pick<TooltipProps, 'withArrow' | 'arrowPosition'>>`
215
+ right: css<TooltipArrowProps>`
217
216
  transform: translate(0, -50%);
218
217
  margin-left: 10px;
219
218
 
220
- ${({ withArrow, arrowPosition }) =>
221
- withArrow &&
219
+ ${({ $withArrow, $arrowPosition }) =>
220
+ $withArrow &&
222
221
  css`
223
222
  &::after {
224
- border-top: 14px solid transparent;
225
- border-bottom: 14px solid transparent;
226
- border-right-width: 8px;
227
- border-right-style: solid;
228
- border-radius: 0 2px 2px 0;
223
+ width: 8px;
224
+ height: 16px;
225
+ clip-path: path('M8 0V16L1.414 9.414A2 2 0 0 1 1.414 6.586Z');
229
226
  top: 50%;
230
227
  left: 0;
231
- ${arrowPosition === 'top' && 'top: 16px; transform: translateX(-99%);'}
232
- ${arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
233
- ${arrowPosition === 'bottom' && 'bottom: 16px; transform: translateX(-99%);'}
228
+ ${$arrowPosition === 'top' && 'top: 22px; transform: translateX(-99%);'}
229
+ ${$arrowPosition === 'center' && 'top: 50%; transform: translate(-99%, -50%);'}
230
+ ${$arrowPosition === 'bottom' && 'bottom: 22px; transform: translateX(-99%);'}
234
231
  }
235
232
  `}
236
233
  `,
@@ -240,12 +237,12 @@ const TooltipWrapper = styled.div`
240
237
  position: relative;
241
238
  display: flex;
242
239
  `;
243
- const TooltipBody = styled.span<{
244
- $placement: NonNullable<TooltipProps['placement']>;
245
- $withArrow: boolean;
246
- $arrowPosition: NonNullable<TooltipProps['arrowPosition']>;
247
- $width?: string;
248
- }>`
240
+ const TooltipBody = styled.span<
241
+ TooltipArrowProps & {
242
+ $placement: NonNullable<TooltipProps['placement']>;
243
+ $width?: string;
244
+ }
245
+ >`
249
246
  display: inline-block;
250
247
 
251
248
  padding: var(--tooltip-padding);
@@ -267,9 +264,7 @@ const TooltipBody = styled.span<{
267
264
 
268
265
  content: ' ';
269
266
  display: inline-block;
270
- width: 0;
271
- height: 0;
272
- border-color: var(--tooltip-arrow-color, var(--tooltip-bg-color));
267
+ background: var(--tooltip-arrow-color, var(--tooltip-bg-color));
273
268
  }
274
269
 
275
270
  background: var(--tooltip-bg-color);
@@ -279,7 +274,5 @@ const TooltipBody = styled.span<{
279
274
  box-shadow: var(--bg-raised-shadow);
280
275
 
281
276
  width: ${({ $width }) => $width || 'max-content'};
282
- ${({ $placement }) => css`
283
- ${PLACEMENTS[$placement]};
284
- `}
277
+ ${({ $placement }) => PLACEMENTS[$placement]}
285
278
  `;
@@ -4,11 +4,10 @@ import type { TooltipProps } from '@redocly/theme/core/types';
4
4
 
5
5
  import { Tooltip as AnchorTooltip } from '@redocly/theme/components/Tooltip/AnchorTooltip';
6
6
  import { Tooltip as JsTooltip } from '@redocly/theme/components/Tooltip/JsTooltip';
7
- import { useThemeHooks } from '@redocly/theme/core/hooks';
7
+ import { useAnchorPositioning } from '@redocly/theme/core/hooks';
8
8
  import { getDefaultFallbackPlacements } from '@redocly/theme/core/utils';
9
9
 
10
10
  function TooltipComponent(props: TooltipProps): React.ReactElement {
11
- const { useAnchorPositioning } = useThemeHooks();
12
11
  const { isSupported } = useAnchorPositioning();
13
12
 
14
13
  const fallbackPlacements =
@@ -1,5 +1,6 @@
1
1
  export * from './use-theme-config';
2
2
  export * from './use-theme-hooks';
3
+ export * from './use-anchor-positioning';
3
4
  export * from './use-mobile-menu';
4
5
  export * from './use-controlled-state';
5
6
  export * from './search/use-recent-searches';
@@ -0,0 +1,3 @@
1
+ import { vi } from 'vitest';
2
+
3
+ export const useAnchorPositioning = vi.fn(() => ({ isSupported: true }));
@@ -3,9 +3,6 @@ import { vi, type MockedFunction } from 'vitest';
3
3
  import type { ThemeHooks } from '../../types/hooks';
4
4
 
5
5
  export const useThemeHooks = vi.fn(() => ({
6
- useAnchorPositioning: vi.fn(() => ({
7
- isSupported: true,
8
- })),
9
6
  useTranslate: vi.fn(() => ({
10
7
  translate: vi.fn((key: string, defaultValue: string | { defaultValue: string }) =>
11
8
  defaultValue
@@ -12,7 +12,7 @@ export function useCatalogEntitySchema({ entity, relatedEntity }: CatalogEntityS
12
12
 
13
13
  try {
14
14
  parsedSchema = JSON.parse(schema);
15
- } catch (error) {
15
+ } catch {
16
16
  parsedSchema = undefined;
17
17
  }
18
18
 
@@ -22,7 +22,7 @@ export function useCatalogEntitySchema({ entity, relatedEntity }: CatalogEntityS
22
22
  parsedApiDefinition = relatedEntity?.metadata?.schema
23
23
  ? (JSON.parse(relatedEntity.metadata.schema) as Record<string, unknown>)
24
24
  : undefined;
25
- } catch (err) {
25
+ } catch {
26
26
  parsedApiDefinition = undefined;
27
27
  }
28
28
 
@@ -8,7 +8,7 @@ export class MockIntersectionObserver {
8
8
  unobserve: (target: HTMLElement) => void;
9
9
  disconnect: () => void;
10
10
 
11
- // @ts-ignore
11
+ // @ts-expect-error
12
12
  constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
13
13
  this.root = null;
14
14
  this.rootMargin = '0px';
@@ -9,7 +9,7 @@ export class MockIntersectionObserver {
9
9
  unobserve: (target: HTMLElement) => void;
10
10
  disconnect: () => void;
11
11
 
12
- // @ts-ignore
12
+ // @ts-expect-error
13
13
  constructor(callback: IntersectionObserverCallback, options?: IntersectionObserverInit) {
14
14
  this.root = null;
15
15
  this.rootMargin = '0px';
@@ -98,7 +98,7 @@ export function useCodeWalkthroughControls(
98
98
  Object.entries(newState).forEach(([id, control]) => {
99
99
  const existingControl = controlsState[id];
100
100
  if (existingControl && existingControl.type === control.type) {
101
- // @ts-ignore
101
+ // @ts-expect-error
102
102
  newState[id] = {
103
103
  ...control,
104
104
  value: existingControl.value,
@@ -55,3 +55,4 @@ export * from './use-toast';
55
55
  export * from './use-toast-logic';
56
56
  export * from './use-banner-telemetry';
57
57
  export * from './use-tooltip-fallback-placement';
58
+ export * from './use-anchor-positioning';
@@ -47,9 +47,9 @@ export function useNestedMenu({ item, labelRef, nestedMenuRef }: NestedMenuProps
47
47
  rect.right <= (window.innerWidth || document.documentElement.clientWidth);
48
48
 
49
49
  // Only scroll if element is in viewport to prevent page jumping
50
- // @ts-ignore
50
+ // @ts-expect-error
51
51
  if (isInViewport && typeof el.scrollIntoViewIfNeeded === 'function') {
52
- // @ts-ignore
52
+ // @ts-expect-error
53
53
  el.scrollIntoViewIfNeeded(centerIfNeeded);
54
54
  }
55
55
  }
@@ -0,0 +1,22 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ export const useAnchorPositioning = (): { isSupported: boolean } => {
4
+ const [isSupported, setIsSupported] = useState(false);
5
+
6
+ useEffect(() => {
7
+ setIsSupported(isAnchorPositioningSupported());
8
+ }, []);
9
+
10
+ return { isSupported };
11
+ };
12
+
13
+ function isAnchorPositioningSupported(): boolean {
14
+ if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
15
+ return false;
16
+ }
17
+ return (
18
+ CSS.supports('anchor-name: --a') &&
19
+ CSS.supports('position-anchor: --a') &&
20
+ CSS.supports('top: anchor(top)')
21
+ );
22
+ }
@@ -6,7 +6,6 @@ import { ThemeDataContext } from '../contexts/ThemeDataContext';
6
6
  import { useTelemetryFallback } from './use-telemetry-fallback';
7
7
 
8
8
  const fallbacks = {
9
- useAnchorPositioning: () => ({ isSupported: false }),
10
9
  useTranslate: () => ({
11
10
  translate: (value?: string, options?: { defaultValue: string } | string) =>
12
11
  (typeof options === 'string' ? options : options?.defaultValue) || value || '',
@@ -44,7 +44,6 @@ import type { BreadcrumbItem } from './breadcrumb';
44
44
  import type { AiSearchError } from '../constants/search';
45
45
 
46
46
  export type ThemeHooks = {
47
- useAnchorPositioning: () => { isSupported: boolean };
48
47
  useTranslate: () => { translate: TFunction };
49
48
  useTranslationKeys: () => string[];
50
49
  /**
@@ -25,9 +25,9 @@ export async function loadAndNavigate({
25
25
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
26
26
  const loader = (window as any)['__LOADER'];
27
27
  const result = await withLoadProgress(loader.tryLoad(pathname));
28
- // @ts-ignore
28
+ // @ts-expect-error
29
29
  if (result?.redirectTo) {
30
- // @ts-ignore
30
+ // @ts-expect-error
31
31
  return loadAndNavigate({ navigate, to: result.redirectTo, origin, options });
32
32
  }
33
33
 
@@ -40,7 +40,7 @@ export async function loadAndNavigate({
40
40
  unstable_flushSync: true,
41
41
  } as NavigateOptions & { unstable_flushSync: boolean });
42
42
  }
43
- // @ts-ignore
43
+ // @ts-expect-error
44
44
  if (result.props?.disableAutoScroll) return;
45
45
 
46
46
  if (hash) {