@atlaskit/renderer 133.14.1 → 133.15.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 (33) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/dist/cjs/messages.js +13 -1
  4. package/dist/cjs/react/nodes/heading.compiled.css +12 -0
  5. package/dist/cjs/react/nodes/heading.js +188 -48
  6. package/dist/cjs/ui/Renderer/RendererStyleContainer.js +8 -1
  7. package/dist/cjs/ui/Renderer/index.js +8 -2
  8. package/dist/cjs/ui/collapsible-headings-dom.js +138 -0
  9. package/dist/cjs/ui/collapsible-headings-section-model.js +38 -0
  10. package/dist/cjs/ui/collapsible-headings.js +232 -0
  11. package/dist/es2019/messages.js +12 -0
  12. package/dist/es2019/react/nodes/heading.compiled.css +12 -0
  13. package/dist/es2019/react/nodes/heading.js +142 -32
  14. package/dist/es2019/ui/Renderer/RendererStyleContainer.js +8 -0
  15. package/dist/es2019/ui/Renderer/index.js +8 -2
  16. package/dist/es2019/ui/collapsible-headings-dom.js +118 -0
  17. package/dist/es2019/ui/collapsible-headings-section-model.js +32 -0
  18. package/dist/es2019/ui/collapsible-headings.js +183 -0
  19. package/dist/esm/messages.js +12 -0
  20. package/dist/esm/react/nodes/heading.compiled.css +12 -0
  21. package/dist/esm/react/nodes/heading.js +188 -46
  22. package/dist/esm/ui/Renderer/RendererStyleContainer.js +8 -1
  23. package/dist/esm/ui/Renderer/index.js +8 -2
  24. package/dist/esm/ui/collapsible-headings-dom.js +129 -0
  25. package/dist/esm/ui/collapsible-headings-section-model.js +32 -0
  26. package/dist/esm/ui/collapsible-headings.js +221 -0
  27. package/dist/types/messages.d.ts +23 -21
  28. package/dist/types/react/nodes/heading.d.ts +3 -2
  29. package/dist/types/ui/collapsible-headings-dom.d.ts +14 -0
  30. package/dist/types/ui/collapsible-headings-section-model.d.ts +9 -0
  31. package/dist/types/ui/collapsible-headings.d.ts +26 -0
  32. package/dist/types/ui/renderer-props.d.ts +7 -0
  33. package/package.json +4 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atlaskit/renderer
2
2
 
3
+ ## 133.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d6d4b831bab67`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d6d4b831bab67) -
8
+ [ux] Implements collapsible headings feature for the full-page renderer.
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+
14
+ ## 133.14.2
15
+
16
+ ### Patch Changes
17
+
18
+ - [`22bc749d89dc9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/22bc749d89dc9) -
19
+ Clean up platform_change_emoji_button_label FG and avoid unsupported ARIA attributes on editor
20
+ emoji nodes Stabilize renderer integration tests for smart cards, heading anchors, and table
21
+ triple-click selection
22
+ - Updated dependencies
23
+
3
24
  ## 133.14.1
4
25
 
5
26
  ### Patch Changes
@@ -46,6 +46,9 @@
46
46
  {
47
47
  "path": "../../../design-system/code/afm-cc/tsconfig.json"
48
48
  },
49
+ {
50
+ "path": "../../../design-system/css/afm-cc/tsconfig.json"
51
+ },
49
52
  {
50
53
  "path": "../../editor-json-transformer/afm-cc/tsconfig.json"
51
54
  },
@@ -3,11 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.tableCellMessages = exports.inlineCommentMessages = exports.headingAnchorLinkMessages = void 0;
6
+ exports.tableCellMessages = exports.inlineCommentMessages = exports.headingAnchorLinkMessages = exports.collapsibleHeadingMessages = void 0;
7
7
  var _reactIntl = require("react-intl");
8
8
  /* eslint-disable @atlaskit/editor/no-re-export */
9
9
  // Entry file in package.json
10
10
 
11
+ var collapsibleHeadingMessages = exports.collapsibleHeadingMessages = (0, _reactIntl.defineMessages)({
12
+ collapseSection: {
13
+ id: 'fabric.editor.collapsibleHeading.collapseSection.ai-non-final',
14
+ defaultMessage: 'Collapse section',
15
+ description: 'Accessible label and tooltip for the button beside an expanded renderer heading. Activating the button hides the content in that heading section.'
16
+ },
17
+ expandSection: {
18
+ id: 'fabric.editor.collapsibleHeading.expandSection.ai-non-final',
19
+ defaultMessage: 'Expand section',
20
+ description: 'Accessible label and tooltip for the button beside a collapsed renderer heading. Activating the button reveals the content in that heading section.'
21
+ }
22
+ });
11
23
  var headingAnchorLinkMessages = exports.headingAnchorLinkMessages = (0, _reactIntl.defineMessages)({
12
24
  copyHeadingLinkToClipboard: {
13
25
  id: 'fabric.editor.headingLink.copyAnchorLink',
@@ -0,0 +1,12 @@
1
+ ._152tidpf{inset-block-start:0}
2
+ ._1e02idpf{inset-inline-start:0}
3
+ ._1e0c1ule{display:block}
4
+ ._1pbykb7n{z-index:1}
5
+ ._ahbqukr8{margin-inline-start:var(--ds-space-negative-400,-2pc)}
6
+ ._bozgxy5q{padding-inline-start:var(--ds-space-400,2pc)}
7
+ ._kqswh2mm{position:relative}
8
+ ._kqswstnw{position:absolute}
9
+ ._lcxvglyw{pointer-events:none}
10
+ ._tzy4idpf{opacity:0}
11
+ @media (hover:none){._tza3kb7n{opacity:1}._12yg1wug{pointer-events:auto}}
12
+ @media (pointer:coarse){._xrqrkb7n{opacity:1}._l4c51wug{pointer-events:auto}}
@@ -1,3 +1,4 @@
1
+ /* heading.tsx generated by @compiled/babel-plugin v0.40.0 */
1
2
  "use strict";
2
3
 
3
4
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
@@ -5,24 +6,26 @@ Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.default = void 0;
9
+ require("./heading.compiled.css");
10
+ var _runtime = require("@compiled/react/runtime");
11
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
8
12
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
9
13
  var _react = _interopRequireDefault(require("react"));
14
+ var _reactIntl = require("react-intl");
15
+ var _new = require("@atlaskit/button/new");
16
+ var _chevronDown = _interopRequireDefault(require("@atlaskit/icon/core/chevron-down"));
17
+ var _chevronRight = _interopRequireDefault(require("@atlaskit/icon/core/chevron-right"));
10
18
  var _interactionMetrics = require("@atlaskit/react-ufo/interaction-metrics");
11
19
  var _analytics = require("@atlaskit/editor-common/analytics");
12
20
  var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden/visually-hidden"));
13
21
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
14
22
  var _analyticsContext = _interopRequireDefault(require("../../analytics/analyticsContext"));
15
23
  var _clipboard = require("../utils/clipboard");
24
+ var _messages = require("../../messages");
25
+ var _collapsibleHeadings = require("../../ui/collapsible-headings");
16
26
  var _headingAnchor = _interopRequireDefault(require("./heading-anchor"));
17
- var _react2 = require("@emotion/react");
18
- /**
19
- * @jsxRuntime classic
20
- * @jsx jsx
21
- */
22
-
23
- // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
24
-
25
27
  var RENDERER_HEADING_WRAPPER = 'renderer-heading-wrapper';
28
+ var RENDERER_COLLAPSIBLE_HEADING_WRAPPER = 'renderer-collapsible-heading-wrapper';
26
29
  var getCurrentUrlWithHash = function getCurrentUrlWithHash() {
27
30
  var hash = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
28
31
  var url = new URL(window.location.href);
@@ -38,13 +41,29 @@ function hasRightAlignmentMark(marks) {
38
41
  return mark.type.name === 'alignment' && mark.attrs.align === 'end';
39
42
  });
40
43
  }
41
- var wrapperStyles = (0, _react2.css)({
42
- // Important: do NOT use flex here.
43
- // With flex + baseline alignment, the anchor aligns to the *first line* of a multi-line heading,
44
- // which visually places it at the top-right. We want the anchor to sit immediately after the
45
- // last character of the heading (i.e. after the final wrapped line), so we use normal inline flow.
46
- display: 'block'
47
- });
44
+ var wrapperStyles = null;
45
+ var collapsibleHeadingWrapperStyles = null;
46
+ var collapsibleHeadingButtonStyles = null;
47
+ var collapsibleHeadingButtonHiddenStyles = null;
48
+ var ChevronDownSmallIcon = function ChevronDownSmallIcon() {
49
+ return /*#__PURE__*/_react.default.createElement(_chevronDown.default, {
50
+ label: "",
51
+ size: "small"
52
+ });
53
+ };
54
+ var ChevronRightSmallIcon = function ChevronRightSmallIcon() {
55
+ return /*#__PURE__*/_react.default.createElement(_chevronRight.default, {
56
+ label: "",
57
+ size: "small"
58
+ });
59
+ };
60
+ var hasFocusVisible = function hasFocusVisible(target) {
61
+ try {
62
+ return target.matches(':focus-visible');
63
+ } catch (_unused) {
64
+ return true;
65
+ }
66
+ };
48
67
  var getHeadingAnchorLinksConfig = function getHeadingAnchorLinksConfig(allowHeadingAnchorLinks) {
49
68
  return (0, _typeof2.default)(allowHeadingAnchorLinks) === 'object' ? allowHeadingAnchorLinks : undefined;
50
69
  };
@@ -54,9 +73,9 @@ function WrappedHeadingAnchor(_ref) {
54
73
  level = _ref.level,
55
74
  headingId = _ref.headingId,
56
75
  hideFromScreenReader = _ref.hideFromScreenReader;
57
- return (0, _react2.jsx)(_analyticsContext.default.Consumer, null, function (_ref2) {
76
+ return /*#__PURE__*/_react.default.createElement(_analyticsContext.default.Consumer, null, function (_ref2) {
58
77
  var fireAnalyticsEvent = _ref2.fireAnalyticsEvent;
59
- return (0, _react2.jsx)(_headingAnchor.default, {
78
+ return /*#__PURE__*/_react.default.createElement(_headingAnchor.default, {
60
79
  enableNestedHeaderLinks: enableNestedHeaderLinks,
61
80
  level: level
62
81
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
@@ -76,6 +95,88 @@ function WrappedHeadingAnchor(_ref) {
76
95
  });
77
96
  });
78
97
  }
98
+ function CollapsibleHeadingButton(_ref3) {
99
+ var collapsibleHeading = _ref3.collapsibleHeading,
100
+ isHeadingHovered = _ref3.isHeadingHovered;
101
+ var intl = (0, _reactIntl.useIntl)();
102
+ var _React$useState = _react.default.useState(false),
103
+ _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
104
+ isFocused = _React$useState2[0],
105
+ setIsFocused = _React$useState2[1];
106
+ var isCollapsed = collapsibleHeading.isCollapsed,
107
+ toggle = collapsibleHeading.toggle;
108
+ var isVisible = isCollapsed || isFocused || isHeadingHovered;
109
+ var handleClick = _react.default.useCallback(function (event) {
110
+ event.stopPropagation();
111
+ toggle();
112
+ }, [toggle]);
113
+ var handleFocus = _react.default.useCallback(function (event) {
114
+ setIsFocused(hasFocusVisible(event.target));
115
+ }, []);
116
+ var handleBlur = _react.default.useCallback(function () {
117
+ return setIsFocused(false);
118
+ }, []);
119
+ var handleKeyDown = _react.default.useCallback(function () {
120
+ return setIsFocused(true);
121
+ }, []);
122
+ return /*#__PURE__*/_react.default.createElement("span", {
123
+ className: (0, _runtime.ax)(["_kqswstnw _152tidpf _1e02idpf _1pbykb7n", !isVisible && "_tzy4idpf _lcxvglyw _tza3kb7n _12yg1wug _xrqrkb7n _l4c51wug"])
124
+ }, /*#__PURE__*/_react.default.createElement(_new.IconButton, {
125
+ appearance: "subtle",
126
+ spacing: "compact",
127
+ icon: isCollapsed ? ChevronRightSmallIcon : ChevronDownSmallIcon,
128
+ label: intl.formatMessage(isCollapsed ? _messages.collapsibleHeadingMessages.expandSection : _messages.collapsibleHeadingMessages.collapseSection),
129
+ "aria-expanded": !isCollapsed,
130
+ isTooltipDisabled: false,
131
+ testId: "collapsible-heading-button",
132
+ onClick: handleClick,
133
+ onFocus: handleFocus,
134
+ onBlur: handleBlur,
135
+ onKeyDown: handleKeyDown
136
+ }));
137
+ }
138
+ function CollapsibleHeadingContainer(_ref4) {
139
+ var children = _ref4.children,
140
+ collapsibleHeading = _ref4.collapsibleHeading,
141
+ headingLevel = _ref4.headingLevel;
142
+ var mouseEntered = _react.default.useRef(false);
143
+ var _React$useState3 = _react.default.useState(false),
144
+ _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2),
145
+ isHovered = _React$useState4[0],
146
+ setIsHovered = _React$useState4[1];
147
+ var _React$useState5 = _react.default.useState(false),
148
+ _React$useState6 = (0, _slicedToArray2.default)(_React$useState5, 2),
149
+ isFocused = _React$useState6[0],
150
+ setIsFocused = _React$useState6[1];
151
+ var mouseEnterHandler = function mouseEnterHandler() {
152
+ if (!mouseEntered.current) {
153
+ (0, _interactionMetrics.abortAll)('new_interaction');
154
+ mouseEntered.current = true;
155
+ }
156
+ };
157
+ return /*#__PURE__*/_react.default.createElement("div", {
158
+ "data-testid": RENDERER_COLLAPSIBLE_HEADING_WRAPPER,
159
+ "data-level": headingLevel,
160
+ onMouseEnter: function onMouseEnter() {
161
+ mouseEnterHandler();
162
+ setIsHovered(true);
163
+ },
164
+ onMouseLeave: function onMouseLeave() {
165
+ return setIsHovered(false);
166
+ },
167
+ onFocus: function onFocus(event) {
168
+ return setIsFocused(hasFocusVisible(event.target));
169
+ },
170
+ onBlur: function onBlur() {
171
+ return setIsFocused(false);
172
+ },
173
+ className: (0, _runtime.ax)(["_ahbqukr8 _bozgxy5q _kqswh2mm"])
174
+ }, /*#__PURE__*/_react.default.createElement(CollapsibleHeadingButton, {
175
+ collapsibleHeading: collapsibleHeading,
176
+ isHeadingHovered: isHovered || isFocused
177
+ }), children);
178
+ }
179
+
79
180
  /**
80
181
  * Old heading structure (before a11y fix):
81
182
  * - headning anchor is rendered INSIDE the heading element
@@ -108,28 +209,28 @@ function HeadingWithDuplicateAnchor(props) {
108
209
  mouseEntered.current = true;
109
210
  }
110
211
  };
111
- return (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(HX, {
212
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(HX, {
112
213
  id: headingIdToUse,
113
214
  "data-local-id": localId,
114
215
  "data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
115
216
  "data-as-inline": asInline,
116
217
  onMouseEnter: mouseEnterHandler,
117
218
  tabIndex: -1
118
- }, (0, _react2.jsx)(_react.default.Fragment, null, showAnchorLink && headingId && isRightAligned && (0, _react2.jsx)(WrappedHeadingAnchor, {
219
+ }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, showAnchorLink && headingId && isRightAligned && /*#__PURE__*/_react.default.createElement(WrappedHeadingAnchor, {
119
220
  level: props.level,
120
221
  enableNestedHeaderLinks: enableNestedHeaderLinks,
121
222
  getHeadingLink: getHeadingLink,
122
223
  headingId: headingId,
123
224
  hideFromScreenReader: true
124
- }), props.children, showAnchorLink && headingId && !isRightAligned && (0, _react2.jsx)(WrappedHeadingAnchor, {
225
+ }), props.children, showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/_react.default.createElement(WrappedHeadingAnchor, {
125
226
  level: props.level,
126
227
  enableNestedHeaderLinks: enableNestedHeaderLinks,
127
228
  getHeadingLink: getHeadingLink,
128
229
  headingId: headingId,
129
230
  hideFromScreenReader: true
130
- }))), (0, _react2.jsx)(_visuallyHidden.default, {
231
+ }))), /*#__PURE__*/_react.default.createElement(_visuallyHidden.default, {
131
232
  testId: "visually-hidden-heading-anchor"
132
- }, showAnchorLink && headingId && (0, _react2.jsx)(WrappedHeadingAnchor, {
233
+ }, showAnchorLink && headingId && /*#__PURE__*/_react.default.createElement(WrappedHeadingAnchor, {
133
234
  level: props.level,
134
235
  enableNestedHeaderLinks: enableNestedHeaderLinks,
135
236
  getHeadingLink: getHeadingLink,
@@ -150,9 +251,18 @@ function HeadingWithWrapper(props) {
150
251
  marks = props.marks,
151
252
  invisible = props.invisible,
152
253
  localId = props.localId,
153
- asInline = props.asInline;
254
+ asInline = props.asInline,
255
+ collapsibleHeading = props.collapsibleHeading;
154
256
  var HX = "h".concat(props.level);
155
257
  var mouseEntered = _react.default.useRef(false);
258
+ var _React$useState7 = _react.default.useState(false),
259
+ _React$useState8 = (0, _slicedToArray2.default)(_React$useState7, 2),
260
+ isHovered = _React$useState8[0],
261
+ setIsHovered = _React$useState8[1];
262
+ var _React$useState9 = _react.default.useState(false),
263
+ _React$useState0 = (0, _slicedToArray2.default)(_React$useState9, 2),
264
+ isFocused = _React$useState0[0],
265
+ setIsFocused = _React$useState0[1];
156
266
  var showAnchorLink = !!props.showAnchorLink;
157
267
  var isRightAligned = hasRightAlignmentMark(marks);
158
268
  var headingAnchorLinksConfig = getHeadingAnchorLinksConfig(allowHeadingAnchorLinks);
@@ -160,7 +270,7 @@ function HeadingWithWrapper(props) {
160
270
  var getHeadingLink = headingAnchorLinksConfig === null || headingAnchorLinksConfig === void 0 ? void 0 : headingAnchorLinksConfig.getHeadingLink;
161
271
  var headingIdToUse = invisible ? undefined : headingId;
162
272
  var mouseEnterHandler = function mouseEnterHandler() {
163
- if (showAnchorLink && !mouseEntered.current) {
273
+ if ((showAnchorLink || collapsibleHeading) && !mouseEntered.current) {
164
274
  // Abort TTVC calculation when the mouse hovers over heading. Hovering over
165
275
  // heading render heading anchor and inline comment buttons. These user-induced
166
276
  // DOM changes are valid reasons to abort the TTVC calculation.
@@ -168,26 +278,45 @@ function HeadingWithWrapper(props) {
168
278
  mouseEntered.current = true;
169
279
  }
170
280
  };
171
- return (0, _react2.jsx)("div", {
281
+ var handleWrapperMouseEnter = function handleWrapperMouseEnter() {
282
+ mouseEnterHandler();
283
+ setIsHovered(true);
284
+ };
285
+ var handleWrapperMouseLeave = function handleWrapperMouseLeave() {
286
+ return setIsHovered(false);
287
+ };
288
+ var handleWrapperFocus = function handleWrapperFocus(event) {
289
+ return setIsFocused(hasFocusVisible(event.target));
290
+ };
291
+ var handleWrapperBlur = function handleWrapperBlur() {
292
+ return setIsFocused(false);
293
+ };
294
+ return /*#__PURE__*/_react.default.createElement("div", {
172
295
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
173
- className: RENDERER_HEADING_WRAPPER,
296
+ className: (0, _runtime.ax)(["_1e0c1ule", collapsibleHeading && "_ahbqukr8 _bozgxy5q _kqswh2mm", RENDERER_HEADING_WRAPPER]),
174
297
  "data-testid": RENDERER_HEADING_WRAPPER,
175
298
  "data-level": props.level,
176
- css: wrapperStyles
177
- }, showAnchorLink && headingId && isRightAligned && (0, _react2.jsx)(WrappedHeadingAnchor, {
299
+ onMouseEnter: collapsibleHeading ? handleWrapperMouseEnter : undefined,
300
+ onMouseLeave: collapsibleHeading ? handleWrapperMouseLeave : undefined,
301
+ onFocus: collapsibleHeading ? handleWrapperFocus : undefined,
302
+ onBlur: collapsibleHeading ? handleWrapperBlur : undefined
303
+ }, collapsibleHeading && /*#__PURE__*/_react.default.createElement(CollapsibleHeadingButton, {
304
+ collapsibleHeading: collapsibleHeading,
305
+ isHeadingHovered: isHovered || isFocused
306
+ }), showAnchorLink && headingId && isRightAligned && /*#__PURE__*/_react.default.createElement(WrappedHeadingAnchor, {
178
307
  level: props.level,
179
308
  enableNestedHeaderLinks: enableNestedHeaderLinks,
180
309
  getHeadingLink: getHeadingLink,
181
310
  headingId: headingId,
182
311
  hideFromScreenReader: false
183
- }), (0, _react2.jsx)(HX, {
312
+ }), /*#__PURE__*/_react.default.createElement(HX, {
184
313
  id: headingIdToUse,
185
314
  "data-local-id": localId,
186
315
  "data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
187
316
  "data-as-inline": asInline,
188
- onMouseEnter: mouseEnterHandler,
317
+ onMouseEnter: collapsibleHeading ? undefined : mouseEnterHandler,
189
318
  tabIndex: -1
190
- }, props.children), showAnchorLink && headingId && !isRightAligned && (0, _react2.jsx)(WrappedHeadingAnchor, {
319
+ }, props.children), showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/_react.default.createElement(WrappedHeadingAnchor, {
191
320
  level: props.level,
192
321
  enableNestedHeaderLinks: enableNestedHeaderLinks,
193
322
  getHeadingLink: getHeadingLink,
@@ -200,23 +329,26 @@ function HeadingWithWrapper(props) {
200
329
  * Gated Heading component:
201
330
  * - When platform_editor_copy_link_a11y_inconsistency_fix experiment is enabled,
202
331
  * returns HeadingWithWrapper (new a11y-improved structure)
203
- * - Otherwise returns HeadingWithDuplicateAnchor (old structure)
332
+ * - Otherwise preserves HeadingWithDuplicateAnchor (old structure), adding only the collapse
333
+ * container when the top-level heading is collapsible
204
334
  */
205
- function Heading(_ref3) {
206
- var allowHeadingAnchorLinks = _ref3.allowHeadingAnchorLinks,
207
- children = _ref3.children,
208
- dataAttributes = _ref3.dataAttributes,
209
- headingId = _ref3.headingId,
210
- invisible = _ref3.invisible,
211
- level = _ref3.level,
212
- localId = _ref3.localId,
213
- marks = _ref3.marks,
214
- nodeType = _ref3.nodeType,
215
- showAnchorLink = _ref3.showAnchorLink,
216
- serializer = _ref3.serializer,
217
- asInline = _ref3.asInline;
335
+ function Heading(_ref5) {
336
+ var allowHeadingAnchorLinks = _ref5.allowHeadingAnchorLinks,
337
+ children = _ref5.children,
338
+ dataAttributes = _ref5.dataAttributes,
339
+ headingId = _ref5.headingId,
340
+ invisible = _ref5.invisible,
341
+ level = _ref5.level,
342
+ localId = _ref5.localId,
343
+ marks = _ref5.marks,
344
+ nodeType = _ref5.nodeType,
345
+ path = _ref5.path,
346
+ showAnchorLink = _ref5.showAnchorLink,
347
+ serializer = _ref5.serializer,
348
+ asInline = _ref5.asInline;
349
+ var collapsibleHeading = (0, _collapsibleHeadings.useCollapsibleHeading)(dataAttributes['data-renderer-start-pos'], (path === null || path === void 0 ? void 0 : path.length) === 0);
218
350
  if ((0, _expValEquals.expValEquals)('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true)) {
219
- return (0, _react2.jsx)(HeadingWithWrapper, {
351
+ return /*#__PURE__*/_react.default.createElement(HeadingWithWrapper, {
220
352
  allowHeadingAnchorLinks: allowHeadingAnchorLinks,
221
353
  dataAttributes: dataAttributes,
222
354
  headingId: headingId,
@@ -227,10 +359,11 @@ function Heading(_ref3) {
227
359
  nodeType: nodeType,
228
360
  serializer: serializer,
229
361
  showAnchorLink: showAnchorLink,
230
- asInline: asInline
362
+ asInline: asInline,
363
+ collapsibleHeading: collapsibleHeading
231
364
  }, children);
232
365
  }
233
- return (0, _react2.jsx)(HeadingWithDuplicateAnchor, {
366
+ var headingWithDuplicateAnchor = /*#__PURE__*/_react.default.createElement(HeadingWithDuplicateAnchor, {
234
367
  allowHeadingAnchorLinks: allowHeadingAnchorLinks,
235
368
  dataAttributes: dataAttributes,
236
369
  headingId: headingId,
@@ -243,5 +376,12 @@ function Heading(_ref3) {
243
376
  showAnchorLink: showAnchorLink,
244
377
  asInline: asInline
245
378
  }, children);
379
+ if (collapsibleHeading) {
380
+ return /*#__PURE__*/_react.default.createElement(CollapsibleHeadingContainer, {
381
+ collapsibleHeading: collapsibleHeading,
382
+ headingLevel: level
383
+ }, headingWithDuplicateAnchor);
384
+ }
385
+ return headingWithDuplicateAnchor;
246
386
  }
247
387
  var _default = exports.default = Heading;
@@ -27,6 +27,7 @@ var _emoji = require("@atlaskit/editor-common/emoji");
27
27
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
28
28
  var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
29
29
  var _syncBlock = require("@atlaskit/editor-common/sync-block");
30
+ var _collapsibleHeadingsDom = require("../collapsible-headings-dom");
30
31
  var _css9, _$concat3, _$concat6;
31
32
  /* eslint-disable @atlaskit/ui-styling-standard/no-important-styles, @atlaskit/ui-styling-standard/no-unsafe-selectors */
32
33
  /* eslint-disable @atlaskit/ui-styling-standard/no-imported-style-values */
@@ -95,7 +96,13 @@ var baseStyles = (0, _react.css)((0, _defineProperty2.default)((0, _defineProper
95
96
  display: 'block',
96
97
  height: 0,
97
98
  clear: 'both'
98
- }), ".".concat(_consts.RendererCssClassName.DOCUMENT), (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, ".".concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME), {
99
+ }), ".".concat(_consts.RendererCssClassName.DOCUMENT), (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "> [".concat(_collapsibleHeadingsDom.COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, "][hidden='until-found']"), {
100
+ display: 'block',
101
+ minBlockSize: 0,
102
+ marginBlock: 0,
103
+ paddingBlock: 0,
104
+ borderBlockWidth: 0
105
+ }), ".".concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME), {
99
106
  height: '22px',
100
107
  transform: "translateY(-2px)"
101
108
  }), "h1", (0, _defineProperty2.default)({}, "> .mediaInlineView-content-wrap > .".concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > :is(a, span[data-mark-type='border']) .mediaInlineView-content-wrap > .").concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > .").concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME, ",\n > :is(a, span[data-mark-type='border']) .").concat(_mediaInline.INLINE_IMAGE_WRAPPER_CLASS_NAME), {
@@ -41,6 +41,7 @@ var _RendererActionsContext = require("../RendererActionsContext");
41
41
  var _SmartCardStorage = require("../SmartCardStorage");
42
42
  var _activeHeaderIdProvider = require("../active-header-id-provider");
43
43
  var _annotations = require("../annotations");
44
+ var _collapsibleHeadings = require("../collapsible-headings");
44
45
  var _ErrorBoundary = require("./ErrorBoundary");
45
46
  var _breakoutSsr = require("./breakout-ssr");
46
47
  var _clickToEdit = require("./click-to-edit");
@@ -72,7 +73,7 @@ var DEGRADED_SEVERITY_THRESHOLD = exports.DEGRADED_SEVERITY_THRESHOLD = 3000;
72
73
  var TABLE_INFO_TIMEOUT = 10000;
73
74
  var RENDER_EVENT_SAMPLE_RATE = 0.1;
74
75
  var packageName = "@atlaskit/renderer";
75
- var packageVersion = "133.14.0";
76
+ var packageVersion = "133.14.2";
76
77
  var setAsQueryContainerStyles = (0, _react2.css)({
77
78
  containerName: 'ak-renderer-wrapper',
78
79
  containerType: 'inline-size'
@@ -468,6 +469,7 @@ var RendererFunctionalComponent = exports.RendererFunctionalComponent = function
468
469
  timeZone: props.timeZone
469
470
  });
470
471
  }, [props.featureFlags, props.isTopLevelRenderer, createRendererContext, props.timeZone]);
472
+ var isCollapsibleHeadingsEnabled = props.allowCollapsibleHeadings === true && ['full-page', 'full-width', 'max'].includes(props.appearance || '') && rendererContext.isTopLevelRenderer && (0, _expValEquals.expValEquals)('platform_renderer_collapsible_headings', 'isEnabled', true);
471
473
  (0, _useScrollToBlock.useScrollToBlock)(editorRef, props.document, props.scrollToBlock);
472
474
  try {
473
475
  var _rendererContext$feat, _props$media;
@@ -527,7 +529,11 @@ var RendererFunctionalComponent = exports.RendererFunctionalComponent = function
527
529
  doc: pmDoc,
528
530
  schema: schema,
529
531
  onAnalyticsEvent: _fireAnalyticsEvent
530
- }, result)))))));
532
+ }, (0, _react2.jsx)(_collapsibleHeadings.CollapsibleHeadingsProvider, {
533
+ pmDocument: pmDoc,
534
+ rendererRef: editorRef,
535
+ isEnabled: isCollapsibleHeadingsEnabled
536
+ }, result))))))));
531
537
  var rendererResult = props.truncated ? (0, _react2.jsx)(_truncatedWrapper.TruncatedWrapper, {
532
538
  height: props.maxHeight,
533
539
  fadeHeight: props.fadeOutHeight
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.COLLAPSED_CONTENT_OWNERS_ATTRIBUTE = void 0;
7
+ exports.getCollapsedContentOwners = getCollapsedContentOwners;
8
+ exports.getOwnedRendererDocuments = getOwnedRendererDocuments;
9
+ exports.reconcileCollapsedHeadingContent = reconcileCollapsedHeadingContent;
10
+ var RENDERER_DOCUMENT_SELECTOR = '.ak-renderer-document';
11
+ var RENDERER_START_POS_ATTRIBUTE = 'data-renderer-start-pos';
12
+ var HEADING_SELECTOR = [1, 2, 3, 4, 5, 6].map(function (level) {
13
+ return "h".concat(level, "[").concat(RENDERER_START_POS_ATTRIBUTE, "]");
14
+ }).join(',');
15
+ var COLLAPSED_CONTENT_OWNERS_ATTRIBUTE = exports.COLLAPSED_CONTENT_OWNERS_ATTRIBUTE = 'data-renderer-collapsed-content-owners';
16
+ function getDirectRendererChild(rendererDocument, element) {
17
+ var _currentElement;
18
+ var currentElement = element;
19
+ while (currentElement && currentElement.parentElement !== rendererDocument) {
20
+ currentElement = currentElement.parentElement;
21
+ }
22
+ return ((_currentElement = currentElement) === null || _currentElement === void 0 ? void 0 : _currentElement.parentElement) === rendererDocument ? currentElement : null;
23
+ }
24
+ function getTopLevelHeadingPositionsByContainer(rendererDocument, topLevelHeadingPositions) {
25
+ var headingPositionsByContainer = new Map();
26
+ rendererDocument.querySelectorAll(HEADING_SELECTOR).forEach(function (headingElement) {
27
+ if (headingElement.closest(RENDERER_DOCUMENT_SELECTOR) !== rendererDocument) {
28
+ return;
29
+ }
30
+ var position = Number(headingElement.getAttribute(RENDERER_START_POS_ATTRIBUTE));
31
+ if (!Number.isFinite(position) || !topLevelHeadingPositions.has(position)) {
32
+ return;
33
+ }
34
+ var headingContainer = getDirectRendererChild(rendererDocument, headingElement);
35
+ if (headingContainer) {
36
+ headingPositionsByContainer.set(headingContainer, position);
37
+ }
38
+ });
39
+ return headingPositionsByContainer;
40
+ }
41
+ function restoreHiddenAttribute(element, originalHiddenAttributes) {
42
+ if (!originalHiddenAttributes.has(element)) {
43
+ return;
44
+ }
45
+ var originalHiddenAttribute = originalHiddenAttributes.get(element);
46
+ if (originalHiddenAttribute === null || originalHiddenAttribute === undefined) {
47
+ element.removeAttribute('hidden');
48
+ } else {
49
+ element.setAttribute('hidden', originalHiddenAttribute);
50
+ }
51
+ originalHiddenAttributes.delete(element);
52
+ }
53
+ function setCollapsedOwners(element, owners, originalHiddenAttributes) {
54
+ if (!originalHiddenAttributes.has(element)) {
55
+ originalHiddenAttributes.set(element, element.getAttribute('hidden'));
56
+ }
57
+ element.setAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, Array.from(owners).join(','));
58
+ element.setAttribute('hidden', 'until-found');
59
+ }
60
+ function getDesiredCollapsedContentOwners(rendererDocuments, collapsedHeadings, sections) {
61
+ var desiredOwners = new Map();
62
+ if (collapsedHeadings.size === 0) {
63
+ return desiredOwners;
64
+ }
65
+ var topLevelHeadingPositions = new Set(sections.map(function (section) {
66
+ return section.headingPos;
67
+ }));
68
+ var sectionsByHeadingPosition = new Map(sections.map(function (section) {
69
+ return [section.headingPos, section];
70
+ }));
71
+ rendererDocuments.forEach(function (rendererDocument) {
72
+ // Index headings once, then reconcile every top-level renderer child in DOM order.
73
+ var headingPositionsByContainer = getTopLevelHeadingPositionsByContainer(rendererDocument, topLevelHeadingPositions);
74
+ var activeCollapsedSections = [];
75
+ var contentElements = Array.from(rendererDocument.children);
76
+ contentElements.forEach(function (contentElement) {
77
+ var headingPosition = headingPositionsByContainer.get(contentElement);
78
+ if (headingPosition !== undefined) {
79
+ activeCollapsedSections = activeCollapsedSections.filter(function (section) {
80
+ return section.to > headingPosition;
81
+ });
82
+ }
83
+ if (activeCollapsedSections.length > 0) {
84
+ desiredOwners.set(contentElement, new Set(activeCollapsedSections.map(function (section) {
85
+ return section.headingPos;
86
+ })));
87
+ }
88
+ if (headingPosition !== undefined && collapsedHeadings.has(headingPosition)) {
89
+ var section = sectionsByHeadingPosition.get(headingPosition);
90
+ if (section) {
91
+ activeCollapsedSections.push(section);
92
+ }
93
+ }
94
+ });
95
+ });
96
+ return desiredOwners;
97
+ }
98
+
99
+ /** Returns renderer documents owned by this renderer root, excluding nested renderers. */
100
+ function getOwnedRendererDocuments(rendererRoot) {
101
+ return Array.from(rendererRoot.querySelectorAll(RENDERER_DOCUMENT_SELECTOR)).filter(function (rendererDocument) {
102
+ var _rendererDocument$par;
103
+ var parentRendererDocument = (_rendererDocument$par = rendererDocument.parentElement) === null || _rendererDocument$par === void 0 ? void 0 : _rendererDocument$par.closest(RENDERER_DOCUMENT_SELECTOR);
104
+ return !parentRendererDocument || !rendererRoot.contains(parentRendererDocument);
105
+ });
106
+ }
107
+
108
+ /** Applies only the visibility-attribute differences required by the collapsed section model. */
109
+ function reconcileCollapsedHeadingContent(_ref) {
110
+ var collapsedHeadings = _ref.collapsedHeadings,
111
+ originalHiddenAttributes = _ref.originalHiddenAttributes,
112
+ rendererRoot = _ref.rendererRoot,
113
+ sections = _ref.sections;
114
+ var rendererDocuments = getOwnedRendererDocuments(rendererRoot);
115
+ var desiredOwners = getDesiredCollapsedContentOwners(rendererDocuments, collapsedHeadings, sections);
116
+ rendererDocuments.forEach(function (rendererDocument) {
117
+ rendererDocument.querySelectorAll("[".concat(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, "]")).forEach(function (element) {
118
+ if (element.closest(RENDERER_DOCUMENT_SELECTOR) === rendererDocument && !desiredOwners.has(element)) {
119
+ element.removeAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE);
120
+ restoreHiddenAttribute(element, originalHiddenAttributes);
121
+ }
122
+ });
123
+ });
124
+ desiredOwners.forEach(function (owners, element) {
125
+ var desiredOwnersAttribute = Array.from(owners).join(',');
126
+ if (element.getAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE) !== desiredOwnersAttribute || element.getAttribute('hidden') !== 'until-found') {
127
+ setCollapsedOwners(element, owners, originalHiddenAttributes);
128
+ }
129
+ });
130
+ }
131
+
132
+ /** Returns the collapsed heading positions that currently hide an element. */
133
+ function getCollapsedContentOwners(element) {
134
+ var _element$getAttribute;
135
+ return ((_element$getAttribute = element.getAttribute(COLLAPSED_CONTENT_OWNERS_ATTRIBUTE)) !== null && _element$getAttribute !== void 0 ? _element$getAttribute : '').split(',').filter(function (owner) {
136
+ return owner !== '';
137
+ }).map(Number).filter(Number.isFinite);
138
+ }