@atlaskit/renderer 132.7.0 → 133.1.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 (54) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/cjs/analytics/enums.js +1 -0
  3. package/dist/cjs/react/index.js +3 -0
  4. package/dist/cjs/react/nodes/codeBlock/codeBlock.js +5 -1
  5. package/dist/cjs/react/nodes/codeBlock/components/codeBlockButtonContainer.js +7 -1
  6. package/dist/cjs/react/nodes/codeBlock/components/codeBlockContainer.js +4 -0
  7. package/dist/cjs/react/nodes/codeBlock/components/codeBlockDownloadButton.js +133 -0
  8. package/dist/cjs/react/nodes/codeBlock/windowedCodeBlock.js +4 -1
  9. package/dist/cjs/react/nodes/layoutColumn-compiled.js +3 -1
  10. package/dist/cjs/react/nodes/layoutColumn-emotion.js +3 -1
  11. package/dist/cjs/react/utils/use-select-all-trap.js +4 -4
  12. package/dist/cjs/steps/index.js +4 -4
  13. package/dist/cjs/ui/Renderer/ErrorBoundary.js +4 -4
  14. package/dist/cjs/ui/Renderer/index.js +4 -1
  15. package/dist/cjs/ui/annotations/element/mark.js +5 -3
  16. package/dist/es2019/analytics/enums.js +1 -0
  17. package/dist/es2019/react/index.js +3 -0
  18. package/dist/es2019/react/nodes/codeBlock/codeBlock.js +4 -1
  19. package/dist/es2019/react/nodes/codeBlock/components/codeBlockButtonContainer.js +7 -1
  20. package/dist/es2019/react/nodes/codeBlock/components/codeBlockContainer.js +4 -0
  21. package/dist/es2019/react/nodes/codeBlock/components/codeBlockDownloadButton.js +123 -0
  22. package/dist/es2019/react/nodes/codeBlock/windowedCodeBlock.js +4 -1
  23. package/dist/es2019/react/nodes/layoutColumn-compiled.js +3 -1
  24. package/dist/es2019/react/nodes/layoutColumn-emotion.js +3 -1
  25. package/dist/es2019/react/utils/use-select-all-trap.js +5 -4
  26. package/dist/es2019/steps/index.js +5 -4
  27. package/dist/es2019/ui/Renderer/ErrorBoundary.js +5 -4
  28. package/dist/es2019/ui/Renderer/index.js +4 -1
  29. package/dist/es2019/ui/annotations/element/mark.js +5 -3
  30. package/dist/esm/analytics/enums.js +1 -0
  31. package/dist/esm/react/index.js +3 -0
  32. package/dist/esm/react/nodes/codeBlock/codeBlock.js +5 -1
  33. package/dist/esm/react/nodes/codeBlock/components/codeBlockButtonContainer.js +7 -1
  34. package/dist/esm/react/nodes/codeBlock/components/codeBlockContainer.js +4 -0
  35. package/dist/esm/react/nodes/codeBlock/components/codeBlockDownloadButton.js +125 -0
  36. package/dist/esm/react/nodes/codeBlock/windowedCodeBlock.js +4 -1
  37. package/dist/esm/react/nodes/layoutColumn-compiled.js +3 -1
  38. package/dist/esm/react/nodes/layoutColumn-emotion.js +3 -1
  39. package/dist/esm/react/utils/use-select-all-trap.js +5 -4
  40. package/dist/esm/steps/index.js +5 -4
  41. package/dist/esm/ui/Renderer/ErrorBoundary.js +5 -4
  42. package/dist/esm/ui/Renderer/index.js +4 -1
  43. package/dist/esm/ui/annotations/element/mark.js +5 -3
  44. package/dist/types/analytics/enums.d.ts +1 -0
  45. package/dist/types/react/index.d.ts +2 -0
  46. package/dist/types/react/nodes/codeBlock/codeBlock.d.ts +1 -0
  47. package/dist/types/react/nodes/codeBlock/components/codeBlockButtonContainer.d.ts +3 -1
  48. package/dist/types/react/nodes/codeBlock/components/codeBlockContainer.d.ts +1 -1
  49. package/dist/types/react/nodes/codeBlock/components/codeBlockDownloadButton.d.ts +14 -0
  50. package/dist/types/react/nodes/codeBlock/windowedCodeBlock.d.ts +1 -1
  51. package/dist/types/react/types.d.ts +1 -0
  52. package/dist/types/ui/Renderer/index.d.ts +1 -0
  53. package/dist/types/ui/renderer-props.d.ts +1 -0
  54. package/package.json +56 -56
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @atlaskit/renderer
2
2
 
3
+ ## 133.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`19869b1832800`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/19869b1832800) -
8
+ Add download button to code block toolbar in Rovo Chat. When enabled via the
9
+ rovo_chat_code_block_download feature gate, users can download code snippets (HTML, Python,
10
+ Markdown, etc.) directly as a file with the correct extension (e.g. rovo-snippet.html,
11
+ rovo-snippet.py). Adds allowDownloadCodeBlock prop to ReactRenderer (opt-in, defaults to false).
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
17
+ ## 133.0.0
18
+
19
+ ### Major Changes
20
+
21
+ - [`f2dc9097319f0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f2dc9097319f0) - ###
22
+ Dropped support for _legacy_ Typescript 4 types. **Typescript 5 is now the new minimum**.
23
+
24
+ Removes the `typesVersions` property and `dist/types-ts4.5` directory from the dist.
25
+
26
+ Types are now exclusively via the `"types": "dist/types/index.d.ts"` property.
27
+
28
+ ```diff
29
+ - "typesVersions": {
30
+ - ">=4.5 <4.9": {
31
+ - "*": [
32
+ - "dist/types-ts4.5/*",
33
+ - "dist/types-ts4.5/index.d.ts"
34
+ - ]
35
+ - }
36
+ - },
37
+ ```
38
+
39
+ ### Minor Changes
40
+
41
+ - [`458ee17c2c8ee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/458ee17c2c8ee) -
42
+ Register layout column vertical alignment rendering experiment and gate renderer layout column
43
+ vertical alignment styles behind it
44
+
45
+ ### Patch Changes
46
+
47
+ - [`eb0de97776ce5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/eb0de97776ce5) -
48
+ cleanup to prefer static regex as part of ees019
49
+ - Updated dependencies
50
+
3
51
  ## 132.7.0
4
52
 
5
53
  ### Minor Changes
@@ -57,6 +57,7 @@ var ACTION_SUBJECT_ID = exports.ACTION_SUBJECT_ID = /*#__PURE__*/function (ACTIO
57
57
  ACTION_SUBJECT_ID["HOVER_LABEL"] = "hoverLabel";
58
58
  ACTION_SUBJECT_ID["INLINE_COMMENT"] = "inlineComment";
59
59
  ACTION_SUBJECT_ID["CODEBLOCK_COPY"] = "codeBlockCopy";
60
+ ACTION_SUBJECT_ID["CODEBLOCK_DOWNLOAD"] = "codeBlockDownload";
60
61
  ACTION_SUBJECT_ID["CODEBLOCK_WRAP"] = "codeBlockWrap";
61
62
  return ACTION_SUBJECT_ID;
62
63
  }({});
@@ -59,6 +59,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
59
59
  */
60
60
  (0, _defineProperty2.default)(this, "expandHeadingIds", []);
61
61
  (0, _defineProperty2.default)(this, "allowCopyToClipboard", false);
62
+ (0, _defineProperty2.default)(this, "allowDownloadCodeBlock", false);
62
63
  (0, _defineProperty2.default)(this, "allowWrapCodeBlock", false);
63
64
  (0, _defineProperty2.default)(this, "allowPlaceholderText", true);
64
65
  (0, _defineProperty2.default)(this, "allowCustomPanels", false);
@@ -197,6 +198,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
197
198
  this.disableActions = init.disableActions;
198
199
  this.allowHeadingAnchorLinks = init.allowHeadingAnchorLinks;
199
200
  this.allowCopyToClipboard = init.allowCopyToClipboard;
201
+ this.allowDownloadCodeBlock = init.allowDownloadCodeBlock;
200
202
  this.allowWrapCodeBlock = init.allowWrapCodeBlock;
201
203
  this.allowPlaceholderText = init.allowPlaceholderText;
202
204
  this.allowCustomPanels = init.allowCustomPanels;
@@ -663,6 +665,7 @@ var ReactSerializer = exports.default = /*#__PURE__*/function () {
663
665
  content: node.content ? node.content.toJSON() : undefined,
664
666
  allowHeadingAnchorLinks: this.allowHeadingAnchorLinks,
665
667
  allowCopyToClipboard: this.allowCopyToClipboard,
668
+ allowDownloadCodeBlock: this.allowDownloadCodeBlock,
666
669
  allowWrapCodeBlock: this.allowWrapCodeBlock,
667
670
  allowPlaceholderText: this.allowPlaceholderText,
668
671
  rendererAppearance: this.appearance,
@@ -28,6 +28,8 @@ function CodeBlock(props) {
28
28
  allowCopyToClipboard = _props$allowCopyToCli === void 0 ? false : _props$allowCopyToCli,
29
29
  _props$allowWrapCodeB = props.allowWrapCodeBlock,
30
30
  allowWrapCodeBlock = _props$allowWrapCodeB === void 0 ? false : _props$allowWrapCodeB,
31
+ _props$allowDownloadC = props.allowDownloadCodeBlock,
32
+ allowDownloadCodeBlock = _props$allowDownloadC === void 0 ? false : _props$allowDownloadC,
31
33
  codeBidiWarningTooltipEnabled = props.codeBidiWarningTooltipEnabled,
32
34
  _props$hideLineNumber = props.hideLineNumbers,
33
35
  hideLineNumbers = _props$hideLineNumber === void 0 ? false : _props$hideLineNumber,
@@ -43,7 +45,9 @@ function CodeBlock(props) {
43
45
  setWrapLongLines = _useState2[1];
44
46
  return (0, _react2.jsx)(_codeBlockContainer.default, {
45
47
  allowCopyToClipboard: allowCopyToClipboard,
46
- allowWrapCodeBlock: allowWrapCodeBlock
48
+ allowWrapCodeBlock: allowWrapCodeBlock,
49
+ allowDownloadCodeBlock: allowDownloadCodeBlock,
50
+ language: language
47
51
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
48
52
  ,
49
53
  className: className,
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.default = void 0;
8
8
  var _react = require("@emotion/react");
9
9
  var _codeBlockCopyButton = _interopRequireDefault(require("./codeBlockCopyButton"));
10
+ var _codeBlockDownloadButton = _interopRequireDefault(require("./codeBlockDownloadButton"));
10
11
  var _codeBlockWrapButton = _interopRequireDefault(require("./codeBlockWrapButton"));
11
12
  /**
12
13
  * @jsxRuntime classic
@@ -55,7 +56,9 @@ var codeBlockButtonsStyle = (0, _react.css)({
55
56
  });
56
57
  var CodeBlockButtonContainer = function CodeBlockButtonContainer(_ref) {
57
58
  var allowCopyToClipboard = _ref.allowCopyToClipboard,
59
+ allowDownloadCodeBlock = _ref.allowDownloadCodeBlock,
58
60
  allowWrapCodeBlock = _ref.allowWrapCodeBlock,
61
+ language = _ref.language,
59
62
  setWrapLongLines = _ref.setWrapLongLines,
60
63
  text = _ref.text,
61
64
  wrapLongLines = _ref.wrapLongLines;
@@ -63,7 +66,10 @@ var CodeBlockButtonContainer = function CodeBlockButtonContainer(_ref) {
63
66
  css: codeBlockButtonsWrapper
64
67
  }, (0, _react.jsx)("div", {
65
68
  css: codeBlockButtonsStyle
66
- }, allowWrapCodeBlock && (0, _react.jsx)(_codeBlockWrapButton.default, {
69
+ }, allowDownloadCodeBlock && (0, _react.jsx)(_codeBlockDownloadButton.default, {
70
+ content: text,
71
+ language: language !== null && language !== void 0 ? language : null
72
+ }), allowWrapCodeBlock && (0, _react.jsx)(_codeBlockWrapButton.default, {
67
73
  setWrapLongLines: setWrapLongLines,
68
74
  wrapLongLines: wrapLongLines
69
75
  }), allowCopyToClipboard && (0, _react.jsx)(_codeBlockCopyButton.default, {
@@ -48,9 +48,11 @@ var denseModeOverrides = (0, _react.css)((0, _defineProperty2.default)({}, "".co
48
48
  }));
49
49
  var CodeBlockContainer = function CodeBlockContainer(_ref) {
50
50
  var allowCopyToClipboard = _ref.allowCopyToClipboard,
51
+ allowDownloadCodeBlock = _ref.allowDownloadCodeBlock,
51
52
  allowWrapCodeBlock = _ref.allowWrapCodeBlock,
52
53
  children = _ref.children,
53
54
  className = _ref.className,
55
+ language = _ref.language,
54
56
  localId = _ref.localId,
55
57
  setWrapLongLines = _ref.setWrapLongLines,
56
58
  text = _ref.text,
@@ -62,7 +64,9 @@ var CodeBlockContainer = function CodeBlockContainer(_ref) {
62
64
  css: [codeBlockStyleOverrides, ((0, _expValEquals.expValEquals)('confluence_compact_text_format', 'isEnabled', true) || (0, _expValEquals.expValEquals)('cc_editor_ai_content_mode', 'variant', 'test') && (0, _platformFeatureFlags.fg)('platform_editor_content_mode_button_mvp')) && denseModeOverrides]
63
65
  }, (0, _react.jsx)(_codeBlockButtonContainer.default, {
64
66
  allowCopyToClipboard: allowCopyToClipboard,
67
+ allowDownloadCodeBlock: allowDownloadCodeBlock,
65
68
  allowWrapCodeBlock: allowWrapCodeBlock,
69
+ language: language,
66
70
  setWrapLongLines: setWrapLongLines,
67
71
  text: text,
68
72
  wrapLongLines: wrapLongLines
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _reactIntl = require("react-intl");
9
+ var _download = _interopRequireDefault(require("@atlaskit/icon/core/download"));
10
+ var _react = require("@emotion/react");
11
+ var _new = require("@atlaskit/button/new");
12
+ var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
13
+ var _messages = require("@atlaskit/editor-common/messages");
14
+ var _analyticsContext = _interopRequireDefault(require("../../../../analytics/analyticsContext"));
15
+ var _enums = require("../../../../analytics/enums");
16
+ /**
17
+ * @jsxRuntime classic
18
+ * @jsx jsx
19
+ */
20
+
21
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
22
+
23
+ /**
24
+ * NOTE: The language-to-extension mapping logic below is intentionally duplicated in
25
+ * platform/packages/ai-mate/conversation-assistant-utils/src/downloadCodeBlock.ts.
26
+ * This is because @atlaskit/renderer cannot import from @atlassian/conversation-assistant-utils
27
+ * (cross-package dependency not allowed). If you update the logic here, update it there too.
28
+ *
29
+ * Maps ADF code block language names to file extensions.
30
+ * Inlined here to avoid cross-package dependencies on ai-mate packages.
31
+ */
32
+ var languageToExtension = {
33
+ bash: 'sh',
34
+ c: 'c',
35
+ cpp: 'cpp',
36
+ css: 'css',
37
+ csv: 'csv',
38
+ go: 'go',
39
+ htm: 'html',
40
+ html: 'html',
41
+ java: 'java',
42
+ javascript: 'js',
43
+ js: 'js',
44
+ json: 'json',
45
+ jsx: 'jsx',
46
+ less: 'less',
47
+ markdown: 'md',
48
+ md: 'md',
49
+ python: 'py',
50
+ ruby: 'rb',
51
+ rust: 'rs',
52
+ scss: 'scss',
53
+ sh: 'sh',
54
+ shell: 'sh',
55
+ sql: 'sql',
56
+ ts: 'ts',
57
+ tsx: 'tsx',
58
+ typescript: 'ts',
59
+ xml: 'xml',
60
+ yaml: 'yaml',
61
+ yml: 'yaml'
62
+ };
63
+ var getFileExtension = function getFileExtension(language) {
64
+ var _languageToExtension$;
65
+ if (!language) {
66
+ return 'txt';
67
+ }
68
+ return (_languageToExtension$ = languageToExtension[language.toLowerCase()]) !== null && _languageToExtension$ !== void 0 ? _languageToExtension$ : 'txt';
69
+ };
70
+ var triggerDownload = function triggerDownload(content, language) {
71
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
72
+ if (typeof document === 'undefined') {
73
+ return;
74
+ }
75
+ var extension = getFileExtension(language);
76
+ var filename = "rovo-snippet.".concat(extension);
77
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
78
+ var doc = document;
79
+ var blob = new Blob([content], {
80
+ type: 'text/plain'
81
+ });
82
+ var url = URL.createObjectURL(blob);
83
+ var anchor = doc.createElement('a');
84
+ anchor.href = url;
85
+ anchor.download = filename;
86
+ anchor.style.display = 'none';
87
+ doc.body.appendChild(anchor);
88
+ anchor.dispatchEvent(new MouseEvent('click', {
89
+ bubbles: false,
90
+ cancelable: true,
91
+ view: window
92
+ }));
93
+ doc.body.removeChild(anchor);
94
+ // Defer revocation to avoid race condition in Safari/Firefox
95
+ setTimeout(function () {
96
+ return URL.revokeObjectURL(url);
97
+ }, 0);
98
+ };
99
+ var DownloadButton = function DownloadButton(_ref) {
100
+ var content = _ref.content,
101
+ language = _ref.language,
102
+ intl = _ref.intl;
103
+ var tooltip = intl.formatMessage(_messages.codeBlockButtonMessages.downloadCodeBlock);
104
+ return (0, _react.jsx)(_analyticsContext.default.Consumer, null, function (_ref2) {
105
+ var fireAnalyticsEvent = _ref2.fireAnalyticsEvent;
106
+ return (0, _react.jsx)("span", null, (0, _react.jsx)(_tooltip.default, {
107
+ content: tooltip,
108
+ hideTooltipOnClick: false,
109
+ position: "top"
110
+ }, (0, _react.jsx)("div", null, (0, _react.jsx)(_new.IconButton, {
111
+ appearance: "subtle",
112
+ label: tooltip,
113
+ icon: _download.default
114
+ // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
115
+ ,
116
+ onClick: function onClick(event) {
117
+ fireAnalyticsEvent({
118
+ // @ts-expect-error - Type 'ACTION.CLICKED' is not assignable to type 'ACTION.CLICKED | ACTION.MEDIA_LINK_TRANSFORMED | ACTION.STARTED | ACTION.TOGGLE_EXPAND | ACTION.UNSUPPORTED_CONTENT_ENCOUNTERED | ACTION.VISITED | ACTION.RENDERED | ACTION.INVALID_PROSEMIRROR_DOCUMENT | ACTION.CRASHED | ... 6 more ... | AnnotationActionType'.
119
+ // This error was introduced after upgrading to TypeScript 5
120
+ action: _enums.ACTION.CLICKED,
121
+ actionSubject: _enums.ACTION_SUBJECT.BUTTON,
122
+ actionSubjectId: _enums.ACTION_SUBJECT_ID.CODEBLOCK_DOWNLOAD,
123
+ eventType: _enums.EVENT_TYPE.UI
124
+ });
125
+ triggerDownload(content, language);
126
+ event.stopPropagation();
127
+ },
128
+ spacing: "compact"
129
+ }))));
130
+ });
131
+ };
132
+ var _default_1 = (0, _reactIntl.injectIntl)(DownloadButton);
133
+ var _default = exports.default = _default_1;
@@ -50,6 +50,7 @@ var WindowedCodeBlock = function WindowedCodeBlock(_ref2) {
50
50
  var text = _ref2.text,
51
51
  language = _ref2.language,
52
52
  allowCopyToClipboard = _ref2.allowCopyToClipboard,
53
+ allowDownloadCodeBlock = _ref2.allowDownloadCodeBlock,
53
54
  _ref2$allowWrapCodeBl = _ref2.allowWrapCodeBlock,
54
55
  allowWrapCodeBlock = _ref2$allowWrapCodeBl === void 0 ? false : _ref2$allowWrapCodeBl,
55
56
  codeBidiWarningTooltipEnabled = _ref2.codeBidiWarningTooltipEnabled,
@@ -84,7 +85,9 @@ var WindowedCodeBlock = function WindowedCodeBlock(_ref2) {
84
85
  fallback: memoizedLightWeightCodeBlock
85
86
  }, (0, _react2.jsx)(_codeBlockContainer.default, {
86
87
  allowCopyToClipboard: allowCopyToClipboard,
87
- allowWrapCodeBlock: allowWrapCodeBlock
88
+ allowWrapCodeBlock: allowWrapCodeBlock,
89
+ allowDownloadCodeBlock: allowDownloadCodeBlock,
90
+ language: language
88
91
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
89
92
  ,
90
93
  className: className,
@@ -28,6 +28,8 @@ var multipleWrappedImagesStyle = null;
28
28
  var clearNextSiblingBlockMarkMarginTopStyle = null;
29
29
  var LayoutSectionCompiled = exports.LayoutSectionCompiled = function LayoutSectionCompiled(props) {
30
30
  var isLayoutColumnMenuEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_menu', 'isEnabled', true);
31
+ // Pure rollout gate: no A/B exposure analysis is planned for this rendering switch.
32
+ var isLayoutColumnValignRenderingEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_valign_rendering', 'isEnabled', true);
31
33
  return /*#__PURE__*/_react.default.createElement("div", {
32
34
  "data-layout-column": true,
33
35
  "data-column-width": props.width,
@@ -37,7 +39,7 @@ var LayoutSectionCompiled = exports.LayoutSectionCompiled = function LayoutSecti
37
39
  style: {
38
40
  flexBasis: "".concat(props.width, "%")
39
41
  },
40
- className: (0, _runtime.ax)([isLayoutColumnMenuEnabled && props.valign === 'middle' && "_1e0c1txw _2lx21bp4 _1bah1h6o", isLayoutColumnMenuEnabled && props.valign === 'bottom' && "_1e0c1txw _2lx21bp4 _1bahesu3", (0, _platformFeatureFlags.fg)('platform_editor_fix_media_in_renderer') && "_1tihidpf _12kpidpf"])
42
+ className: (0, _runtime.ax)([(isLayoutColumnValignRenderingEnabled || isLayoutColumnMenuEnabled) && props.valign === 'middle' && "_1e0c1txw _2lx21bp4 _1bah1h6o", (isLayoutColumnValignRenderingEnabled || isLayoutColumnMenuEnabled) && props.valign === 'bottom' && "_1e0c1txw _2lx21bp4 _1bahesu3", (0, _platformFeatureFlags.fg)('platform_editor_fix_media_in_renderer') && "_1tihidpf _12kpidpf"])
41
43
  }, /*#__PURE__*/_react.default.createElement(_ui.WidthProvider, null, /*#__PURE__*/_react.default.createElement("div", {
42
44
  className: (0, _runtime.ax)(["_1skbgrf3", "_19segrf3 _1ki1grf3 _bmdegrf3 _166hgrf3 _7g1ogrf3 _sk2jgrf3 _hgeogrf3"])
43
45
  }), props.children));
@@ -58,6 +58,8 @@ var clearNextSiblingBlockMarkMarginTopStyle = (0, _react2.css)((0, _defineProper
58
58
  }));
59
59
  var LayoutSectionEmotion = exports.LayoutSectionEmotion = function LayoutSectionEmotion(props) {
60
60
  var isLayoutColumnMenuEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_menu', 'isEnabled', true);
61
+ // Pure rollout gate: no A/B exposure analysis is planned for this rendering switch.
62
+ var isLayoutColumnValignRenderingEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_layout_column_valign_rendering', 'isEnabled', true);
61
63
  return (0, _react2.jsx)("div", {
62
64
  "data-layout-column": true,
63
65
  "data-column-width": props.width,
@@ -69,7 +71,7 @@ var LayoutSectionEmotion = exports.LayoutSectionEmotion = function LayoutSection
69
71
  },
70
72
  css: [
71
73
  // Keep separate: Compiled crashes on ternary/object lookup here.
72
- isLayoutColumnMenuEnabled && props.valign === 'middle' && verticalAlignMiddleStyles, isLayoutColumnMenuEnabled && props.valign === 'bottom' && verticalAlignBottomStyles, (0, _platformFeatureFlags.fg)('platform_editor_fix_media_in_renderer') && multipleWrappedImagesStyle]
74
+ (isLayoutColumnValignRenderingEnabled || isLayoutColumnMenuEnabled) && props.valign === 'middle' && verticalAlignMiddleStyles, (isLayoutColumnValignRenderingEnabled || isLayoutColumnMenuEnabled) && props.valign === 'bottom' && verticalAlignBottomStyles, (0, _platformFeatureFlags.fg)('platform_editor_fix_media_in_renderer') && multipleWrappedImagesStyle]
73
75
  }, (0, _react2.jsx)(_ui.WidthProvider, null, (0, _react2.jsx)("div", {
74
76
  css: [clearNextSiblingMarginTopStyle, clearNextSiblingBlockMarkMarginTopStyle]
75
77
  }), props.children));
@@ -9,16 +9,16 @@ var _analytics = require("@atlaskit/editor-common/analytics");
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _analyticsContext = _interopRequireDefault(require("../../analytics/analyticsContext"));
11
11
  var _elementSelection = require("./element-selection");
12
+ // Ignored via go/ees005
13
+ // eslint-disable-next-line require-unicode-regexp
14
+ var MAC_PLATFORM_REGEX = /Mac/;
12
15
  var useSelectAllTrap = exports.useSelectAllTrap = function useSelectAllTrap() {
13
16
  var _React$useContext = _react.default.useContext(_analyticsContext.default),
14
17
  fireAnalyticsEvent = _React$useContext.fireAnalyticsEvent;
15
18
  var ref = _react.default.useRef(null);
16
19
  var clicked = _react.default.useRef(false);
17
20
  var caught = _react.default.useRef();
18
-
19
- // Ignored via go/ees005
20
- // eslint-disable-next-line require-unicode-regexp
21
- var mac = typeof navigator !== 'undefined' ? /Mac/.test(navigator.platform) : false;
21
+ var mac = typeof navigator !== 'undefined' ? MAC_PLATFORM_REGEX.test(navigator.platform) : false;
22
22
  var onKeyDown = _react.default.useCallback(function (e) {
23
23
  var _e$target, _e$target$matches;
24
24
  var el = ref.current;
@@ -13,6 +13,9 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
13
  var _transform = require("@atlaskit/editor-prosemirror/transform");
14
14
  /* eslint-disable jsdoc/require-jsdoc -- internal step helpers */
15
15
 
16
+ // Ignored via go/ees005
17
+ // eslint-disable-next-line require-unicode-regexp
18
+ var MEDIA_OR_MEDIA_SINGLE_REGEX = /media|mediaSingle/;
16
19
  function getStartPos(element) {
17
20
  return parseInt(element.dataset.rendererStartPos || '-1', 10);
18
21
  }
@@ -231,10 +234,7 @@ function getPosFromRange(range) {
231
234
  var possibleMediaOrMediaSingleElement = findParent(startContainer);
232
235
 
233
236
  // Video hover targets return media single, not media, thus, the extra check in condition.
234
- var isMediaOrMediaSingle = possibleMediaOrMediaSingleElement &&
235
- // Ignored via go/ees005
236
- // eslint-disable-next-line require-unicode-regexp
237
- /media|mediaSingle/.test(getNodeType(possibleMediaOrMediaSingleElement) || '');
237
+ var isMediaOrMediaSingle = possibleMediaOrMediaSingleElement && MEDIA_OR_MEDIA_SINGLE_REGEX.test(getNodeType(possibleMediaOrMediaSingleElement) || '');
238
238
  if (isMediaOrMediaSingle) {
239
239
  var pos;
240
240
  var mediaSingleElement = getNodeType(possibleMediaOrMediaSingleElement) === 'mediaSingle' ? possibleMediaOrMediaSingleElement : findMediaParent(possibleMediaOrMediaSingleElement);
@@ -21,6 +21,9 @@ var _uuid = _interopRequireDefault(require("uuid"));
21
21
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
22
22
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
23
23
  // Ignored via go/ees005
24
+ // eslint-disable-next-line require-unicode-regexp
25
+ var FAILED_TO_EXECUTE_REGEX = /Failed to execute.*on 'Node'.*/;
26
+ // Ignored via go/ees005
24
27
  // eslint-disable-next-line @repo/internal/react/no-class-components
25
28
  var ErrorBoundary = exports.ErrorBoundary = /*#__PURE__*/function (_React$Component) {
26
29
  function ErrorBoundary() {
@@ -78,10 +81,7 @@ var ErrorBoundary = exports.ErrorBoundary = /*#__PURE__*/function (_React$Compon
78
81
  (0, _monitoring.logException)(error, {
79
82
  location: 'renderer'
80
83
  });
81
- // Ignored via go/ees005
82
- // eslint-disable-next-line require-unicode-regexp
83
- var pattern = /Failed to execute.*on 'Node'.*/;
84
- var matchesPattern = pattern.test(error.message);
84
+ var matchesPattern = FAILED_TO_EXECUTE_REGEX.test(error.message);
85
85
  if (matchesPattern) {
86
86
  this.fireAnalyticsEvent({
87
87
  action: _analytics.ACTION.CAUGHT_DOM_ERROR,
@@ -72,7 +72,7 @@ var DEGRADED_SEVERITY_THRESHOLD = exports.DEGRADED_SEVERITY_THRESHOLD = 3000;
72
72
  var TABLE_INFO_TIMEOUT = 10000;
73
73
  var RENDER_EVENT_SAMPLE_RATE = 0.2;
74
74
  var packageName = "@atlaskit/renderer";
75
- var packageVersion = "132.7.0";
75
+ var packageVersion = "133.0.0";
76
76
  var setAsQueryContainerStyles = (0, _react2.css)({
77
77
  containerName: 'ak-renderer-wrapper',
78
78
  containerType: 'inline-size'
@@ -263,6 +263,7 @@ var RendererFunctionalComponent = exports.RendererFunctionalComponent = function
263
263
  extensionViewportSizes: props.extensionViewportSizes,
264
264
  getExtensionHeight: props.getExtensionHeight,
265
265
  allowCopyToClipboard: props.allowCopyToClipboard,
266
+ allowDownloadCodeBlock: props.allowDownloadCodeBlock,
266
267
  allowWrapCodeBlock: props.allowWrapCodeBlock,
267
268
  allowCustomPanels: props.allowCustomPanels,
268
269
  allowAnnotations: props.allowAnnotations,
@@ -482,6 +483,7 @@ var RendererFunctionalComponent = exports.RendererFunctionalComponent = function
482
483
  allowNestedHeaderLinks: (0, _links.isNestedHeaderLinksEnabled)(props.allowHeadingAnchorLinks),
483
484
  allowColumnSorting: props.allowColumnSorting,
484
485
  allowCopyToClipboard: props.allowCopyToClipboard,
486
+ allowDownloadCodeBlock: props.allowDownloadCodeBlock,
485
487
  allowWrapCodeBlock: props.allowWrapCodeBlock,
486
488
  allowCustomPanels: props.allowCustomPanels,
487
489
  allowPlaceholderText: props.allowPlaceholderText,
@@ -521,6 +523,7 @@ var RendererFunctionalComponent = exports.RendererFunctionalComponent = function
521
523
  appearance: props.appearance,
522
524
  contentMode: props.contentMode || 'standard',
523
525
  allowCopyToClipboard: props.allowCopyToClipboard,
526
+ allowDownloadCodeBlock: props.allowDownloadCodeBlock,
524
527
  allowWrapCodeBlock: props.allowWrapCodeBlock,
525
528
  allowPlaceholderText: props.allowPlaceholderText,
526
529
  allowColumnSorting: props.allowColumnSorting,
@@ -88,10 +88,12 @@ var markStylesWithCommentsPanel = (0, _react2.css)((0, _defineProperty2.default)
88
88
  boxShadow: "var(--ds-shadow-overlay, 0px 8px 12px #1E1F2126, 0px 0px 1px #1E1F214f)"
89
89
  }
90
90
  }));
91
+
92
+ // Ignored via go/ees005
93
+ // eslint-disable-next-line require-unicode-regexp
94
+ var MOBILE_USER_AGENT_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
91
95
  var isMobile = function isMobile() {
92
- // Ignored via go/ees005
93
- // eslint-disable-next-line require-unicode-regexp
94
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
96
+ return MOBILE_USER_AGENT_REGEX.test(navigator.userAgent);
95
97
  };
96
98
  var accessibilityStylesNew = (0, _react2.css)({
97
99
  '&::before, &::after': {
@@ -51,6 +51,7 @@ export let ACTION_SUBJECT_ID = /*#__PURE__*/function (ACTION_SUBJECT_ID) {
51
51
  ACTION_SUBJECT_ID["HOVER_LABEL"] = "hoverLabel";
52
52
  ACTION_SUBJECT_ID["INLINE_COMMENT"] = "inlineComment";
53
53
  ACTION_SUBJECT_ID["CODEBLOCK_COPY"] = "codeBlockCopy";
54
+ ACTION_SUBJECT_ID["CODEBLOCK_DOWNLOAD"] = "codeBlockDownload";
54
55
  ACTION_SUBJECT_ID["CODEBLOCK_WRAP"] = "codeBlockWrap";
55
56
  return ACTION_SUBJECT_ID;
56
57
  }({});
@@ -43,6 +43,7 @@ export default class ReactSerializer {
43
43
  */
44
44
  _defineProperty(this, "expandHeadingIds", []);
45
45
  _defineProperty(this, "allowCopyToClipboard", false);
46
+ _defineProperty(this, "allowDownloadCodeBlock", false);
46
47
  _defineProperty(this, "allowWrapCodeBlock", false);
47
48
  _defineProperty(this, "allowPlaceholderText", true);
48
49
  _defineProperty(this, "allowCustomPanels", false);
@@ -184,6 +185,7 @@ export default class ReactSerializer {
184
185
  this.disableActions = init.disableActions;
185
186
  this.allowHeadingAnchorLinks = init.allowHeadingAnchorLinks;
186
187
  this.allowCopyToClipboard = init.allowCopyToClipboard;
188
+ this.allowDownloadCodeBlock = init.allowDownloadCodeBlock;
187
189
  this.allowWrapCodeBlock = init.allowWrapCodeBlock;
188
190
  this.allowPlaceholderText = init.allowPlaceholderText;
189
191
  this.allowCustomPanels = init.allowCustomPanels;
@@ -593,6 +595,7 @@ export default class ReactSerializer {
593
595
  content: node.content ? node.content.toJSON() : undefined,
594
596
  allowHeadingAnchorLinks: this.allowHeadingAnchorLinks,
595
597
  allowCopyToClipboard: this.allowCopyToClipboard,
598
+ allowDownloadCodeBlock: this.allowDownloadCodeBlock,
596
599
  allowWrapCodeBlock: this.allowWrapCodeBlock,
597
600
  allowPlaceholderText: this.allowPlaceholderText,
598
601
  rendererAppearance: this.appearance,
@@ -17,6 +17,7 @@ function CodeBlock(props) {
17
17
  language,
18
18
  allowCopyToClipboard = false,
19
19
  allowWrapCodeBlock = false,
20
+ allowDownloadCodeBlock = false,
20
21
  codeBidiWarningTooltipEnabled,
21
22
  hideLineNumbers = false,
22
23
  localId,
@@ -27,7 +28,9 @@ function CodeBlock(props) {
27
28
  const [wrapLongLines, setWrapLongLines] = useState(() => expValEquals('platform_editor_code_block_q4_lovability', 'isEnabled', true) && Boolean(wrap));
28
29
  return jsx(CodeBlockContainer, {
29
30
  allowCopyToClipboard: allowCopyToClipboard,
30
- allowWrapCodeBlock: allowWrapCodeBlock
31
+ allowWrapCodeBlock: allowWrapCodeBlock,
32
+ allowDownloadCodeBlock: allowDownloadCodeBlock,
33
+ language: language
31
34
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
32
35
  ,
33
36
  className: className,
@@ -5,6 +5,7 @@
5
5
  /* eslint-disable @typescript-eslint/consistent-type-imports, @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766; jsx required at runtime for @jsxRuntime classic */
6
6
  import { jsx, css } from '@emotion/react';
7
7
  import CopyButton from './codeBlockCopyButton';
8
+ import DownloadButton from './codeBlockDownloadButton';
8
9
  import CodeWrapButton from './codeBlockWrapButton';
9
10
  const codeBlockButtonsWrapper = css({
10
11
  position: 'sticky',
@@ -47,7 +48,9 @@ const codeBlockButtonsStyle = css({
47
48
  });
48
49
  const CodeBlockButtonContainer = ({
49
50
  allowCopyToClipboard,
51
+ allowDownloadCodeBlock,
50
52
  allowWrapCodeBlock,
53
+ language,
51
54
  setWrapLongLines,
52
55
  text,
53
56
  wrapLongLines
@@ -56,7 +59,10 @@ const CodeBlockButtonContainer = ({
56
59
  css: codeBlockButtonsWrapper
57
60
  }, jsx("div", {
58
61
  css: codeBlockButtonsStyle
59
- }, allowWrapCodeBlock && jsx(CodeWrapButton, {
62
+ }, allowDownloadCodeBlock && jsx(DownloadButton, {
63
+ content: text,
64
+ language: language !== null && language !== void 0 ? language : null
65
+ }), allowWrapCodeBlock && jsx(CodeWrapButton, {
60
66
  setWrapLongLines: setWrapLongLines,
61
67
  wrapLongLines: wrapLongLines
62
68
  }), allowCopyToClipboard && jsx(CopyButton, {
@@ -76,9 +76,11 @@ const denseModeOverrides = css({
76
76
  });
77
77
  const CodeBlockContainer = ({
78
78
  allowCopyToClipboard,
79
+ allowDownloadCodeBlock,
79
80
  allowWrapCodeBlock,
80
81
  children,
81
82
  className,
83
+ language,
82
84
  localId,
83
85
  setWrapLongLines,
84
86
  text,
@@ -91,7 +93,9 @@ const CodeBlockContainer = ({
91
93
  css: [codeBlockStyleOverrides, (expValEquals('confluence_compact_text_format', 'isEnabled', true) || expValEquals('cc_editor_ai_content_mode', 'variant', 'test') && fg('platform_editor_content_mode_button_mvp')) && denseModeOverrides]
92
94
  }, jsx(CodeBlockButtonContainer, {
93
95
  allowCopyToClipboard: allowCopyToClipboard,
96
+ allowDownloadCodeBlock: allowDownloadCodeBlock,
94
97
  allowWrapCodeBlock: allowWrapCodeBlock,
98
+ language: language,
95
99
  setWrapLongLines: setWrapLongLines,
96
100
  text: text,
97
101
  wrapLongLines: wrapLongLines