@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.
- package/CHANGELOG.md +23 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/messages.js +13 -1
- package/dist/cjs/react/nodes/heading.compiled.css +12 -0
- package/dist/cjs/react/nodes/heading.js +188 -48
- package/dist/cjs/ui/Renderer/RendererStyleContainer.js +8 -1
- package/dist/cjs/ui/Renderer/index.js +8 -2
- package/dist/cjs/ui/collapsible-headings-dom.js +138 -0
- package/dist/cjs/ui/collapsible-headings-section-model.js +38 -0
- package/dist/cjs/ui/collapsible-headings.js +232 -0
- package/dist/es2019/messages.js +12 -0
- package/dist/es2019/react/nodes/heading.compiled.css +12 -0
- package/dist/es2019/react/nodes/heading.js +142 -32
- package/dist/es2019/ui/Renderer/RendererStyleContainer.js +8 -0
- package/dist/es2019/ui/Renderer/index.js +8 -2
- package/dist/es2019/ui/collapsible-headings-dom.js +118 -0
- package/dist/es2019/ui/collapsible-headings-section-model.js +32 -0
- package/dist/es2019/ui/collapsible-headings.js +183 -0
- package/dist/esm/messages.js +12 -0
- package/dist/esm/react/nodes/heading.compiled.css +12 -0
- package/dist/esm/react/nodes/heading.js +188 -46
- package/dist/esm/ui/Renderer/RendererStyleContainer.js +8 -1
- package/dist/esm/ui/Renderer/index.js +8 -2
- package/dist/esm/ui/collapsible-headings-dom.js +129 -0
- package/dist/esm/ui/collapsible-headings-section-model.js +32 -0
- package/dist/esm/ui/collapsible-headings.js +221 -0
- package/dist/types/messages.d.ts +23 -21
- package/dist/types/react/nodes/heading.d.ts +3 -2
- package/dist/types/ui/collapsible-headings-dom.d.ts +14 -0
- package/dist/types/ui/collapsible-headings-section-model.d.ts +9 -0
- package/dist/types/ui/collapsible-headings.d.ts +26 -0
- package/dist/types/ui/renderer-props.d.ts +7 -0
- package/package.json +14 -13
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.buildTopLevelHeadingSections = buildTopLevelHeadingSections;
|
|
7
|
+
var RENDERER_DOCUMENT_POSITION_OFFSET = 1;
|
|
8
|
+
/** Builds collapsible ranges for headings that are direct children of the renderer document. */
|
|
9
|
+
function buildTopLevelHeadingSections(pmDocument) {
|
|
10
|
+
if (!pmDocument) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
var sections = [];
|
|
14
|
+
var openSections = [];
|
|
15
|
+
var documentEnd = pmDocument.content.size + RENDERER_DOCUMENT_POSITION_OFFSET;
|
|
16
|
+
pmDocument.forEach(function (node, offset) {
|
|
17
|
+
if (node.type.name !== 'heading') {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
var headingPos = offset + RENDERER_DOCUMENT_POSITION_OFFSET;
|
|
21
|
+
var level = Number(node.attrs.level);
|
|
22
|
+
while (openSections.length > 0 && openSections[openSections.length - 1].level >= level) {
|
|
23
|
+
var _section = openSections.pop();
|
|
24
|
+
if (_section) {
|
|
25
|
+
_section.to = headingPos;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
var section = {
|
|
29
|
+
contentFrom: headingPos + node.nodeSize,
|
|
30
|
+
headingPos: headingPos,
|
|
31
|
+
level: level,
|
|
32
|
+
to: documentEnd
|
|
33
|
+
};
|
|
34
|
+
sections.push(section);
|
|
35
|
+
openSections.push(section);
|
|
36
|
+
});
|
|
37
|
+
return sections;
|
|
38
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.CollapsibleHeadingsProvider = CollapsibleHeadingsProvider;
|
|
9
|
+
exports.useCollapsibleHeading = useCollapsibleHeading;
|
|
10
|
+
exports.useCollapsibleHeadingsController = useCollapsibleHeadingsController;
|
|
11
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
12
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
13
|
+
var _bindEventListener = require("bind-event-listener");
|
|
14
|
+
var _collapsibleHeadingsDom = require("./collapsible-headings-dom");
|
|
15
|
+
var _collapsibleHeadingsSectionModel = require("./collapsible-headings-section-model");
|
|
16
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
17
|
+
var CollapsibleHeadingsContext = /*#__PURE__*/_react.default.createContext(null);
|
|
18
|
+
var emptyCollapsedHeadings = new Set();
|
|
19
|
+
function supportsHiddenUntilFound(rendererRef) {
|
|
20
|
+
var _rendererRef$current;
|
|
21
|
+
var body = (_rendererRef$current = rendererRef.current) === null || _rendererRef$current === void 0 ? void 0 : _rendererRef$current.ownerDocument.body;
|
|
22
|
+
return body ? 'onbeforematch' in body : false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Provides collapse state and synchronizes hidden top-level renderer content. */
|
|
26
|
+
function CollapsibleHeadingsProvider(_ref) {
|
|
27
|
+
var children = _ref.children,
|
|
28
|
+
isEnabled = _ref.isEnabled,
|
|
29
|
+
pmDocument = _ref.pmDocument,
|
|
30
|
+
rendererRef = _ref.rendererRef;
|
|
31
|
+
var _useState = (0, _react.useState)(false),
|
|
32
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
33
|
+
isBrowserFindSupported = _useState2[0],
|
|
34
|
+
setIsBrowserFindSupported = _useState2[1];
|
|
35
|
+
var _useState3 = (0, _react.useState)({
|
|
36
|
+
pmDocument: pmDocument,
|
|
37
|
+
positions: new Set()
|
|
38
|
+
}),
|
|
39
|
+
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
40
|
+
state = _useState4[0],
|
|
41
|
+
setState = _useState4[1];
|
|
42
|
+
var originalHiddenAttributes = _react.default.useRef(new WeakMap()).current;
|
|
43
|
+
var sections = (0, _react.useMemo)(function () {
|
|
44
|
+
return (0, _collapsibleHeadingsSectionModel.buildTopLevelHeadingSections)(pmDocument);
|
|
45
|
+
}, [pmDocument]);
|
|
46
|
+
var collapsibleSectionPositions = (0, _react.useMemo)(function () {
|
|
47
|
+
return new Set(sections.filter(function (section) {
|
|
48
|
+
return section.contentFrom < section.to;
|
|
49
|
+
}).map(function (section) {
|
|
50
|
+
return section.headingPos;
|
|
51
|
+
}));
|
|
52
|
+
}, [sections]);
|
|
53
|
+
var collapsedHeadings = state.pmDocument === pmDocument ? state.positions : emptyCollapsedHeadings;
|
|
54
|
+
var isActive = isEnabled && isBrowserFindSupported && Boolean(pmDocument);
|
|
55
|
+
(0, _react.useEffect)(function () {
|
|
56
|
+
setIsBrowserFindSupported(isEnabled && supportsHiddenUntilFound(rendererRef));
|
|
57
|
+
}, [isEnabled, rendererRef]);
|
|
58
|
+
var updateCollapsedHeadings = (0, _react.useCallback)(function (update) {
|
|
59
|
+
setState(function (currentState) {
|
|
60
|
+
var positions = new Set(currentState.pmDocument === pmDocument ? currentState.positions : emptyCollapsedHeadings);
|
|
61
|
+
if (!update(positions)) {
|
|
62
|
+
return currentState.pmDocument === pmDocument ? currentState : {
|
|
63
|
+
pmDocument: pmDocument,
|
|
64
|
+
positions: positions
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
pmDocument: pmDocument,
|
|
69
|
+
positions: positions
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
}, [pmDocument]);
|
|
73
|
+
var collapse = (0, _react.useCallback)(function (headingPos) {
|
|
74
|
+
if (!collapsibleSectionPositions.has(headingPos)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
updateCollapsedHeadings(function (positions) {
|
|
78
|
+
if (positions.has(headingPos)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
positions.add(headingPos);
|
|
82
|
+
return true;
|
|
83
|
+
});
|
|
84
|
+
}, [collapsibleSectionPositions, updateCollapsedHeadings]);
|
|
85
|
+
var expand = (0, _react.useCallback)(function (headingPos) {
|
|
86
|
+
updateCollapsedHeadings(function (positions) {
|
|
87
|
+
return positions.delete(headingPos);
|
|
88
|
+
});
|
|
89
|
+
}, [updateCollapsedHeadings]);
|
|
90
|
+
var expandMany = (0, _react.useCallback)(function (headingPositions) {
|
|
91
|
+
var positionsToExpand = new Set(headingPositions);
|
|
92
|
+
updateCollapsedHeadings(function (positions) {
|
|
93
|
+
var didChange = false;
|
|
94
|
+
positionsToExpand.forEach(function (headingPos) {
|
|
95
|
+
didChange = positions.delete(headingPos) || didChange;
|
|
96
|
+
});
|
|
97
|
+
return didChange;
|
|
98
|
+
});
|
|
99
|
+
}, [updateCollapsedHeadings]);
|
|
100
|
+
var expandContainingPosition = (0, _react.useCallback)(function (position) {
|
|
101
|
+
expandMany(sections.filter(function (section) {
|
|
102
|
+
return position >= section.contentFrom && position < section.to;
|
|
103
|
+
}).map(function (section) {
|
|
104
|
+
return section.headingPos;
|
|
105
|
+
}));
|
|
106
|
+
}, [expandMany, sections]);
|
|
107
|
+
var toggle = (0, _react.useCallback)(function (headingPos) {
|
|
108
|
+
if (!collapsibleSectionPositions.has(headingPos)) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
updateCollapsedHeadings(function (positions) {
|
|
112
|
+
if (positions.has(headingPos)) {
|
|
113
|
+
positions.delete(headingPos);
|
|
114
|
+
} else {
|
|
115
|
+
positions.add(headingPos);
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
});
|
|
119
|
+
}, [collapsibleSectionPositions, updateCollapsedHeadings]);
|
|
120
|
+
var contextValue = (0, _react.useMemo)(function () {
|
|
121
|
+
return isActive ? {
|
|
122
|
+
canCollapse: function canCollapse(headingPos) {
|
|
123
|
+
return collapsibleSectionPositions.has(headingPos);
|
|
124
|
+
},
|
|
125
|
+
collapse: collapse,
|
|
126
|
+
expand: expand,
|
|
127
|
+
expandContainingPosition: expandContainingPosition,
|
|
128
|
+
expandMany: expandMany,
|
|
129
|
+
isCollapsed: function isCollapsed(headingPos) {
|
|
130
|
+
return collapsedHeadings.has(headingPos);
|
|
131
|
+
},
|
|
132
|
+
toggle: toggle
|
|
133
|
+
} : null;
|
|
134
|
+
}, [collapse, collapsedHeadings, collapsibleSectionPositions, expand, expandContainingPosition, expandMany, isActive, toggle]);
|
|
135
|
+
(0, _react.useEffect)(function () {
|
|
136
|
+
var rendererRoot = rendererRef.current;
|
|
137
|
+
if (!rendererRoot) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
var positions = isActive ? collapsedHeadings : emptyCollapsedHeadings;
|
|
141
|
+
var sync = function sync() {
|
|
142
|
+
return (0, _collapsibleHeadingsDom.reconcileCollapsedHeadingContent)({
|
|
143
|
+
collapsedHeadings: positions,
|
|
144
|
+
originalHiddenAttributes: originalHiddenAttributes,
|
|
145
|
+
rendererRoot: rendererRoot,
|
|
146
|
+
sections: sections
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
sync();
|
|
150
|
+
if (!isActive || positions.size === 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
var rendererDocuments = (0, _collapsibleHeadingsDom.getOwnedRendererDocuments)(rendererRoot);
|
|
154
|
+
var rendererDocumentSet = new Set(rendererDocuments);
|
|
155
|
+
var handleBeforeMatch = function handleBeforeMatch(event) {
|
|
156
|
+
var _rendererRoot$ownerDo;
|
|
157
|
+
var target = event.target;
|
|
158
|
+
var HTMLElementConstructor = (_rendererRoot$ownerDo = rendererRoot.ownerDocument.defaultView) === null || _rendererRoot$ownerDo === void 0 ? void 0 : _rendererRoot$ownerDo.HTMLElement;
|
|
159
|
+
if (!HTMLElementConstructor || !(target instanceof HTMLElementConstructor)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
var collapsedContent = target.closest("[".concat(_collapsibleHeadingsDom.COLLAPSED_CONTENT_OWNERS_ATTRIBUTE, "]"));
|
|
163
|
+
if (!collapsedContent) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
var rendererDocument = collapsedContent.closest('.ak-renderer-document');
|
|
167
|
+
if (!rendererDocument || !rendererDocumentSet.has(rendererDocument)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
expandMany((0, _collapsibleHeadingsDom.getCollapsedContentOwners)(collapsedContent));
|
|
171
|
+
};
|
|
172
|
+
var unbindBeforeMatchListeners = rendererDocuments.map(function (rendererDocument) {
|
|
173
|
+
return (0, _bindEventListener.bind)(rendererDocument, {
|
|
174
|
+
type: 'beforematch',
|
|
175
|
+
listener: handleBeforeMatch,
|
|
176
|
+
options: {
|
|
177
|
+
capture: true
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
var observer = typeof MutationObserver === 'undefined' ? undefined : new MutationObserver(sync);
|
|
182
|
+
rendererDocuments.forEach(function (rendererDocument) {
|
|
183
|
+
observer === null || observer === void 0 || observer.observe(rendererDocument, {
|
|
184
|
+
childList: true
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
return function () {
|
|
188
|
+
observer === null || observer === void 0 || observer.disconnect();
|
|
189
|
+
unbindBeforeMatchListeners.forEach(function (unbindBeforeMatch) {
|
|
190
|
+
return unbindBeforeMatch();
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
}, [collapsedHeadings, expandMany, isActive, originalHiddenAttributes, rendererRef, sections]);
|
|
194
|
+
(0, _react.useEffect)(function () {
|
|
195
|
+
return function () {
|
|
196
|
+
var rendererRoot = rendererRef.current;
|
|
197
|
+
if (rendererRoot) {
|
|
198
|
+
(0, _collapsibleHeadingsDom.reconcileCollapsedHeadingContent)({
|
|
199
|
+
collapsedHeadings: emptyCollapsedHeadings,
|
|
200
|
+
originalHiddenAttributes: originalHiddenAttributes,
|
|
201
|
+
rendererRoot: rendererRoot,
|
|
202
|
+
sections: []
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}, [originalHiddenAttributes, rendererRef]);
|
|
207
|
+
return /*#__PURE__*/_react.default.createElement(CollapsibleHeadingsContext.Provider, {
|
|
208
|
+
value: contextValue
|
|
209
|
+
}, children);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Returns collapse state for a top-level heading when the provider is enabled. */
|
|
213
|
+
function useCollapsibleHeading(startPos, isTopLevel) {
|
|
214
|
+
var context = _react.default.useContext(CollapsibleHeadingsContext);
|
|
215
|
+
var contextToggle = context === null || context === void 0 ? void 0 : context.toggle;
|
|
216
|
+
var isCollapsible = Boolean(context && isTopLevel && context.canCollapse(startPos));
|
|
217
|
+
var isCollapsed = Boolean(isCollapsible && (context === null || context === void 0 ? void 0 : context.isCollapsed(startPos)));
|
|
218
|
+
var toggle = (0, _react.useCallback)(function () {
|
|
219
|
+
return contextToggle === null || contextToggle === void 0 ? void 0 : contextToggle(startPos);
|
|
220
|
+
}, [contextToggle, startPos]);
|
|
221
|
+
return (0, _react.useMemo)(function () {
|
|
222
|
+
return isCollapsible ? {
|
|
223
|
+
isCollapsed: isCollapsed,
|
|
224
|
+
toggle: toggle
|
|
225
|
+
} : null;
|
|
226
|
+
}, [isCollapsed, isCollapsible, toggle]);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Returns the collapse controller for integrations such as renderer Find. */
|
|
230
|
+
function useCollapsibleHeadingsController() {
|
|
231
|
+
return _react.default.useContext(CollapsibleHeadingsContext);
|
|
232
|
+
}
|
package/dist/es2019/messages.js
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
// Entry file in package.json
|
|
3
3
|
|
|
4
4
|
import { defineMessages } from 'react-intl';
|
|
5
|
+
export const collapsibleHeadingMessages = defineMessages({
|
|
6
|
+
collapseSection: {
|
|
7
|
+
id: 'fabric.editor.collapsibleHeading.collapseSection.ai-non-final',
|
|
8
|
+
defaultMessage: 'Collapse section',
|
|
9
|
+
description: 'Accessible label and tooltip for the button beside an expanded renderer heading. Activating the button hides the content in that heading section.'
|
|
10
|
+
},
|
|
11
|
+
expandSection: {
|
|
12
|
+
id: 'fabric.editor.collapsibleHeading.expandSection.ai-non-final',
|
|
13
|
+
defaultMessage: 'Expand section',
|
|
14
|
+
description: 'Accessible label and tooltip for the button beside a collapsed renderer heading. Activating the button reveals the content in that heading section.'
|
|
15
|
+
}
|
|
16
|
+
});
|
|
5
17
|
export const headingAnchorLinkMessages = defineMessages({
|
|
6
18
|
copyHeadingLinkToClipboard: {
|
|
7
19
|
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,18 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
1
|
+
/* heading.tsx generated by @compiled/babel-plugin v0.40.0 */
|
|
2
|
+
import "./heading.compiled.css";
|
|
3
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
5
4
|
import React from 'react';
|
|
5
|
+
import { useIntl } from 'react-intl';
|
|
6
|
+
import { IconButton } from '@atlaskit/button/new';
|
|
7
|
+
import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
|
|
8
|
+
import ChevronRightIcon from '@atlaskit/icon/core/chevron-right';
|
|
6
9
|
import { abortAll } from '@atlaskit/react-ufo/interaction-metrics';
|
|
7
10
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
8
11
|
import VisuallyHidden from '@atlaskit/visually-hidden/visually-hidden';
|
|
9
12
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
13
|
import AnalyticsContext from '../../analytics/analyticsContext';
|
|
11
14
|
import { copyTextToClipboard } from '../utils/clipboard';
|
|
15
|
+
import { collapsibleHeadingMessages } from '../../messages';
|
|
16
|
+
import { useCollapsibleHeading } from '../../ui/collapsible-headings';
|
|
12
17
|
import HeadingAnchor from './heading-anchor';
|
|
13
|
-
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
14
|
-
import { css, jsx } from '@emotion/react';
|
|
15
18
|
const RENDERER_HEADING_WRAPPER = 'renderer-heading-wrapper';
|
|
19
|
+
const RENDERER_COLLAPSIBLE_HEADING_WRAPPER = 'renderer-collapsible-heading-wrapper';
|
|
16
20
|
const getCurrentUrlWithHash = (hash = '') => {
|
|
17
21
|
const url = new URL(window.location.href);
|
|
18
22
|
url.search = ''; // clear any query params so that the page will correctly scroll to the anchor
|
|
@@ -25,13 +29,25 @@ function hasRightAlignmentMark(marks) {
|
|
|
25
29
|
}
|
|
26
30
|
return marks.some(mark => mark.type.name === 'alignment' && mark.attrs.align === 'end');
|
|
27
31
|
}
|
|
28
|
-
const wrapperStyles =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const wrapperStyles = null;
|
|
33
|
+
const collapsibleHeadingWrapperStyles = null;
|
|
34
|
+
const collapsibleHeadingButtonStyles = null;
|
|
35
|
+
const collapsibleHeadingButtonHiddenStyles = null;
|
|
36
|
+
const ChevronDownSmallIcon = () => /*#__PURE__*/React.createElement(ChevronDownIcon, {
|
|
37
|
+
label: "",
|
|
38
|
+
size: "small"
|
|
34
39
|
});
|
|
40
|
+
const ChevronRightSmallIcon = () => /*#__PURE__*/React.createElement(ChevronRightIcon, {
|
|
41
|
+
label: "",
|
|
42
|
+
size: "small"
|
|
43
|
+
});
|
|
44
|
+
const hasFocusVisible = target => {
|
|
45
|
+
try {
|
|
46
|
+
return target.matches(':focus-visible');
|
|
47
|
+
} catch {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
35
51
|
const getHeadingAnchorLinksConfig = allowHeadingAnchorLinks => typeof allowHeadingAnchorLinks === 'object' ? allowHeadingAnchorLinks : undefined;
|
|
36
52
|
function WrappedHeadingAnchor({
|
|
37
53
|
enableNestedHeaderLinks,
|
|
@@ -40,9 +56,9 @@ function WrappedHeadingAnchor({
|
|
|
40
56
|
headingId,
|
|
41
57
|
hideFromScreenReader
|
|
42
58
|
}) {
|
|
43
|
-
return
|
|
59
|
+
return /*#__PURE__*/React.createElement(AnalyticsContext.Consumer, null, ({
|
|
44
60
|
fireAnalyticsEvent
|
|
45
|
-
}) =>
|
|
61
|
+
}) => /*#__PURE__*/React.createElement(HeadingAnchor, {
|
|
46
62
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
47
63
|
level: level
|
|
48
64
|
// eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
|
|
@@ -61,6 +77,73 @@ function WrappedHeadingAnchor({
|
|
|
61
77
|
headingId: headingId
|
|
62
78
|
}));
|
|
63
79
|
}
|
|
80
|
+
function CollapsibleHeadingButton({
|
|
81
|
+
collapsibleHeading,
|
|
82
|
+
isHeadingHovered
|
|
83
|
+
}) {
|
|
84
|
+
const intl = useIntl();
|
|
85
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
86
|
+
const {
|
|
87
|
+
isCollapsed,
|
|
88
|
+
toggle
|
|
89
|
+
} = collapsibleHeading;
|
|
90
|
+
const isVisible = isCollapsed || isFocused || isHeadingHovered;
|
|
91
|
+
const handleClick = React.useCallback(event => {
|
|
92
|
+
event.stopPropagation();
|
|
93
|
+
toggle();
|
|
94
|
+
}, [toggle]);
|
|
95
|
+
const handleFocus = React.useCallback(event => {
|
|
96
|
+
setIsFocused(hasFocusVisible(event.target));
|
|
97
|
+
}, []);
|
|
98
|
+
const handleBlur = React.useCallback(() => setIsFocused(false), []);
|
|
99
|
+
const handleKeyDown = React.useCallback(() => setIsFocused(true), []);
|
|
100
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
101
|
+
className: ax(["_kqswstnw _152tidpf _1e02idpf _1pbykb7n", !isVisible && "_tzy4idpf _lcxvglyw _tza3kb7n _12yg1wug _xrqrkb7n _l4c51wug"])
|
|
102
|
+
}, /*#__PURE__*/React.createElement(IconButton, {
|
|
103
|
+
appearance: "subtle",
|
|
104
|
+
spacing: "compact",
|
|
105
|
+
icon: isCollapsed ? ChevronRightSmallIcon : ChevronDownSmallIcon,
|
|
106
|
+
label: intl.formatMessage(isCollapsed ? collapsibleHeadingMessages.expandSection : collapsibleHeadingMessages.collapseSection),
|
|
107
|
+
"aria-expanded": !isCollapsed,
|
|
108
|
+
isTooltipDisabled: false,
|
|
109
|
+
testId: "collapsible-heading-button",
|
|
110
|
+
onClick: handleClick,
|
|
111
|
+
onFocus: handleFocus,
|
|
112
|
+
onBlur: handleBlur,
|
|
113
|
+
onKeyDown: handleKeyDown
|
|
114
|
+
}));
|
|
115
|
+
}
|
|
116
|
+
function CollapsibleHeadingContainer({
|
|
117
|
+
children,
|
|
118
|
+
collapsibleHeading,
|
|
119
|
+
headingLevel
|
|
120
|
+
}) {
|
|
121
|
+
const mouseEntered = React.useRef(false);
|
|
122
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
123
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
124
|
+
const mouseEnterHandler = () => {
|
|
125
|
+
if (!mouseEntered.current) {
|
|
126
|
+
abortAll('new_interaction');
|
|
127
|
+
mouseEntered.current = true;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
131
|
+
"data-testid": RENDERER_COLLAPSIBLE_HEADING_WRAPPER,
|
|
132
|
+
"data-level": headingLevel,
|
|
133
|
+
onMouseEnter: () => {
|
|
134
|
+
mouseEnterHandler();
|
|
135
|
+
setIsHovered(true);
|
|
136
|
+
},
|
|
137
|
+
onMouseLeave: () => setIsHovered(false),
|
|
138
|
+
onFocus: event => setIsFocused(hasFocusVisible(event.target)),
|
|
139
|
+
onBlur: () => setIsFocused(false),
|
|
140
|
+
className: ax(["_ahbqukr8 _bozgxy5q _kqswh2mm"])
|
|
141
|
+
}, /*#__PURE__*/React.createElement(CollapsibleHeadingButton, {
|
|
142
|
+
collapsibleHeading: collapsibleHeading,
|
|
143
|
+
isHeadingHovered: isHovered || isFocused
|
|
144
|
+
}), children);
|
|
145
|
+
}
|
|
146
|
+
|
|
64
147
|
/**
|
|
65
148
|
* Old heading structure (before a11y fix):
|
|
66
149
|
* - headning anchor is rendered INSIDE the heading element
|
|
@@ -95,28 +178,28 @@ function HeadingWithDuplicateAnchor(props) {
|
|
|
95
178
|
mouseEntered.current = true;
|
|
96
179
|
}
|
|
97
180
|
};
|
|
98
|
-
return
|
|
181
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(HX, {
|
|
99
182
|
id: headingIdToUse,
|
|
100
183
|
"data-local-id": localId,
|
|
101
184
|
"data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
|
|
102
185
|
"data-as-inline": asInline,
|
|
103
186
|
onMouseEnter: mouseEnterHandler,
|
|
104
187
|
tabIndex: -1
|
|
105
|
-
},
|
|
188
|
+
}, /*#__PURE__*/React.createElement(React.Fragment, null, showAnchorLink && headingId && isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
|
|
106
189
|
level: props.level,
|
|
107
190
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
108
191
|
getHeadingLink: getHeadingLink,
|
|
109
192
|
headingId: headingId,
|
|
110
193
|
hideFromScreenReader: true
|
|
111
|
-
}), props.children, showAnchorLink && headingId && !isRightAligned &&
|
|
194
|
+
}), props.children, showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
|
|
112
195
|
level: props.level,
|
|
113
196
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
114
197
|
getHeadingLink: getHeadingLink,
|
|
115
198
|
headingId: headingId,
|
|
116
199
|
hideFromScreenReader: true
|
|
117
|
-
}))),
|
|
200
|
+
}))), /*#__PURE__*/React.createElement(VisuallyHidden, {
|
|
118
201
|
testId: "visually-hidden-heading-anchor"
|
|
119
|
-
}, showAnchorLink && headingId &&
|
|
202
|
+
}, showAnchorLink && headingId && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
|
|
120
203
|
level: props.level,
|
|
121
204
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
122
205
|
getHeadingLink: getHeadingLink,
|
|
@@ -138,10 +221,13 @@ function HeadingWithWrapper(props) {
|
|
|
138
221
|
marks,
|
|
139
222
|
invisible,
|
|
140
223
|
localId,
|
|
141
|
-
asInline
|
|
224
|
+
asInline,
|
|
225
|
+
collapsibleHeading
|
|
142
226
|
} = props;
|
|
143
227
|
const HX = `h${props.level}`;
|
|
144
228
|
const mouseEntered = React.useRef(false);
|
|
229
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
230
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
145
231
|
const showAnchorLink = !!props.showAnchorLink;
|
|
146
232
|
const isRightAligned = hasRightAlignmentMark(marks);
|
|
147
233
|
const headingAnchorLinksConfig = getHeadingAnchorLinksConfig(allowHeadingAnchorLinks);
|
|
@@ -149,7 +235,7 @@ function HeadingWithWrapper(props) {
|
|
|
149
235
|
const getHeadingLink = headingAnchorLinksConfig === null || headingAnchorLinksConfig === void 0 ? void 0 : headingAnchorLinksConfig.getHeadingLink;
|
|
150
236
|
const headingIdToUse = invisible ? undefined : headingId;
|
|
151
237
|
const mouseEnterHandler = () => {
|
|
152
|
-
if (showAnchorLink && !mouseEntered.current) {
|
|
238
|
+
if ((showAnchorLink || collapsibleHeading) && !mouseEntered.current) {
|
|
153
239
|
// Abort TTVC calculation when the mouse hovers over heading. Hovering over
|
|
154
240
|
// heading render heading anchor and inline comment buttons. These user-induced
|
|
155
241
|
// DOM changes are valid reasons to abort the TTVC calculation.
|
|
@@ -157,26 +243,39 @@ function HeadingWithWrapper(props) {
|
|
|
157
243
|
mouseEntered.current = true;
|
|
158
244
|
}
|
|
159
245
|
};
|
|
160
|
-
|
|
246
|
+
const handleWrapperMouseEnter = () => {
|
|
247
|
+
mouseEnterHandler();
|
|
248
|
+
setIsHovered(true);
|
|
249
|
+
};
|
|
250
|
+
const handleWrapperMouseLeave = () => setIsHovered(false);
|
|
251
|
+
const handleWrapperFocus = event => setIsFocused(hasFocusVisible(event.target));
|
|
252
|
+
const handleWrapperBlur = () => setIsFocused(false);
|
|
253
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
161
254
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
162
|
-
className: RENDERER_HEADING_WRAPPER,
|
|
255
|
+
className: ax(["_1e0c1ule", collapsibleHeading && "_ahbqukr8 _bozgxy5q _kqswh2mm", RENDERER_HEADING_WRAPPER]),
|
|
163
256
|
"data-testid": RENDERER_HEADING_WRAPPER,
|
|
164
257
|
"data-level": props.level,
|
|
165
|
-
|
|
166
|
-
|
|
258
|
+
onMouseEnter: collapsibleHeading ? handleWrapperMouseEnter : undefined,
|
|
259
|
+
onMouseLeave: collapsibleHeading ? handleWrapperMouseLeave : undefined,
|
|
260
|
+
onFocus: collapsibleHeading ? handleWrapperFocus : undefined,
|
|
261
|
+
onBlur: collapsibleHeading ? handleWrapperBlur : undefined
|
|
262
|
+
}, collapsibleHeading && /*#__PURE__*/React.createElement(CollapsibleHeadingButton, {
|
|
263
|
+
collapsibleHeading: collapsibleHeading,
|
|
264
|
+
isHeadingHovered: isHovered || isFocused
|
|
265
|
+
}), showAnchorLink && headingId && isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
|
|
167
266
|
level: props.level,
|
|
168
267
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
169
268
|
getHeadingLink: getHeadingLink,
|
|
170
269
|
headingId: headingId,
|
|
171
270
|
hideFromScreenReader: false
|
|
172
|
-
}),
|
|
271
|
+
}), /*#__PURE__*/React.createElement(HX, {
|
|
173
272
|
id: headingIdToUse,
|
|
174
273
|
"data-local-id": localId,
|
|
175
274
|
"data-renderer-start-pos": dataAttributes['data-renderer-start-pos'],
|
|
176
275
|
"data-as-inline": asInline,
|
|
177
|
-
onMouseEnter: mouseEnterHandler,
|
|
276
|
+
onMouseEnter: collapsibleHeading ? undefined : mouseEnterHandler,
|
|
178
277
|
tabIndex: -1
|
|
179
|
-
}, props.children), showAnchorLink && headingId && !isRightAligned &&
|
|
278
|
+
}, props.children), showAnchorLink && headingId && !isRightAligned && /*#__PURE__*/React.createElement(WrappedHeadingAnchor, {
|
|
180
279
|
level: props.level,
|
|
181
280
|
enableNestedHeaderLinks: enableNestedHeaderLinks,
|
|
182
281
|
getHeadingLink: getHeadingLink,
|
|
@@ -189,7 +288,8 @@ function HeadingWithWrapper(props) {
|
|
|
189
288
|
* Gated Heading component:
|
|
190
289
|
* - When platform_editor_copy_link_a11y_inconsistency_fix experiment is enabled,
|
|
191
290
|
* returns HeadingWithWrapper (new a11y-improved structure)
|
|
192
|
-
* - Otherwise
|
|
291
|
+
* - Otherwise preserves HeadingWithDuplicateAnchor (old structure), adding only the collapse
|
|
292
|
+
* container when the top-level heading is collapsible
|
|
193
293
|
*/
|
|
194
294
|
function Heading({
|
|
195
295
|
allowHeadingAnchorLinks,
|
|
@@ -201,12 +301,14 @@ function Heading({
|
|
|
201
301
|
localId,
|
|
202
302
|
marks,
|
|
203
303
|
nodeType,
|
|
304
|
+
path,
|
|
204
305
|
showAnchorLink,
|
|
205
306
|
serializer,
|
|
206
307
|
asInline
|
|
207
308
|
}) {
|
|
309
|
+
const collapsibleHeading = useCollapsibleHeading(dataAttributes['data-renderer-start-pos'], (path === null || path === void 0 ? void 0 : path.length) === 0);
|
|
208
310
|
if (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true)) {
|
|
209
|
-
return
|
|
311
|
+
return /*#__PURE__*/React.createElement(HeadingWithWrapper, {
|
|
210
312
|
allowHeadingAnchorLinks: allowHeadingAnchorLinks,
|
|
211
313
|
dataAttributes: dataAttributes,
|
|
212
314
|
headingId: headingId,
|
|
@@ -217,10 +319,11 @@ function Heading({
|
|
|
217
319
|
nodeType: nodeType,
|
|
218
320
|
serializer: serializer,
|
|
219
321
|
showAnchorLink: showAnchorLink,
|
|
220
|
-
asInline: asInline
|
|
322
|
+
asInline: asInline,
|
|
323
|
+
collapsibleHeading: collapsibleHeading
|
|
221
324
|
}, children);
|
|
222
325
|
}
|
|
223
|
-
|
|
326
|
+
const headingWithDuplicateAnchor = /*#__PURE__*/React.createElement(HeadingWithDuplicateAnchor, {
|
|
224
327
|
allowHeadingAnchorLinks: allowHeadingAnchorLinks,
|
|
225
328
|
dataAttributes: dataAttributes,
|
|
226
329
|
headingId: headingId,
|
|
@@ -233,5 +336,12 @@ function Heading({
|
|
|
233
336
|
showAnchorLink: showAnchorLink,
|
|
234
337
|
asInline: asInline
|
|
235
338
|
}, children);
|
|
339
|
+
if (collapsibleHeading) {
|
|
340
|
+
return /*#__PURE__*/React.createElement(CollapsibleHeadingContainer, {
|
|
341
|
+
collapsibleHeading: collapsibleHeading,
|
|
342
|
+
headingLevel: level
|
|
343
|
+
}, headingWithDuplicateAnchor);
|
|
344
|
+
}
|
|
345
|
+
return headingWithDuplicateAnchor;
|
|
236
346
|
}
|
|
237
347
|
export default Heading;
|
|
@@ -28,6 +28,7 @@ import { EmojiSharedCssClassName, defaultEmojiHeight, defaultDenseEmojiHeight, d
|
|
|
28
28
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
29
29
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
30
30
|
import { BodiedSyncBlockSharedCssClassName, SyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
31
|
+
import { COLLAPSED_CONTENT_OWNERS_ATTRIBUTE } from '../collapsible-headings-dom';
|
|
31
32
|
const wrappedMediaBreakoutPoint = 410;
|
|
32
33
|
const TELEPOINTER_ID = 'ai-streaming-telepointer';
|
|
33
34
|
const tableShadowWidth = 32;
|
|
@@ -86,6 +87,13 @@ const baseStyles = css({
|
|
|
86
87
|
clear: 'both'
|
|
87
88
|
},
|
|
88
89
|
[`.${RendererCssClassName.DOCUMENT}`]: {
|
|
90
|
+
[`> [${COLLAPSED_CONTENT_OWNERS_ATTRIBUTE}][hidden='until-found']`]: {
|
|
91
|
+
display: 'block',
|
|
92
|
+
minBlockSize: 0,
|
|
93
|
+
marginBlock: 0,
|
|
94
|
+
paddingBlock: 0,
|
|
95
|
+
borderBlockWidth: 0
|
|
96
|
+
},
|
|
89
97
|
// p, h3, and action items
|
|
90
98
|
[`.${INLINE_IMAGE_WRAPPER_CLASS_NAME}`]: {
|
|
91
99
|
height: '22px',
|
|
@@ -36,6 +36,7 @@ import { RendererContext as ActionsContext, RendererActionsContext } from '../Re
|
|
|
36
36
|
import { Provider as SmartCardStorageProvider } from '../SmartCardStorage';
|
|
37
37
|
import { ActiveHeaderIdProvider } from '../active-header-id-provider';
|
|
38
38
|
import { AnnotationsPositionContext, AnnotationsWrapper } from '../annotations';
|
|
39
|
+
import { CollapsibleHeadingsProvider } from '../collapsible-headings';
|
|
39
40
|
import { ErrorBoundary } from './ErrorBoundary';
|
|
40
41
|
import { BreakoutSSRInlineScript } from './breakout-ssr';
|
|
41
42
|
import { isInteractiveElement } from './click-to-edit';
|
|
@@ -58,7 +59,7 @@ export const DEGRADED_SEVERITY_THRESHOLD = 3000;
|
|
|
58
59
|
const TABLE_INFO_TIMEOUT = 10000;
|
|
59
60
|
const RENDER_EVENT_SAMPLE_RATE = 0.1;
|
|
60
61
|
const packageName = "@atlaskit/renderer";
|
|
61
|
-
const packageVersion = "133.
|
|
62
|
+
const packageVersion = "133.15.0";
|
|
62
63
|
const setAsQueryContainerStyles = css({
|
|
63
64
|
containerName: 'ak-renderer-wrapper',
|
|
64
65
|
containerType: 'inline-size'
|
|
@@ -457,6 +458,7 @@ export const RendererFunctionalComponent = props => {
|
|
|
457
458
|
...createRendererContext(props.featureFlags, props.isTopLevelRenderer),
|
|
458
459
|
timeZone: props.timeZone
|
|
459
460
|
}), [props.featureFlags, props.isTopLevelRenderer, createRendererContext, props.timeZone]);
|
|
461
|
+
const isCollapsibleHeadingsEnabled = props.allowCollapsibleHeadings === true && ['full-page', 'full-width', 'max'].includes(props.appearance || '') && rendererContext.isTopLevelRenderer && expValEquals('platform_renderer_collapsible_headings', 'isEnabled', true);
|
|
460
462
|
useScrollToBlock(editorRef, props.document, props.scrollToBlock);
|
|
461
463
|
try {
|
|
462
464
|
var _rendererContext$feat, _props$media;
|
|
@@ -514,7 +516,11 @@ export const RendererFunctionalComponent = props => {
|
|
|
514
516
|
doc: pmDoc,
|
|
515
517
|
schema: schema,
|
|
516
518
|
onAnalyticsEvent: fireAnalyticsEvent
|
|
517
|
-
},
|
|
519
|
+
}, jsx(CollapsibleHeadingsProvider, {
|
|
520
|
+
pmDocument: pmDoc,
|
|
521
|
+
rendererRef: editorRef,
|
|
522
|
+
isEnabled: isCollapsibleHeadingsEnabled
|
|
523
|
+
}, result))))))));
|
|
518
524
|
const rendererResult = props.truncated ? jsx(TruncatedWrapper, {
|
|
519
525
|
height: props.maxHeight,
|
|
520
526
|
fadeHeight: props.fadeOutHeight
|