@atlaskit/renderer 133.14.2 → 133.16.0

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 (34) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-products/tsconfig.json +3 -0
  4. package/dist/cjs/messages.js +13 -1
  5. package/dist/cjs/react/nodes/heading.compiled.css +12 -0
  6. package/dist/cjs/react/nodes/heading.js +188 -48
  7. package/dist/cjs/ui/Renderer/RendererStyleContainer.js +8 -1
  8. package/dist/cjs/ui/Renderer/index.js +8 -2
  9. package/dist/cjs/ui/collapsible-headings-dom.js +138 -0
  10. package/dist/cjs/ui/collapsible-headings-section-model.js +38 -0
  11. package/dist/cjs/ui/collapsible-headings.js +232 -0
  12. package/dist/es2019/messages.js +12 -0
  13. package/dist/es2019/react/nodes/heading.compiled.css +12 -0
  14. package/dist/es2019/react/nodes/heading.js +142 -32
  15. package/dist/es2019/ui/Renderer/RendererStyleContainer.js +8 -0
  16. package/dist/es2019/ui/Renderer/index.js +8 -2
  17. package/dist/es2019/ui/collapsible-headings-dom.js +118 -0
  18. package/dist/es2019/ui/collapsible-headings-section-model.js +32 -0
  19. package/dist/es2019/ui/collapsible-headings.js +183 -0
  20. package/dist/esm/messages.js +12 -0
  21. package/dist/esm/react/nodes/heading.compiled.css +12 -0
  22. package/dist/esm/react/nodes/heading.js +188 -46
  23. package/dist/esm/ui/Renderer/RendererStyleContainer.js +8 -1
  24. package/dist/esm/ui/Renderer/index.js +8 -2
  25. package/dist/esm/ui/collapsible-headings-dom.js +129 -0
  26. package/dist/esm/ui/collapsible-headings-section-model.js +32 -0
  27. package/dist/esm/ui/collapsible-headings.js +221 -0
  28. package/dist/types/messages.d.ts +23 -21
  29. package/dist/types/react/nodes/heading.d.ts +3 -2
  30. package/dist/types/ui/collapsible-headings-dom.d.ts +14 -0
  31. package/dist/types/ui/collapsible-headings-section-model.d.ts +9 -0
  32. package/dist/types/ui/collapsible-headings.d.ts +26 -0
  33. package/dist/types/ui/renderer-props.d.ts +7 -0
  34. package/package.json +14 -13
@@ -1,19 +1,24 @@
1
+ /* heading.tsx generated by @compiled/babel-plugin v0.40.0 */
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
3
  import _typeof from "@babel/runtime/helpers/typeof";
2
- /**
3
- * @jsxRuntime classic
4
- * @jsx jsx
5
- */
4
+ import "./heading.compiled.css";
5
+ import { ax, ix } from "@compiled/react/runtime";
6
6
  import React from 'react';
7
+ import { useIntl } from 'react-intl';
8
+ import { IconButton } from '@atlaskit/button/new';
9
+ import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
10
+ import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
7
11
  import { abortAll } from '@atlaskit/react-ufo/interaction-metrics';
8
12
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
9
13
  import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
10
14
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
11
15
  import AnalyticsContext from '../../analytics/analyticsContext';
12
16
  import { copyTextToClipboard } from '../utils/clipboard';
17
+ import { collapsibleHeadingMessages } from '../../messages';
18
+ import { useCollapsibleHeading } from '../../ui/collapsible-headings';
13
19
  import HeadingAnchor from './heading-anchor';
14
- // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
15
- import { css, jsx } from '@emotion/react';
16
20
  var RENDERER_HEADING_WRAPPER = 'renderer-heading-wrapper';
21
+ var RENDERER_COLLAPSIBLE_HEADING_WRAPPER = 'renderer-collapsible-heading-wrapper';
17
22
  var getCurrentUrlWithHash = function getCurrentUrlWithHash() {
18
23
  var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
19
24
  var url = new URL(window.location.href);
@@ -29,13 +34,29 @@ function hasRightAlignmentMark(marks) {
29
34
  return mark.type.name === 'alignment' && mark.attrs.align === 'end';
30
35
  });
31
36
  }
32
- var wrapperStyles = css({
33
- // Important: do NOT use flex here.
34
- // With flex + baseline alignment, the anchor aligns to the *first line* of a multi-line heading,
35
- // which visually places it at the top-right. We want the anchor to sit immediately after the
36
- // last character of the heading (i.e. after the final wrapped line), so we use normal inline flow.
37
- display: 'block'
38
- });
37
+ var wrapperStyles = null;
38
+ var collapsibleHeadingWrapperStyles = null;
39
+ var collapsibleHeadingButtonStyles = null;
40
+ var collapsibleHeadingButtonHiddenStyles = null;
41
+ var ChevronDownSmallIcon = function ChevronDownSmallIcon() {
42
+ return /*#__PURE__*/React.createElement(ChevronDownIcon, {
43
+ label: "",
44
+ size: "small"
45
+ });
46
+ };
47
+ var ChevronRightSmallIcon = function ChevronRightSmallIcon() {
48
+ return /*#__PURE__*/React.createElement(ChevronRightIcon, {
49
+ label: "",
50
+ size: "small"
51
+ });
52
+ };
53
+ var hasFocusVisible = function hasFocusVisible(target) {
54
+ try {
55
+ return target.matches(':focus-visible');
56
+ } catch (_unused) {
57
+ return true;
58
+ }
59
+ };
39
60
  var getHeadingAnchorLinksConfig = function getHeadingAnchorLinksConfig(allowHeadingAnchorLinks) {
40
61
  return _typeof(allowHeadingAnchorLinks) === 'object' ? allowHeadingAnchorLinks : undefined;
41
62
  };
@@ -45,9 +66,9 @@ function WrappedHeadingAnchor(_ref) {
45
66
  level = _ref.level,
46
67
  headingId = _ref.headingId,
47
68
  hideFromScreenReader = _ref.hideFromScreenReader;
48
- return jsx(AnalyticsContext.Consumer, null, function (_ref2) {
69
+ return /*#__PURE__*/React.createElement(AnalyticsContext.Consumer, null, function (_ref2) {
49
70
  var fireAnalyticsEvent = _ref2.fireAnalyticsEvent;
50
- return jsx(HeadingAnchor, {
71
+ return /*#__PURE__*/React.createElement(HeadingAnchor, {
51
72
  enableNestedHeaderLinks: enableNestedHeaderLinks,
52
73
  level: level
53
74
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
@@ -67,6 +88,88 @@ function WrappedHeadingAnchor(_ref) {
67
88
  });
68
89
  });
69
90
  }
91
+ function CollapsibleHeadingButton(_ref3) {
92
+ var collapsibleHeading = _ref3.collapsibleHeading,
93
+ isHeadingHovered = _ref3.isHeadingHovered;
94
+ var intl = useIntl();
95
+ var _React$useState = React.useState(false),
96
+ _React$useState2 = _slicedToArray(_React$useState, 2),
97
+ isFocused = _React$useState2[0],
98
+ setIsFocused = _React$useState2[1];
99
+ var isCollapsed = collapsibleHeading.isCollapsed,
100
+ toggle = collapsibleHeading.toggle;
101
+ var isVisible = isCollapsed || isFocused || isHeadingHovered;
102
+ var handleClick = React.useCallback(function (event) {
103
+ event.stopPropagation();
104
+ toggle();
105
+ }, [toggle]);
106
+ var handleFocus = React.useCallback(function (event) {
107
+ setIsFocused(hasFocusVisible(event.target));
108
+ }, []);
109
+ var handleBlur = React.useCallback(function () {
110
+ return setIsFocused(false);
111
+ }, []);
112
+ var handleKeyDown = React.useCallback(function () {
113
+ return setIsFocused(true);
114
+ }, []);
115
+ return /*#__PURE__*/React.createElement("span", {
116
+ className: ax(["_kqswstnw _152tidpf _1e02idpf _1pbykb7n", !isVisible && "_tzy4idpf _lcxvglyw _tza3kb7n _12yg1wug _xrqrkb7n _l4c51wug"])
117
+ }, /*#__PURE__*/React.createElement(IconButton, {
118
+ appearance: "subtle",
119
+ spacing: "compact",
120
+ icon: isCollapsed ? ChevronRightSmallIcon : ChevronDownSmallIcon,
121
+ label: intl.formatMessage(isCollapsed ? collapsibleHeadingMessages.expandSection : collapsibleHeadingMessages.collapseSection),
122
+ "aria-expanded": !isCollapsed,
123
+ isTooltipDisabled: false,
124
+ testId: "collapsible-heading-button",
125
+ onClick: handleClick,
126
+ onFocus: handleFocus,
127
+ onBlur: handleBlur,
128
+ onKeyDown: handleKeyDown
129
+ }));
130
+ }
131
+ function CollapsibleHeadingContainer(_ref4) {
132
+ var children = _ref4.children,
133
+ collapsibleHeading = _ref4.collapsibleHeading,
134
+ headingLevel = _ref4.headingLevel;
135
+ var mouseEntered = React.useRef(false);
136
+ var _React$useState3 = React.useState(false),
137
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
138
+ isHovered = _React$useState4[0],
139
+ setIsHovered = _React$useState4[1];
140
+ var _React$useState5 = React.useState(false),
141
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
142
+ isFocused = _React$useState6[0],
143
+ setIsFocused = _React$useState6[1];
144
+ var mouseEnterHandler = function mouseEnterHandler() {
145
+ if (!mouseEntered.current) {
146
+ abortAll('new_interaction');
147
+ mouseEntered.current = true;
148
+ }
149
+ };
150
+ return /*#__PURE__*/React.createElement("div", {
151
+ "data-testid": RENDERER_COLLAPSIBLE_HEADING_WRAPPER,
152
+ "data-level": headingLevel,
153
+ onMouseEnter: function onMouseEnter() {
154
+ mouseEnterHandler();
155
+ setIsHovered(true);
156
+ },
157
+ onMouseLeave: function onMouseLeave() {
158
+ return setIsHovered(false);
159
+ },
160
+ onFocus: function onFocus(event) {
161
+ return setIsFocused(hasFocusVisible(event.target));
162
+ },
163
+ onBlur: function onBlur() {
164
+ return setIsFocused(false);
165
+ },
166
+ className: ax(["_ahbqukr8 _bozgxy5q _kqswh2mm"])
167
+ }, /*#__PURE__*/React.createElement(CollapsibleHeadingButton, {
168
+ collapsibleHeading: collapsibleHeading,
169
+ isHeadingHovered: isHovered || isFocused
170
+ }), children);
171
+ }
172
+
70
173
  /**
71
174
  * Old heading structure (before a11y fix):
72
175
  * - headning anchor is rendered INSIDE the heading element
@@ -99,28 +202,28 @@ function HeadingWithDuplicateAnchor(props) {
99
202
  mouseEntered.current = true;
100
203
  }
101
204
  };
102
- return jsx(React.Fragment, null, jsx(HX, {
205
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(HX, {
103
206
  id: headingIdToUse,
104
207
  "data-local-id": localId,
105
208
  "data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
106
209
  "data-as-inline": asInline,
107
210
  onMouseEnter: mouseEnterHandler,
108
211
  tabIndex: -1
109
- }, jsx(React.Fragment, null, showAnchorLink && headingId && isRightAligned && jsx(WrappedHeadingAnchor, {
212
+ }, /*#__PURE__*/React.createElement(React.Fragment, null, showAnchorLink && headingId && isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
110
213
  level: props.level,
111
214
  enableNestedHeaderLinks: enableNestedHeaderLinks,
112
215
  getHeadingLink: getHeadingLink,
113
216
  headingId: headingId,
114
217
  hideFromScreenReader: true
115
- }), props.children, showAnchorLink && headingId && !isRightAligned && jsx(WrappedHeadingAnchor, {
218
+ }), props.children, showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
116
219
  level: props.level,
117
220
  enableNestedHeaderLinks: enableNestedHeaderLinks,
118
221
  getHeadingLink: getHeadingLink,
119
222
  headingId: headingId,
120
223
  hideFromScreenReader: true
121
- }))), jsx(VisuallyHidden, {
224
+ }))), /*#__PURE__*/React.createElement(VisuallyHidden, {
122
225
  testId: "visually-hidden-heading-anchor"
123
- }, showAnchorLink && headingId && jsx(WrappedHeadingAnchor, {
226
+ }, showAnchorLink && headingId && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
124
227
  level: props.level,
125
228
  enableNestedHeaderLinks: enableNestedHeaderLinks,
126
229
  getHeadingLink: getHeadingLink,
@@ -141,9 +244,18 @@ function HeadingWithWrapper(props) {
141
244
  marks = props.marks,
142
245
  invisible = props.invisible,
143
246
  localId = props.localId,
144
- asInline = props.asInline;
247
+ asInline = props.asInline,
248
+ collapsibleHeading = props.collapsibleHeading;
145
249
  var HX = "h".concat(props.level);
146
250
  var mouseEntered = React.useRef(false);
251
+ var _React$useState7 = React.useState(false),
252
+ _React$useState8 = _slicedToArray(_React$useState7, 2),
253
+ isHovered = _React$useState8[0],
254
+ setIsHovered = _React$useState8[1];
255
+ var _React$useState9 = React.useState(false),
256
+ _React$useState0 = _slicedToArray(_React$useState9, 2),
257
+ isFocused = _React$useState0[0],
258
+ setIsFocused = _React$useState0[1];
147
259
  var showAnchorLink = !!props.showAnchorLink;
148
260
  var isRightAligned = hasRightAlignmentMark(marks);
149
261
  var headingAnchorLinksConfig = getHeadingAnchorLinksConfig(allowHeadingAnchorLinks);
@@ -151,7 +263,7 @@ function HeadingWithWrapper(props) {
151
263
  var getHeadingLink = headingAnchorLinksConfig === null || headingAnchorLinksConfig === void 0 ? void 0 : headingAnchorLinksConfig.getHeadingLink;
152
264
  var headingIdToUse = invisible ? undefined : headingId;
153
265
  var mouseEnterHandler = function mouseEnterHandler() {
154
- if (showAnchorLink && !mouseEntered.current) {
266
+ if ((showAnchorLink || collapsibleHeading) && !mouseEntered.current) {
155
267
  // Abort TTVC calculation when the mouse hovers over heading. Hovering over
156
268
  // heading render heading anchor and inline comment buttons. These user-induced
157
269
  // DOM changes are valid reasons to abort the TTVC calculation.
@@ -159,26 +271,45 @@ function HeadingWithWrapper(props) {
159
271
  mouseEntered.current = true;
160
272
  }
161
273
  };
162
- return jsx("div", {
274
+ var handleWrapperMouseEnter = function handleWrapperMouseEnter() {
275
+ mouseEnterHandler();
276
+ setIsHovered(true);
277
+ };
278
+ var handleWrapperMouseLeave = function handleWrapperMouseLeave() {
279
+ return setIsHovered(false);
280
+ };
281
+ var handleWrapperFocus = function handleWrapperFocus(event) {
282
+ return setIsFocused(hasFocusVisible(event.target));
283
+ };
284
+ var handleWrapperBlur = function handleWrapperBlur() {
285
+ return setIsFocused(false);
286
+ };
287
+ return /*#__PURE__*/React.createElement("div", {
163
288
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
164
- className: RENDERER_HEADING_WRAPPER,
289
+ className: ax(["_1e0c1ule", collapsibleHeading && "_ahbqukr8 _bozgxy5q _kqswh2mm", RENDERER_HEADING_WRAPPER]),
165
290
  "data-testid": RENDERER_HEADING_WRAPPER,
166
291
  "data-level": props.level,
167
- css: wrapperStyles
168
- }, showAnchorLink && headingId && isRightAligned && jsx(WrappedHeadingAnchor, {
292
+ onMouseEnter: collapsibleHeading ? handleWrapperMouseEnter : undefined,
293
+ onMouseLeave: collapsibleHeading ? handleWrapperMouseLeave : undefined,
294
+ onFocus: collapsibleHeading ? handleWrapperFocus : undefined,
295
+ onBlur: collapsibleHeading ? handleWrapperBlur : undefined
296
+ }, collapsibleHeading && /*#__PURE__*/React.createElement(CollapsibleHeadingButton, {
297
+ collapsibleHeading: collapsibleHeading,
298
+ isHeadingHovered: isHovered || isFocused
299
+ }), showAnchorLink && headingId && isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
169
300
  level: props.level,
170
301
  enableNestedHeaderLinks: enableNestedHeaderLinks,
171
302
  getHeadingLink: getHeadingLink,
172
303
  headingId: headingId,
173
304
  hideFromScreenReader: false
174
- }), jsx(HX, {
305
+ }), /*#__PURE__*/React.createElement(HX, {
175
306
  id: headingIdToUse,
176
307
  "data-local-id": localId,
177
308
  "data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
178
309
  "data-as-inline": asInline,
179
- onMouseEnter: mouseEnterHandler,
310
+ onMouseEnter: collapsibleHeading ? undefined : mouseEnterHandler,
180
311
  tabIndex: -1
181
- }, props.children), showAnchorLink && headingId && !isRightAligned && jsx(WrappedHeadingAnchor, {
312
+ }, props.children), showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
182
313
  level: props.level,
183
314
  enableNestedHeaderLinks: enableNestedHeaderLinks,
184
315
  getHeadingLink: getHeadingLink,
@@ -191,23 +322,26 @@ function HeadingWithWrapper(props) {
191
322
  * Gated Heading component:
192
323
  * - When platform_editor_copy_link_a11y_inconsistency_fix experiment is enabled,
193
324
  * returns HeadingWithWrapper (new a11y-improved structure)
194
- * - Otherwise returns HeadingWithDuplicateAnchor (old structure)
325
+ * - Otherwise preserves HeadingWithDuplicateAnchor (old structure), adding only the collapse
326
+ * container when the top-level heading is collapsible
195
327
  */
196
- function Heading(_ref3) {
197
- var allowHeadingAnchorLinks = _ref3.allowHeadingAnchorLinks,
198
- children = _ref3.children,
199
- dataAttributes = _ref3.dataAttributes,
200
- headingId = _ref3.headingId,
201
- invisible = _ref3.invisible,
202
- level = _ref3.level,
203
- localId = _ref3.localId,
204
- marks = _ref3.marks,
205
- nodeType = _ref3.nodeType,
206
- showAnchorLink = _ref3.showAnchorLink,
207
- serializer = _ref3.serializer,
208
- asInline = _ref3.asInline;
328
+ function Heading(_ref5) {
329
+ var allowHeadingAnchorLinks = _ref5.allowHeadingAnchorLinks,
330
+ children = _ref5.children,
331
+ dataAttributes = _ref5.dataAttributes,
332
+ headingId = _ref5.headingId,
333
+ invisible = _ref5.invisible,
334
+ level = _ref5.level,
335
+ localId = _ref5.localId,
336
+ marks = _ref5.marks,
337
+ nodeType = _ref5.nodeType,
338
+ path = _ref5.path,
339
+ showAnchorLink = _ref5.showAnchorLink,
340
+ serializer = _ref5.serializer,
341
+ asInline = _ref5.asInline;
342
+ var collapsibleHeading = useCollapsibleHeading(dataAttributes['data-renderer-start-pos'], (path === null || path === void 0 ? void 0 : path.length) === 0);
209
343
  if (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true)) {
210
- return jsx(HeadingWithWrapper, {
344
+ return /*#__PURE__*/React.createElement(HeadingWithWrapper, {
211
345
  allowHeadingAnchorLinks: allowHeadingAnchorLinks,
212
346
  dataAttributes: dataAttributes,
213
347
  headingId: headingId,
@@ -218,10 +352,11 @@ function Heading(_ref3) {
218
352
  nodeType: nodeType,
219
353
  serializer: serializer,
220
354
  showAnchorLink: showAnchorLink,
221
- asInline: asInline
355
+ asInline: asInline,
356
+ collapsibleHeading: collapsibleHeading
222
357
  }, children);
223
358
  }
224
- return jsx(HeadingWithDuplicateAnchor, {
359
+ var headingWithDuplicateAnchor = /*#__PURE__*/React.createElement(HeadingWithDuplicateAnchor, {
225
360
  allowHeadingAnchorLinks: allowHeadingAnchorLinks,
226
361
  dataAttributes: dataAttributes,
227
362
  headingId: headingId,
@@ -234,5 +369,12 @@ function Heading(_ref3) {
234
369
  showAnchorLink: showAnchorLink,
235
370
  asInline: asInline
236
371
  }, children);
372
+ if (collapsibleHeading) {
373
+ return /*#__PURE__*/React.createElement(CollapsibleHeadingContainer, {
374
+ collapsibleHeading: collapsibleHeading,
375
+ headingLevel: level
376
+ }, headingWithDuplicateAnchor);
377
+ }
378
+ return headingWithDuplicateAnchor;
237
379
  }
238
380
  export default Heading;
@@ -32,6 +32,7 @@ import { EmojiSharedCssClassName, defaultEmojiHeight, defaultDenseEmojiHeight, d
32
32
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
33
33
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
34
34
  import { BodiedSyncBlockSharedCssClassName, SyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
35
+ import { COLLAPSED_CONTENT_OWNERS_ATTRIBUTE } from '../collapsible-headings-dom';
35
36
  var wrappedMediaBreakoutPoint = 410;
36
37
  var TELEPOINTER_ID = 'ai-streaming-telepointer';
37
38
  var tableShadowWidth = 32;
@@ -88,7 +89,13 @@ var baseStyles = css(_defineProperty(_defineProperty(_defineProperty(_defineProp
88
89
  display: 'block',
89
90
  height: 0,
90
91
  clear: 'both'
91
- }), ".".concat(RendererCssClassName.DOCUMENT), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ".".concat(INLINE_IMAGE_WRAPPER_CLASS_NAME), {
92
+ }), ".".concat(RendererCssClassName.DOCUMENT), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "> [".concat(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, "][hidden='until-found']"), {
93
+ display: 'block',
94
+ minBlockSize: 0,
95
+ marginBlock: 0,
96
+ paddingBlock: 0,
97
+ borderBlockWidth: 0
98
+ }), ".".concat(INLINE_IMAGE_WRAPPER_CLASS_NAME), {
92
99
  height: '22px',
93
100
  transform: "translateY(-2px)"
94
101
  }), "h1", _defineProperty({}, "> .mediaInlineView-content-wrap > .".concat(INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > :is(a, span[data-mark-type='border']) .mediaInlineView-content-wrap > .").concat(INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > .").concat(INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > :is(a, span[data-mark-type='border']) .").concat(INLINE_IMAGE_WRAPPER_CLASS_NAME), {
@@ -41,6 +41,7 @@ import { RendererContext as ActionsContext, RendererActionsContext } from '../Re
41
41
  import { Provider as SmartCardStorageProvider } from '../SmartCardStorage';
42
42
  import { ActiveHeaderIdProvider } from '../active-header-id-provider';
43
43
  import { AnnotationsPositionContext, AnnotationsWrapper } from '../annotations';
44
+ import { CollapsibleHeadingsProvider } from '../collapsible-headings';
44
45
  import { ErrorBoundary } from './ErrorBoundary';
45
46
  import { BreakoutSSRInlineScript } from './breakout-ssr';
46
47
  import { isInteractiveElement } from './click-to-edit';
@@ -63,7 +64,7 @@ export var DEGRADED_SEVERITY_THRESHOLD = 3000;
63
64
  var TABLE_INFO_TIMEOUT = 10000;
64
65
  var RENDER_EVENT_SAMPLE_RATE = 0.1;
65
66
  var packageName = "@atlaskit/renderer";
66
- var packageVersion = "133.14.1";
67
+ var packageVersion = "133.15.0";
67
68
  var setAsQueryContainerStyles = css({
68
69
  containerName: 'ak-renderer-wrapper',
69
70
  containerType: 'inline-size'
@@ -459,6 +460,7 @@ export var RendererFunctionalComponent = function RendererFunctionalComponent(pr
459
460
  timeZone: props.timeZone
460
461
  });
461
462
  }, [props.featureFlags, props.isTopLevelRenderer, createRendererContext, props.timeZone]);
463
+ var isCollapsibleHeadingsEnabled = props.allowCollapsibleHeadings === true && ['full-page', 'full-width', 'max'].includes(props.appearance || '') && rendererContext.isTopLevelRenderer && expValEquals('platform_renderer_collapsible_headings', 'isEnabled', true);
462
464
  useScrollToBlock(editorRef, props.document, props.scrollToBlock);
463
465
  try {
464
466
  var _rendererContext$feat, _props$media;
@@ -518,7 +520,11 @@ export var RendererFunctionalComponent = function RendererFunctionalComponent(pr
518
520
  doc: pmDoc,
519
521
  schema: schema,
520
522
  onAnalyticsEvent: _fireAnalyticsEvent
521
- }, result)))))));
523
+ }, jsx(CollapsibleHeadingsProvider, {
524
+ pmDocument: pmDoc,
525
+ rendererRef: editorRef,
526
+ isEnabled: isCollapsibleHeadingsEnabled
527
+ }, result))))))));
522
528
  var rendererResult = props.truncated ? jsx(TruncatedWrapper, {
523
529
  height: props.maxHeight,
524
530
  fadeHeight: props.fadeOutHeight
@@ -0,0 +1,129 @@
1
+ var RENDERER_DOCUMENT_SELECTOR = '.ak-renderer-document';
2
+ var RENDERER_START_POS_ATTRIBUTE = 'data-renderer-start-pos';
3
+ var HEADING_SELECTOR = [1, 2, 3, 4, 5, 6].map(function (level) {
4
+ return "h".concat(level, "[").concat(RENDERER_START_POS_ATTRIBUTE, "]");
5
+ }).join(',');
6
+ export var COLLAPSED_CONTENT_OWNERS_ATTRIBUTE = 'data-renderer-collapsed-content-owners';
7
+ function getDirectRendererChild(rendererDocument, element) {
8
+ var _currentElement;
9
+ var currentElement = element;
10
+ while (currentElement && currentElement.parentElement !== rendererDocument) {
11
+ currentElement = currentElement.parentElement;
12
+ }
13
+ return ((_currentElement = currentElement) === null || _currentElement === void 0 ? void 0 : _currentElement.parentElement) === rendererDocument ? currentElement : null;
14
+ }
15
+ function getTopLevelHeadingPositionsByContainer(rendererDocument, topLevelHeadingPositions) {
16
+ var headingPositionsByContainer = new Map();
17
+ rendererDocument.querySelectorAll(HEADING_SELECTOR).forEach(function (headingElement) {
18
+ if (headingElement.closest(RENDERER_DOCUMENT_SELECTOR) !== rendererDocument) {
19
+ return;
20
+ }
21
+ var position = Number(headingElement.getAttribute(RENDERER_START_POS_ATTRIBUTE));
22
+ if (!Number.isFinite(position) || !topLevelHeadingPositions.has(position)) {
23
+ return;
24
+ }
25
+ var headingContainer = getDirectRendererChild(rendererDocument, headingElement);
26
+ if (headingContainer) {
27
+ headingPositionsByContainer.set(headingContainer, position);
28
+ }
29
+ });
30
+ return headingPositionsByContainer;
31
+ }
32
+ function restoreHiddenAttribute(element, originalHiddenAttributes) {
33
+ if (!originalHiddenAttributes.has(element)) {
34
+ return;
35
+ }
36
+ var originalHiddenAttribute = originalHiddenAttributes.get(element);
37
+ if (originalHiddenAttribute === null || originalHiddenAttribute === undefined) {
38
+ element.removeAttribute('hidden');
39
+ } else {
40
+ element.setAttribute('hidden', originalHiddenAttribute);
41
+ }
42
+ originalHiddenAttributes.delete(element);
43
+ }
44
+ function setCollapsedOwners(element, owners, originalHiddenAttributes) {
45
+ if (!originalHiddenAttributes.has(element)) {
46
+ originalHiddenAttributes.set(element, element.getAttribute('hidden'));
47
+ }
48
+ element.setAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, Array.from(owners).join(','));
49
+ element.setAttribute('hidden', 'until-found');
50
+ }
51
+ function getDesiredCollapsedContentOwners(rendererDocuments, collapsedHeadings, sections) {
52
+ var desiredOwners = new Map();
53
+ if (collapsedHeadings.size === 0) {
54
+ return desiredOwners;
55
+ }
56
+ var topLevelHeadingPositions = new Set(sections.map(function (section) {
57
+ return section.headingPos;
58
+ }));
59
+ var sectionsByHeadingPosition = new Map(sections.map(function (section) {
60
+ return [section.headingPos, section];
61
+ }));
62
+ rendererDocuments.forEach(function (rendererDocument) {
63
+ // Index headings once, then reconcile every top-level renderer child in DOM order.
64
+ var headingPositionsByContainer = getTopLevelHeadingPositionsByContainer(rendererDocument, topLevelHeadingPositions);
65
+ var activeCollapsedSections = [];
66
+ var contentElements = Array.from(rendererDocument.children);
67
+ contentElements.forEach(function (contentElement) {
68
+ var headingPosition = headingPositionsByContainer.get(contentElement);
69
+ if (headingPosition !== undefined) {
70
+ activeCollapsedSections = activeCollapsedSections.filter(function (section) {
71
+ return section.to > headingPosition;
72
+ });
73
+ }
74
+ if (activeCollapsedSections.length > 0) {
75
+ desiredOwners.set(contentElement, new Set(activeCollapsedSections.map(function (section) {
76
+ return section.headingPos;
77
+ })));
78
+ }
79
+ if (headingPosition !== undefined && collapsedHeadings.has(headingPosition)) {
80
+ var section = sectionsByHeadingPosition.get(headingPosition);
81
+ if (section) {
82
+ activeCollapsedSections.push(section);
83
+ }
84
+ }
85
+ });
86
+ });
87
+ return desiredOwners;
88
+ }
89
+
90
+ /** Returns renderer documents owned by this renderer root, excluding nested renderers. */
91
+ export function getOwnedRendererDocuments(rendererRoot) {
92
+ return Array.from(rendererRoot.querySelectorAll(RENDERER_DOCUMENT_SELECTOR)).filter(function (rendererDocument) {
93
+ var _rendererDocument$par;
94
+ var parentRendererDocument = (_rendererDocument$par = rendererDocument.parentElement) === null || _rendererDocument$par === void 0 ? void 0 : _rendererDocument$par.closest(RENDERER_DOCUMENT_SELECTOR);
95
+ return !parentRendererDocument || !rendererRoot.contains(parentRendererDocument);
96
+ });
97
+ }
98
+
99
+ /** Applies only the visibility-attribute differences required by the collapsed section model. */
100
+ export function reconcileCollapsedHeadingContent(_ref) {
101
+ var collapsedHeadings = _ref.collapsedHeadings,
102
+ originalHiddenAttributes = _ref.originalHiddenAttributes,
103
+ rendererRoot = _ref.rendererRoot,
104
+ sections = _ref.sections;
105
+ var rendererDocuments = getOwnedRendererDocuments(rendererRoot);
106
+ var desiredOwners = getDesiredCollapsedContentOwners(rendererDocuments, collapsedHeadings, sections);
107
+ rendererDocuments.forEach(function (rendererDocument) {
108
+ rendererDocument.querySelectorAll("[".concat(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, "]")).forEach(function (element) {
109
+ if (element.closest(RENDERER_DOCUMENT_SELECTOR) === rendererDocument && !desiredOwners.has(element)) {
110
+ element.removeAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE);
111
+ restoreHiddenAttribute(element, originalHiddenAttributes);
112
+ }
113
+ });
114
+ });
115
+ desiredOwners.forEach(function (owners, element) {
116
+ var desiredOwnersAttribute = Array.from(owners).join(',');
117
+ if (element.getAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE) !== desiredOwnersAttribute || element.getAttribute('hidden') !== 'until-found') {
118
+ setCollapsedOwners(element, owners, originalHiddenAttributes);
119
+ }
120
+ });
121
+ }
122
+
123
+ /** Returns the collapsed heading positions that currently hide an element. */
124
+ export function getCollapsedContentOwners(element) {
125
+ var _element$getAttribute;
126
+ return ((_element$getAttribute = element.getAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE)) !== null && _element$getAttribute !== void 0 ? _element$getAttribute : '').split(',').filter(function (owner) {
127
+ return owner !== '';
128
+ }).map(Number).filter(Number.isFinite);
129
+ }
@@ -0,0 +1,32 @@
1
+ var RENDERER_DOCUMENT_POSITION_OFFSET = 1;
2
+ /** Builds collapsible ranges for headings that are direct children of the renderer document. */
3
+ export function buildTopLevelHeadingSections(pmDocument) {
4
+ if (!pmDocument) {
5
+ return [];
6
+ }
7
+ var sections = [];
8
+ var openSections = [];
9
+ var documentEnd = pmDocument.content.size + RENDERER_DOCUMENT_POSITION_OFFSET;
10
+ pmDocument.forEach(function (node, offset) {
11
+ if (node.type.name !== 'heading') {
12
+ return;
13
+ }
14
+ var headingPos = offset + RENDERER_DOCUMENT_POSITION_OFFSET;
15
+ var level = Number(node.attrs.level);
16
+ while (openSections.length > 0 && openSections[openSections.length - 1].level >= level) {
17
+ var _section = openSections.pop();
18
+ if (_section) {
19
+ _section.to = headingPos;
20
+ }
21
+ }
22
+ var section = {
23
+ contentFrom: headingPos + node.nodeSize,
24
+ headingPos: headingPos,
25
+ level: level,
26
+ to: documentEnd
27
+ };
28
+ sections.push(section);
29
+ openSections.push(section);
30
+ });
31
+ return sections;
32
+ }