@atlaskit/renderer 112.6.12 → 112.6.13

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/renderer
2
2
 
3
+ ## 112.6.13
4
+
5
+ ### Patch Changes
6
+
7
+ - [#156429](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/156429)
8
+ [`01453825d9537`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/01453825d9537) -
9
+ added renderer functional component behind FF as part of React18 upgrade
10
+
3
11
  ## 112.6.12
4
12
 
5
13
  ### Patch Changes
@@ -210,6 +210,7 @@ var RendererActions = exports.default = /*#__PURE__*/function () {
210
210
  }
211
211
  }
212
212
 
213
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
213
214
  /**
214
215
  * This is replaced by `isRangeAnnotatable`.
215
216
  *
@@ -65,7 +65,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
65
65
  var NORMAL_SEVERITY_THRESHOLD = exports.NORMAL_SEVERITY_THRESHOLD = 2000;
66
66
  var DEGRADED_SEVERITY_THRESHOLD = exports.DEGRADED_SEVERITY_THRESHOLD = 3000;
67
67
  var packageName = "@atlaskit/renderer";
68
- var packageVersion = "112.6.12";
68
+ var packageVersion = "112.6.13";
69
69
  var setAsQueryContainerStyles = (0, _react2.css)({
70
70
  containerName: 'ak-renderer-wrapper',
71
71
  containerType: 'inline-size',
@@ -76,6 +76,7 @@ var defaultNodeComponents = exports.defaultNodeComponents = _nodes.nodeToReact;
76
76
  /**
77
77
  * Exported due to enzyme test reliance on this component.
78
78
  */
79
+ // eslint-disable-next-line @repo/internal/react/no-class-components
79
80
  var __RendererClassComponent = exports.__RendererClassComponent = /*#__PURE__*/function (_PureComponent) {
80
81
  (0, _inherits2.default)(__RendererClassComponent, _PureComponent);
81
82
  var _super = _createSuper(__RendererClassComponent);
@@ -445,18 +446,357 @@ var __RendererClassComponent = exports.__RendererClassComponent = /*#__PURE__*/f
445
446
  }]);
446
447
  return __RendererClassComponent;
447
448
  }(_react.PureComponent);
449
+ var handleMouseTripleClickInTables = function handleMouseTripleClickInTables(event) {
450
+ var _parentElement3, _parentElement4;
451
+ if (_browser.browser.ios || _browser.browser.android) {
452
+ return;
453
+ }
454
+ var badBrowser = _browser.browser.chrome || _browser.browser.safari;
455
+ var tripleClick = event.detail >= 3;
456
+ if (!(badBrowser && tripleClick)) {
457
+ return;
458
+ }
459
+ var selection = window.getSelection();
460
+ if (!selection) {
461
+ return;
462
+ }
463
+ var type = selection.type,
464
+ anchorNode = selection.anchorNode,
465
+ focusNode = selection.focusNode;
466
+ var rangeSelection = Boolean(type === 'Range' && anchorNode && focusNode);
467
+ if (!rangeSelection) {
468
+ return;
469
+ }
470
+ var target = event.target;
471
+ var tableCell = target.closest('td,th');
472
+ var clickedInCell = Boolean(tableCell);
473
+ if (!clickedInCell) {
474
+ return;
475
+ }
476
+ var anchorInCell = tableCell.contains(anchorNode);
477
+ var focusInCell = tableCell.contains(focusNode);
478
+ var selectionStartsOrEndsOutsideClickedCell = !(anchorInCell && focusInCell);
479
+ if (!selectionStartsOrEndsOutsideClickedCell) {
480
+ return;
481
+ }
482
+
483
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
484
+ // This logic originated in jira-frontend:
485
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
486
+
487
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
488
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
489
+ // return an empty selection, which will erroneously fire onUnhandledClick.
490
+
491
+ var elementToSelect = anchorInCell ? (_parentElement3 = anchorNode.parentElement) === null || _parentElement3 === void 0 ? void 0 : _parentElement3.closest('div,p') : focusInCell ? (_parentElement4 = focusNode.parentElement) === null || _parentElement4 === void 0 ? void 0 : _parentElement4.closest('div,p') : tableCell;
492
+ if (elementToSelect) {
493
+ selection.selectAllChildren(elementToSelect);
494
+ }
495
+ };
496
+
497
+ /**
498
+ * Handle clicks inside renderer. If the click isn't on media, in the media picker, or on a
499
+ * link, call the onUnhandledClick eventHandler (which in Jira for example, may switch the
500
+ * renderer out for the editor).
501
+ * @param event Click event anywhere inside renderer
502
+ */
503
+ var handleWrapperOnClick = function handleWrapperOnClick(event, props, mouseDownSelection) {
504
+ var _props$eventHandlers;
505
+ var targetElement = event.target;
506
+ handleMouseTripleClickInTables(event);
507
+
508
+ // ED-14862: When a user triple clicks to select a line of content inside a
509
+ // a table cell, but the browser incorrectly moves the selection start or end into
510
+ // a different table cell, we manually set the selection back to within the original
511
+ // table cell the user intended to target
512
+ if (!((_props$eventHandlers = props.eventHandlers) !== null && _props$eventHandlers !== void 0 && _props$eventHandlers.onUnhandledClick)) {
513
+ return;
514
+ }
515
+ if (!(targetElement instanceof window.Element)) {
516
+ return;
517
+ }
518
+ var rendererWrapper = event.currentTarget;
519
+ var isInteractiveElementInTree = (0, _utils2.findInTree)(targetElement, rendererWrapper, _clickToEdit.isInteractiveElement);
520
+ if (isInteractiveElementInTree) {
521
+ return;
522
+ }
523
+
524
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
525
+ // This logic originated in jira-frontend:
526
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
527
+
528
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
529
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
530
+ // return an empty selection, which will erroneously fire onUnhandledClick.
531
+ var windowSelection = window.getSelection();
532
+ var selection = windowSelection !== null ? windowSelection.toString() : undefined;
533
+ var hasSelection = selection && selection.length !== 0;
534
+ var hasSelectionMouseDown = mouseDownSelection.current && mouseDownSelection.current.length !== 0;
535
+ var allowEditBasedOnSelection = !hasSelection && !hasSelectionMouseDown;
536
+ if (allowEditBasedOnSelection) {
537
+ props.eventHandlers.onUnhandledClick(event);
538
+ }
539
+ };
540
+ var RendererFunctionalComponent = function RendererFunctionalComponent(props) {
541
+ var mouseDownSelection = (0, _react.useRef)(undefined);
542
+ var providerFactory = (0, _react.useMemo)(function () {
543
+ return props.dataProviders || new _providerFactory.ProviderFactory();
544
+ }, [props.dataProviders]);
545
+ var createRendererContext = (0, _react.useMemo)(function () {
546
+ return function (featureFlags, isTopLevelRenderer) {
547
+ var normalizedFeatureFlags = (0, _normalizeFeatureFlags.normalizeFeatureFlags)(featureFlags);
548
+ return {
549
+ featureFlags: normalizedFeatureFlags,
550
+ isTopLevelRenderer: isTopLevelRenderer === undefined
551
+ };
552
+ };
553
+ }, []);
554
+ var _fireAnalyticsEvent = (0, _react.useCallback)(function (event) {
555
+ var createAnalyticsEvent = props.createAnalyticsEvent;
556
+ if (createAnalyticsEvent) {
557
+ var channel = _types.FabricChannel.editor;
558
+ createAnalyticsEvent(event).fire(channel);
559
+ }
560
+ }, [props]);
561
+ var deriveSerializerProps = (0, _react.useCallback)(function (props) {
562
+ var stickyHeaders = props.stickyHeaders ? props.stickyHeaders === true ? {} : props.stickyHeaders : undefined;
563
+ var annotationProvider = props.annotationProvider;
564
+ var allowAnnotationsDraftMode = Boolean(annotationProvider && annotationProvider.inlineComment && annotationProvider.inlineComment.allowDraftMode);
565
+ var _createRendererContex = createRendererContext(props.featureFlags, props.isTopLevelRenderer),
566
+ featureFlags = _createRendererContex.featureFlags;
567
+ return {
568
+ startPos: props.startPos,
569
+ providers: providerFactory,
570
+ eventHandlers: props.eventHandlers,
571
+ extensionHandlers: props.extensionHandlers,
572
+ portal: props.portal,
573
+ objectContext: _objectSpread({
574
+ adDoc: props.document,
575
+ schema: props.schema
576
+ }, props.rendererContext),
577
+ appearance: props.appearance,
578
+ disableHeadingIDs: props.disableHeadingIDs,
579
+ disableActions: props.disableActions,
580
+ allowHeadingAnchorLinks: props.allowHeadingAnchorLinks,
581
+ allowColumnSorting: props.allowColumnSorting,
582
+ fireAnalyticsEvent: _fireAnalyticsEvent,
583
+ shouldOpenMediaViewer: props.shouldOpenMediaViewer,
584
+ allowAltTextOnImages: props.allowAltTextOnImages,
585
+ stickyHeaders: stickyHeaders,
586
+ allowMediaLinking: props.media && props.media.allowLinking,
587
+ surroundTextNodesWithTextWrapper: allowAnnotationsDraftMode,
588
+ media: props.media,
589
+ emojiResourceConfig: props.emojiResourceConfig,
590
+ smartLinks: props.smartLinks,
591
+ allowCopyToClipboard: props.allowCopyToClipboard,
592
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
593
+ allowCustomPanels: props.allowCustomPanels,
594
+ allowAnnotations: props.allowAnnotations,
595
+ allowSelectAllTrap: props.allowSelectAllTrap,
596
+ allowPlaceholderText: props.allowPlaceholderText,
597
+ nodeComponents: props.nodeComponents,
598
+ allowWindowedCodeBlock: featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.allowWindowedCodeBlock,
599
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
600
+ textHighlighter: props.UNSTABLE_textHighlighter,
601
+ allowTableAlignment: props.UNSTABLE_allowTableAlignment,
602
+ allowTableResizing: props.UNSTABLE_allowTableResizing
603
+ };
604
+ }, [createRendererContext, providerFactory, _fireAnalyticsEvent]);
605
+ var serializer = (0, _react.useMemo)(function () {
606
+ var _props$startPos;
607
+ return new _.ReactSerializer(deriveSerializerProps(_objectSpread(_objectSpread({}, props), {}, {
608
+ startPos: (_props$startPos = props.startPos) !== null && _props$startPos !== void 0 ? _props$startPos : 0
609
+ })));
610
+ }, [deriveSerializerProps, props]);
611
+ var localRef = (0, _react.useRef)(null);
612
+ var editorRef = props.innerRef || localRef;
613
+ var id = (0, _react.useMemo)(function () {
614
+ return (0, _v.default)();
615
+ }, []);
616
+ var renderedMeasurementDistortedDurationMonitor = (0, _react.useMemo)(function () {
617
+ return (0, _measureRender.getDistortedDurationMonitor)();
618
+ }, []);
619
+
620
+ // we are doing this to ensure it runs as
621
+ // early as possible in the React lifecycle
622
+ // to avoid any other side effects
623
+ var measureStarted = (0, _react.useRef)(false);
624
+ var startAnalyticsMeasure = function startAnalyticsMeasure() {
625
+ (0, _performanceMeasures.startMeasure)("Renderer Render Time: ".concat(id));
626
+ };
627
+ if (!measureStarted.current) {
628
+ startAnalyticsMeasure();
629
+ measureStarted.current = true;
630
+ }
631
+ var anchorLinkAnalytics = (0, _react.useCallback)(function () {
632
+ var hash = window.location.hash && decodeURIComponent(window.location.hash.slice(1));
633
+ var disableHeadingIDs = props.disableHeadingIDs;
634
+ if (!disableHeadingIDs && hash && editorRef && editorRef.current instanceof HTMLElement) {
635
+ var anchorLinkElement = document.getElementById(hash);
636
+ if (anchorLinkElement && editorRef.current.contains(anchorLinkElement)) {
637
+ _fireAnalyticsEvent({
638
+ action: _analytics.ACTION.VIEWED,
639
+ actionSubject: _analytics.ACTION_SUBJECT.ANCHOR_LINK,
640
+ attributes: {
641
+ platform: _events.PLATFORM.WEB,
642
+ mode: _events.MODE.RENDERER
643
+ },
644
+ eventType: _analytics.EVENT_TYPE.UI
645
+ });
646
+ }
647
+ }
648
+ }, [props.disableHeadingIDs, editorRef, _fireAnalyticsEvent]);
649
+ var getSchema = (0, _react.useMemo)(function () {
650
+ return function (schema, adfStage) {
651
+ if (schema) {
652
+ return schema;
653
+ }
654
+ return (0, _schemaDefault.getSchemaBasedOnStage)(adfStage);
655
+ };
656
+ }, []);
657
+ var onMouseDownEditView = function onMouseDownEditView() {
658
+ var windowSelection = window.getSelection();
659
+ mouseDownSelection.current = windowSelection !== null ? windowSelection.toString() : undefined;
660
+ };
661
+ var dataProviders = props.dataProviders,
662
+ analyticsEventSeverityTracking = props.analyticsEventSeverityTracking;
663
+ (0, _react.useEffect)(function () {
664
+ var rafID;
665
+ var handleAnalytics = function handleAnalytics() {
666
+ _fireAnalyticsEvent({
667
+ action: _analytics.ACTION.STARTED,
668
+ actionSubject: _analytics.ACTION_SUBJECT.RENDERER,
669
+ attributes: {
670
+ platform: _events.PLATFORM.WEB
671
+ },
672
+ eventType: _analytics.EVENT_TYPE.UI
673
+ });
674
+ rafID = requestAnimationFrame(function () {
675
+ (0, _performanceMeasures.stopMeasure)("Renderer Render Time: ".concat(id), function (duration) {
676
+ var _analyticsEventSeveri3, _analyticsEventSeveri4;
677
+ var forceSeverityTracking = typeof analyticsEventSeverityTracking === 'undefined' && (0, _utils.shouldForceTracking)();
678
+ var severity = !!forceSeverityTracking || analyticsEventSeverityTracking !== null && analyticsEventSeverityTracking !== void 0 && analyticsEventSeverityTracking.enabled ? (0, _utils.getAnalyticsEventSeverity)(duration, (_analyticsEventSeveri3 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityNormalThreshold) !== null && _analyticsEventSeveri3 !== void 0 ? _analyticsEventSeveri3 : NORMAL_SEVERITY_THRESHOLD, (_analyticsEventSeveri4 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityDegradedThreshold) !== null && _analyticsEventSeveri4 !== void 0 ? _analyticsEventSeveri4 : DEGRADED_SEVERITY_THRESHOLD) : undefined;
679
+ var isTTRTrackingExplicitlyDisabled = (analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.enabled) === false;
680
+ if (!isTTRTrackingExplicitlyDisabled) {
681
+ _fireAnalyticsEvent({
682
+ action: _analytics.ACTION.RENDERED,
683
+ actionSubject: _analytics.ACTION_SUBJECT.RENDERER,
684
+ attributes: {
685
+ platform: _events.PLATFORM.WEB,
686
+ duration: duration,
687
+ distortedDuration: renderedMeasurementDistortedDurationMonitor.distortedDuration,
688
+ ttfb: (0, _navigation.getResponseEndTime)(),
689
+ nodes: (0, _countNodes.countNodes)(props.document),
690
+ severity: severity
691
+ },
692
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL
693
+ });
694
+ }
695
+ renderedMeasurementDistortedDurationMonitor.cleanup();
696
+ });
697
+ anchorLinkAnalytics();
698
+ });
699
+ };
700
+ handleAnalytics();
701
+ return function () {
702
+ if (rafID) {
703
+ window.cancelAnimationFrame(rafID);
704
+ }
705
+ if (dataProviders) {
706
+ providerFactory.destroy();
707
+ }
708
+ };
709
+ // we are going to ignore this because I'm doing this on purpose
710
+ // having a dependency array means we run stopMeasure twice per render
711
+ // eslint-disable-next-line react-hooks/exhaustive-deps
712
+ }, []);
713
+ try {
714
+ var _createRendererContex2, _props$media;
715
+ var schema = getSchema(props.schema, props.adfStage);
716
+ var _renderDocument2 = (0, _.renderDocument)(props.document, serializer, schema, props.adfStage, props.useSpecBasedValidator, id, _fireAnalyticsEvent, props.unsupportedContentLevelsTracking, props.appearance, props.includeNodesCountInStats),
717
+ result = _renderDocument2.result,
718
+ stat = _renderDocument2.stat,
719
+ pmDoc = _renderDocument2.pmDoc;
720
+ if (props.onComplete) {
721
+ props.onComplete(stat);
722
+ }
723
+ var rendererOutput = (0, _react2.jsx)(_rendererContext.RendererContextProvider, {
724
+ value: createRendererContext(props.featureFlags, props.isTopLevelRenderer)
725
+ }, (0, _react2.jsx)(_activeHeaderIdProvider.ActiveHeaderIdProvider, {
726
+ value: (0, _links.getActiveHeadingId)(props.allowHeadingAnchorLinks)
727
+ }, (0, _react2.jsx)(_analyticsContext.default.Provider, {
728
+ value: {
729
+ fireAnalyticsEvent: function fireAnalyticsEvent(event) {
730
+ return _fireAnalyticsEvent(event);
731
+ }
732
+ }
733
+ }, (0, _react2.jsx)(_SmartCardStorage.Provider, null, (0, _react2.jsx)(_providerFactory.ProviderFactoryProvider, {
734
+ value: providerFactory
735
+ }, (0, _react2.jsx)(RendererWrapper, {
736
+ allowAnnotations: props.allowAnnotations,
737
+ appearance: props.appearance,
738
+ allowNestedHeaderLinks: (0, _links.isNestedHeaderLinksEnabled)(props.allowHeadingAnchorLinks),
739
+ allowColumnSorting: props.allowColumnSorting,
740
+ allowCopyToClipboard: props.allowCopyToClipboard,
741
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
742
+ allowCustomPanels: props.allowCustomPanels,
743
+ allowPlaceholderText: props.allowPlaceholderText,
744
+ useBlockRenderForCodeBlock: (_createRendererContex2 = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex2 !== void 0 ? _createRendererContex2 : true,
745
+ addTelepointer: props.addTelepointer,
746
+ innerRef: editorRef,
747
+ onClick: function onClick(event) {
748
+ return handleWrapperOnClick(event, props, mouseDownSelection);
749
+ },
750
+ onMouseDown: onMouseDownEditView,
751
+ ssr: (_props$media = props.media) === null || _props$media === void 0 ? void 0 : _props$media.ssr,
752
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
753
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
754
+ }, props.enableSsrInlineScripts ? (0, _react2.jsx)(_breakoutSsr.BreakoutSSRInlineScript, null) : null, (0, _react2.jsx)(RendererActionsInternalUpdater, {
755
+ doc: pmDoc,
756
+ schema: schema,
757
+ onAnalyticsEvent: _fireAnalyticsEvent
758
+ }, result)))))));
759
+ var rendererResult = props.truncated ? (0, _react2.jsx)(_truncatedWrapper.TruncatedWrapper, {
760
+ height: props.maxHeight,
761
+ fadeHeight: props.fadeOutHeight
762
+ }, rendererOutput) : rendererOutput;
763
+ return (0, _react2.jsx)(_react.Fragment, null, rendererResult);
764
+ } catch (e) {
765
+ var _createRendererContex3;
766
+ if (props.onError) {
767
+ props.onError(e);
768
+ }
769
+ return (0, _react2.jsx)(RendererWrapper, {
770
+ allowAnnotations: props.allowAnnotations,
771
+ appearance: props.appearance,
772
+ allowCopyToClipboard: props.allowCopyToClipboard,
773
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
774
+ allowPlaceholderText: props.allowPlaceholderText,
775
+ allowColumnSorting: props.allowColumnSorting,
776
+ allowNestedHeaderLinks: (0, _links.isNestedHeaderLinksEnabled)(props.allowHeadingAnchorLinks),
777
+ useBlockRenderForCodeBlock: (_createRendererContex3 = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex3 !== void 0 ? _createRendererContex3 : true,
778
+ addTelepointer: props.addTelepointer,
779
+ onClick: function onClick(event) {
780
+ return handleWrapperOnClick(event, props, mouseDownSelection);
781
+ },
782
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
783
+ }, (0, _react2.jsx)(_ui.UnsupportedBlock, null));
784
+ }
785
+ };
448
786
  function Renderer(props) {
449
787
  var _React$useContext = _react.default.useContext(_annotations.AnnotationsPositionContext),
450
788
  startPos = _React$useContext.startPos;
451
789
  var _useRendererContext = (0, _rendererContext.useRendererContext)(),
452
790
  isTopLevelRenderer = _useRendererContext.isTopLevelRenderer;
453
- return (
454
- // eslint-disable-next-line react/jsx-pascal-case
455
- (0, _react2.jsx)(__RendererClassComponent, (0, _extends2.default)({}, props, {
456
- startPos: startPos,
457
- isTopLevelRenderer: isTopLevelRenderer
458
- }))
459
- );
791
+ return (0, _platformFeatureFlags.fg)('platform_editor_react18_renderer') ? (0, _react2.jsx)(RendererFunctionalComponent, (0, _extends2.default)({}, props, {
792
+ startPos: startPos,
793
+ isTopLevelRenderer: isTopLevelRenderer
794
+ })) :
795
+ // eslint-disable-next-line react/jsx-pascal-case
796
+ (0, _react2.jsx)(__RendererClassComponent, (0, _extends2.default)({}, props, {
797
+ startPos: startPos,
798
+ isTopLevelRenderer: isTopLevelRenderer
799
+ }));
460
800
  }
461
801
 
462
802
  // Usage notes:
@@ -506,7 +846,7 @@ var RendererWrapper = /*#__PURE__*/_react.default.memo(function (props) {
506
846
  return telepointer;
507
847
  };
508
848
  var initialUpdate = _react.default.useRef(true);
509
- _react.default.useEffect(function () {
849
+ (0, _react.useEffect)(function () {
510
850
  // We must check if window is defined, if it isn't we are in a SSR environment
511
851
  // and we don't want to add the telepointer
512
852
  if (typeof window !== 'undefined' && addTelepointer && innerRef !== null && innerRef !== void 0 && innerRef.current) {
@@ -660,5 +1000,6 @@ var RendererWithAnnotationSelection = function RendererWithAnnotationSelection(p
660
1000
  }))));
661
1001
  };
662
1002
 
1003
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
663
1004
  /* @deprecated using this version of the renderer causes the RendererActions to inaccessible from any consumers */
664
1005
  var _default = exports.default = RendererWithAnnotationSelection;
@@ -188,6 +188,7 @@ export default class RendererActions {
188
188
  }
189
189
  }
190
190
 
191
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
191
192
  /**
192
193
  * This is replaced by `isRangeAnnotatable`.
193
194
  *
@@ -4,7 +4,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  * @jsxRuntime classic
5
5
  * @jsx jsx
6
6
  */
7
- import React, { Fragment, useContext, useLayoutEffect, useRef, PureComponent } from 'react';
7
+ import React, { Fragment, useContext, useLayoutEffect, useRef, PureComponent, useCallback, useMemo, useEffect } from 'react';
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
9
9
  import { css, jsx } from '@emotion/react';
10
10
  import { getSchemaBasedOnStage } from '@atlaskit/adf-schema/schema-default';
@@ -45,7 +45,7 @@ import { countNodes } from './count-nodes';
45
45
  export const NORMAL_SEVERITY_THRESHOLD = 2000;
46
46
  export const DEGRADED_SEVERITY_THRESHOLD = 3000;
47
47
  const packageName = "@atlaskit/renderer";
48
- const packageVersion = "112.6.12";
48
+ const packageVersion = "112.6.13";
49
49
  const setAsQueryContainerStyles = css({
50
50
  containerName: 'ak-renderer-wrapper',
51
51
  containerType: 'inline-size',
@@ -56,6 +56,7 @@ export const defaultNodeComponents = nodeToReact;
56
56
  /**
57
57
  * Exported due to enzyme test reliance on this component.
58
58
  */
59
+ // eslint-disable-next-line @repo/internal/react/no-class-components
59
60
  export class __RendererClassComponent extends PureComponent {
60
61
  constructor(props) {
61
62
  super(props);
@@ -418,6 +419,341 @@ export class __RendererClassComponent extends PureComponent {
418
419
  }
419
420
  }
420
421
  }
422
+ const handleMouseTripleClickInTables = event => {
423
+ var _parentElement3, _parentElement4;
424
+ if (browser.ios || browser.android) {
425
+ return;
426
+ }
427
+ const badBrowser = browser.chrome || browser.safari;
428
+ const tripleClick = event.detail >= 3;
429
+ if (!(badBrowser && tripleClick)) {
430
+ return;
431
+ }
432
+ const selection = window.getSelection();
433
+ if (!selection) {
434
+ return;
435
+ }
436
+ const {
437
+ type,
438
+ anchorNode,
439
+ focusNode
440
+ } = selection;
441
+ const rangeSelection = Boolean(type === 'Range' && anchorNode && focusNode);
442
+ if (!rangeSelection) {
443
+ return;
444
+ }
445
+ const target = event.target;
446
+ const tableCell = target.closest('td,th');
447
+ const clickedInCell = Boolean(tableCell);
448
+ if (!clickedInCell) {
449
+ return;
450
+ }
451
+ const anchorInCell = tableCell.contains(anchorNode);
452
+ const focusInCell = tableCell.contains(focusNode);
453
+ const selectionStartsOrEndsOutsideClickedCell = !(anchorInCell && focusInCell);
454
+ if (!selectionStartsOrEndsOutsideClickedCell) {
455
+ return;
456
+ }
457
+
458
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
459
+ // This logic originated in jira-frontend:
460
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
461
+
462
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
463
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
464
+ // return an empty selection, which will erroneously fire onUnhandledClick.
465
+
466
+ const elementToSelect = anchorInCell ? (_parentElement3 = anchorNode.parentElement) === null || _parentElement3 === void 0 ? void 0 : _parentElement3.closest('div,p') : focusInCell ? (_parentElement4 = focusNode.parentElement) === null || _parentElement4 === void 0 ? void 0 : _parentElement4.closest('div,p') : tableCell;
467
+ if (elementToSelect) {
468
+ selection.selectAllChildren(elementToSelect);
469
+ }
470
+ };
471
+
472
+ /**
473
+ * Handle clicks inside renderer. If the click isn't on media, in the media picker, or on a
474
+ * link, call the onUnhandledClick eventHandler (which in Jira for example, may switch the
475
+ * renderer out for the editor).
476
+ * @param event Click event anywhere inside renderer
477
+ */
478
+ const handleWrapperOnClick = (event, props, mouseDownSelection) => {
479
+ var _props$eventHandlers;
480
+ const targetElement = event.target;
481
+ handleMouseTripleClickInTables(event);
482
+
483
+ // ED-14862: When a user triple clicks to select a line of content inside a
484
+ // a table cell, but the browser incorrectly moves the selection start or end into
485
+ // a different table cell, we manually set the selection back to within the original
486
+ // table cell the user intended to target
487
+ if (!((_props$eventHandlers = props.eventHandlers) !== null && _props$eventHandlers !== void 0 && _props$eventHandlers.onUnhandledClick)) {
488
+ return;
489
+ }
490
+ if (!(targetElement instanceof window.Element)) {
491
+ return;
492
+ }
493
+ const rendererWrapper = event.currentTarget;
494
+ const isInteractiveElementInTree = findInTree(targetElement, rendererWrapper, isInteractiveElement);
495
+ if (isInteractiveElementInTree) {
496
+ return;
497
+ }
498
+
499
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
500
+ // This logic originated in jira-frontend:
501
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
502
+
503
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
504
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
505
+ // return an empty selection, which will erroneously fire onUnhandledClick.
506
+ const windowSelection = window.getSelection();
507
+ const selection = windowSelection !== null ? windowSelection.toString() : undefined;
508
+ const hasSelection = selection && selection.length !== 0;
509
+ const hasSelectionMouseDown = mouseDownSelection.current && mouseDownSelection.current.length !== 0;
510
+ const allowEditBasedOnSelection = !hasSelection && !hasSelectionMouseDown;
511
+ if (allowEditBasedOnSelection) {
512
+ props.eventHandlers.onUnhandledClick(event);
513
+ }
514
+ };
515
+ const RendererFunctionalComponent = props => {
516
+ let mouseDownSelection = useRef(undefined);
517
+ const providerFactory = useMemo(() => props.dataProviders || new ProviderFactory(), [props.dataProviders]);
518
+ const createRendererContext = useMemo(() => (featureFlags, isTopLevelRenderer) => {
519
+ const normalizedFeatureFlags = normalizeFeatureFlags(featureFlags);
520
+ return {
521
+ featureFlags: normalizedFeatureFlags,
522
+ isTopLevelRenderer: isTopLevelRenderer === undefined
523
+ };
524
+ }, []);
525
+ const fireAnalyticsEvent = useCallback(event => {
526
+ const {
527
+ createAnalyticsEvent
528
+ } = props;
529
+ if (createAnalyticsEvent) {
530
+ const channel = FabricChannel.editor;
531
+ createAnalyticsEvent(event).fire(channel);
532
+ }
533
+ }, [props]);
534
+ const deriveSerializerProps = useCallback(props => {
535
+ const stickyHeaders = props.stickyHeaders ? props.stickyHeaders === true ? {} : props.stickyHeaders : undefined;
536
+ const {
537
+ annotationProvider
538
+ } = props;
539
+ const allowAnnotationsDraftMode = Boolean(annotationProvider && annotationProvider.inlineComment && annotationProvider.inlineComment.allowDraftMode);
540
+ const {
541
+ featureFlags
542
+ } = createRendererContext(props.featureFlags, props.isTopLevelRenderer);
543
+ return {
544
+ startPos: props.startPos,
545
+ providers: providerFactory,
546
+ eventHandlers: props.eventHandlers,
547
+ extensionHandlers: props.extensionHandlers,
548
+ portal: props.portal,
549
+ objectContext: {
550
+ adDoc: props.document,
551
+ schema: props.schema,
552
+ ...props.rendererContext
553
+ },
554
+ appearance: props.appearance,
555
+ disableHeadingIDs: props.disableHeadingIDs,
556
+ disableActions: props.disableActions,
557
+ allowHeadingAnchorLinks: props.allowHeadingAnchorLinks,
558
+ allowColumnSorting: props.allowColumnSorting,
559
+ fireAnalyticsEvent: fireAnalyticsEvent,
560
+ shouldOpenMediaViewer: props.shouldOpenMediaViewer,
561
+ allowAltTextOnImages: props.allowAltTextOnImages,
562
+ stickyHeaders,
563
+ allowMediaLinking: props.media && props.media.allowLinking,
564
+ surroundTextNodesWithTextWrapper: allowAnnotationsDraftMode,
565
+ media: props.media,
566
+ emojiResourceConfig: props.emojiResourceConfig,
567
+ smartLinks: props.smartLinks,
568
+ allowCopyToClipboard: props.allowCopyToClipboard,
569
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
570
+ allowCustomPanels: props.allowCustomPanels,
571
+ allowAnnotations: props.allowAnnotations,
572
+ allowSelectAllTrap: props.allowSelectAllTrap,
573
+ allowPlaceholderText: props.allowPlaceholderText,
574
+ nodeComponents: props.nodeComponents,
575
+ allowWindowedCodeBlock: featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.allowWindowedCodeBlock,
576
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
577
+ textHighlighter: props.UNSTABLE_textHighlighter,
578
+ allowTableAlignment: props.UNSTABLE_allowTableAlignment,
579
+ allowTableResizing: props.UNSTABLE_allowTableResizing
580
+ };
581
+ }, [createRendererContext, providerFactory, fireAnalyticsEvent]);
582
+ const serializer = useMemo(() => {
583
+ var _props$startPos;
584
+ return new ReactSerializer(deriveSerializerProps({
585
+ ...props,
586
+ startPos: (_props$startPos = props.startPos) !== null && _props$startPos !== void 0 ? _props$startPos : 0
587
+ }));
588
+ }, [deriveSerializerProps, props]);
589
+ const localRef = useRef(null);
590
+ const editorRef = props.innerRef || localRef;
591
+ const id = useMemo(() => uuid(), []);
592
+ const renderedMeasurementDistortedDurationMonitor = useMemo(() => getDistortedDurationMonitor(), []);
593
+
594
+ // we are doing this to ensure it runs as
595
+ // early as possible in the React lifecycle
596
+ // to avoid any other side effects
597
+ const measureStarted = useRef(false);
598
+ const startAnalyticsMeasure = () => {
599
+ startMeasure(`Renderer Render Time: ${id}`);
600
+ };
601
+ if (!measureStarted.current) {
602
+ startAnalyticsMeasure();
603
+ measureStarted.current = true;
604
+ }
605
+ const anchorLinkAnalytics = useCallback(() => {
606
+ const hash = window.location.hash && decodeURIComponent(window.location.hash.slice(1));
607
+ const disableHeadingIDs = props.disableHeadingIDs;
608
+ if (!disableHeadingIDs && hash && editorRef && editorRef.current instanceof HTMLElement) {
609
+ const anchorLinkElement = document.getElementById(hash);
610
+ if (anchorLinkElement && editorRef.current.contains(anchorLinkElement)) {
611
+ fireAnalyticsEvent({
612
+ action: ACTION.VIEWED,
613
+ actionSubject: ACTION_SUBJECT.ANCHOR_LINK,
614
+ attributes: {
615
+ platform: PLATFORM.WEB,
616
+ mode: MODE.RENDERER
617
+ },
618
+ eventType: EVENT_TYPE.UI
619
+ });
620
+ }
621
+ }
622
+ }, [props.disableHeadingIDs, editorRef, fireAnalyticsEvent]);
623
+ const getSchema = useMemo(() => {
624
+ return (schema, adfStage) => {
625
+ if (schema) {
626
+ return schema;
627
+ }
628
+ return getSchemaBasedOnStage(adfStage);
629
+ };
630
+ }, []);
631
+ const onMouseDownEditView = () => {
632
+ const windowSelection = window.getSelection();
633
+ mouseDownSelection.current = windowSelection !== null ? windowSelection.toString() : undefined;
634
+ };
635
+ const {
636
+ dataProviders,
637
+ analyticsEventSeverityTracking
638
+ } = props;
639
+ useEffect(() => {
640
+ let rafID;
641
+ const handleAnalytics = () => {
642
+ fireAnalyticsEvent({
643
+ action: ACTION.STARTED,
644
+ actionSubject: ACTION_SUBJECT.RENDERER,
645
+ attributes: {
646
+ platform: PLATFORM.WEB
647
+ },
648
+ eventType: EVENT_TYPE.UI
649
+ });
650
+ rafID = requestAnimationFrame(() => {
651
+ stopMeasure(`Renderer Render Time: ${id}`, duration => {
652
+ var _analyticsEventSeveri3, _analyticsEventSeveri4;
653
+ const forceSeverityTracking = typeof analyticsEventSeverityTracking === 'undefined' && shouldForceTracking();
654
+ const severity = !!forceSeverityTracking || analyticsEventSeverityTracking !== null && analyticsEventSeverityTracking !== void 0 && analyticsEventSeverityTracking.enabled ? getAnalyticsEventSeverity(duration, (_analyticsEventSeveri3 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityNormalThreshold) !== null && _analyticsEventSeveri3 !== void 0 ? _analyticsEventSeveri3 : NORMAL_SEVERITY_THRESHOLD, (_analyticsEventSeveri4 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityDegradedThreshold) !== null && _analyticsEventSeveri4 !== void 0 ? _analyticsEventSeveri4 : DEGRADED_SEVERITY_THRESHOLD) : undefined;
655
+ const isTTRTrackingExplicitlyDisabled = (analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.enabled) === false;
656
+ if (!isTTRTrackingExplicitlyDisabled) {
657
+ fireAnalyticsEvent({
658
+ action: ACTION.RENDERED,
659
+ actionSubject: ACTION_SUBJECT.RENDERER,
660
+ attributes: {
661
+ platform: PLATFORM.WEB,
662
+ duration,
663
+ distortedDuration: renderedMeasurementDistortedDurationMonitor.distortedDuration,
664
+ ttfb: getResponseEndTime(),
665
+ nodes: countNodes(props.document),
666
+ severity
667
+ },
668
+ eventType: EVENT_TYPE.OPERATIONAL
669
+ });
670
+ }
671
+ renderedMeasurementDistortedDurationMonitor.cleanup();
672
+ });
673
+ anchorLinkAnalytics();
674
+ });
675
+ };
676
+ handleAnalytics();
677
+ return () => {
678
+ if (rafID) {
679
+ window.cancelAnimationFrame(rafID);
680
+ }
681
+ if (dataProviders) {
682
+ providerFactory.destroy();
683
+ }
684
+ };
685
+ // we are going to ignore this because I'm doing this on purpose
686
+ // having a dependency array means we run stopMeasure twice per render
687
+ // eslint-disable-next-line react-hooks/exhaustive-deps
688
+ }, []);
689
+ try {
690
+ var _createRendererContex, _props$media;
691
+ const schema = getSchema(props.schema, props.adfStage);
692
+ const {
693
+ result,
694
+ stat,
695
+ pmDoc
696
+ } = renderDocument(props.document, serializer, schema, props.adfStage, props.useSpecBasedValidator, id, fireAnalyticsEvent, props.unsupportedContentLevelsTracking, props.appearance, props.includeNodesCountInStats);
697
+ if (props.onComplete) {
698
+ props.onComplete(stat);
699
+ }
700
+ const rendererOutput = jsx(RendererContextProvider, {
701
+ value: createRendererContext(props.featureFlags, props.isTopLevelRenderer)
702
+ }, jsx(ActiveHeaderIdProvider, {
703
+ value: getActiveHeadingId(props.allowHeadingAnchorLinks)
704
+ }, jsx(AnalyticsContext.Provider, {
705
+ value: {
706
+ fireAnalyticsEvent: event => fireAnalyticsEvent(event)
707
+ }
708
+ }, jsx(SmartCardStorageProvider, null, jsx(ProviderFactoryProvider, {
709
+ value: providerFactory
710
+ }, jsx(RendererWrapper, {
711
+ allowAnnotations: props.allowAnnotations,
712
+ appearance: props.appearance,
713
+ allowNestedHeaderLinks: isNestedHeaderLinksEnabled(props.allowHeadingAnchorLinks),
714
+ allowColumnSorting: props.allowColumnSorting,
715
+ allowCopyToClipboard: props.allowCopyToClipboard,
716
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
717
+ allowCustomPanels: props.allowCustomPanels,
718
+ allowPlaceholderText: props.allowPlaceholderText,
719
+ useBlockRenderForCodeBlock: (_createRendererContex = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex !== void 0 ? _createRendererContex : true,
720
+ addTelepointer: props.addTelepointer,
721
+ innerRef: editorRef,
722
+ onClick: event => handleWrapperOnClick(event, props, mouseDownSelection),
723
+ onMouseDown: onMouseDownEditView,
724
+ ssr: (_props$media = props.media) === null || _props$media === void 0 ? void 0 : _props$media.ssr,
725
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
726
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
727
+ }, props.enableSsrInlineScripts ? jsx(BreakoutSSRInlineScript, null) : null, jsx(RendererActionsInternalUpdater, {
728
+ doc: pmDoc,
729
+ schema: schema,
730
+ onAnalyticsEvent: fireAnalyticsEvent
731
+ }, result)))))));
732
+ let rendererResult = props.truncated ? jsx(TruncatedWrapper, {
733
+ height: props.maxHeight,
734
+ fadeHeight: props.fadeOutHeight
735
+ }, rendererOutput) : rendererOutput;
736
+ return jsx(Fragment, null, rendererResult);
737
+ } catch (e) {
738
+ var _createRendererContex2;
739
+ if (props.onError) {
740
+ props.onError(e);
741
+ }
742
+ return jsx(RendererWrapper, {
743
+ allowAnnotations: props.allowAnnotations,
744
+ appearance: props.appearance,
745
+ allowCopyToClipboard: props.allowCopyToClipboard,
746
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
747
+ allowPlaceholderText: props.allowPlaceholderText,
748
+ allowColumnSorting: props.allowColumnSorting,
749
+ allowNestedHeaderLinks: isNestedHeaderLinksEnabled(props.allowHeadingAnchorLinks),
750
+ useBlockRenderForCodeBlock: (_createRendererContex2 = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex2 !== void 0 ? _createRendererContex2 : true,
751
+ addTelepointer: props.addTelepointer,
752
+ onClick: event => handleWrapperOnClick(event, props, mouseDownSelection),
753
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
754
+ }, jsx(UnsupportedBlock, null));
755
+ }
756
+ };
421
757
  export function Renderer(props) {
422
758
  const {
423
759
  startPos
@@ -425,13 +761,15 @@ export function Renderer(props) {
425
761
  const {
426
762
  isTopLevelRenderer
427
763
  } = useRendererContext();
428
- return (
429
- // eslint-disable-next-line react/jsx-pascal-case
430
- jsx(__RendererClassComponent, _extends({}, props, {
431
- startPos: startPos,
432
- isTopLevelRenderer: isTopLevelRenderer
433
- }))
434
- );
764
+ return fg('platform_editor_react18_renderer') ? jsx(RendererFunctionalComponent, _extends({}, props, {
765
+ startPos: startPos,
766
+ isTopLevelRenderer: isTopLevelRenderer
767
+ })) :
768
+ // eslint-disable-next-line react/jsx-pascal-case
769
+ jsx(__RendererClassComponent, _extends({}, props, {
770
+ startPos: startPos,
771
+ isTopLevelRenderer: isTopLevelRenderer
772
+ }));
435
773
  }
436
774
 
437
775
  // Usage notes:
@@ -481,7 +819,7 @@ const RendererWrapper = /*#__PURE__*/React.memo(props => {
481
819
  return telepointer;
482
820
  };
483
821
  const initialUpdate = React.useRef(true);
484
- React.useEffect(() => {
822
+ useEffect(() => {
485
823
  // We must check if window is defined, if it isn't we are in a SSR environment
486
824
  // and we don't want to add the telepointer
487
825
  if (typeof window !== 'undefined' && addTelepointer && innerRef !== null && innerRef !== void 0 && innerRef.current) {
@@ -634,5 +972,6 @@ const RendererWithAnnotationSelection = props => {
634
972
  }))));
635
973
  };
636
974
 
975
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
637
976
  /* @deprecated using this version of the renderer causes the RendererActions to inaccessible from any consumers */
638
977
  export default RendererWithAnnotationSelection;
@@ -203,6 +203,7 @@ var RendererActions = /*#__PURE__*/function () {
203
203
  }
204
204
  }
205
205
 
206
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
206
207
  /**
207
208
  * This is replaced by `isRangeAnnotatable`.
208
209
  *
@@ -14,7 +14,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
14
14
  * @jsxRuntime classic
15
15
  * @jsx jsx
16
16
  */
17
- import React, { Fragment, useContext, useLayoutEffect, useRef, PureComponent } from 'react';
17
+ import React, { Fragment, useContext, useLayoutEffect, useRef, PureComponent, useCallback, useMemo, useEffect } from 'react';
18
18
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
19
19
  import { css, jsx } from '@emotion/react';
20
20
  import { getSchemaBasedOnStage } from '@atlaskit/adf-schema/schema-default';
@@ -55,7 +55,7 @@ import { countNodes } from './count-nodes';
55
55
  export var NORMAL_SEVERITY_THRESHOLD = 2000;
56
56
  export var DEGRADED_SEVERITY_THRESHOLD = 3000;
57
57
  var packageName = "@atlaskit/renderer";
58
- var packageVersion = "112.6.12";
58
+ var packageVersion = "112.6.13";
59
59
  var setAsQueryContainerStyles = css({
60
60
  containerName: 'ak-renderer-wrapper',
61
61
  containerType: 'inline-size',
@@ -66,6 +66,7 @@ export var defaultNodeComponents = nodeToReact;
66
66
  /**
67
67
  * Exported due to enzyme test reliance on this component.
68
68
  */
69
+ // eslint-disable-next-line @repo/internal/react/no-class-components
69
70
  export var __RendererClassComponent = /*#__PURE__*/function (_PureComponent) {
70
71
  _inherits(__RendererClassComponent, _PureComponent);
71
72
  var _super = _createSuper(__RendererClassComponent);
@@ -435,18 +436,357 @@ export var __RendererClassComponent = /*#__PURE__*/function (_PureComponent) {
435
436
  }]);
436
437
  return __RendererClassComponent;
437
438
  }(PureComponent);
439
+ var handleMouseTripleClickInTables = function handleMouseTripleClickInTables(event) {
440
+ var _parentElement3, _parentElement4;
441
+ if (browser.ios || browser.android) {
442
+ return;
443
+ }
444
+ var badBrowser = browser.chrome || browser.safari;
445
+ var tripleClick = event.detail >= 3;
446
+ if (!(badBrowser && tripleClick)) {
447
+ return;
448
+ }
449
+ var selection = window.getSelection();
450
+ if (!selection) {
451
+ return;
452
+ }
453
+ var type = selection.type,
454
+ anchorNode = selection.anchorNode,
455
+ focusNode = selection.focusNode;
456
+ var rangeSelection = Boolean(type === 'Range' && anchorNode && focusNode);
457
+ if (!rangeSelection) {
458
+ return;
459
+ }
460
+ var target = event.target;
461
+ var tableCell = target.closest('td,th');
462
+ var clickedInCell = Boolean(tableCell);
463
+ if (!clickedInCell) {
464
+ return;
465
+ }
466
+ var anchorInCell = tableCell.contains(anchorNode);
467
+ var focusInCell = tableCell.contains(focusNode);
468
+ var selectionStartsOrEndsOutsideClickedCell = !(anchorInCell && focusInCell);
469
+ if (!selectionStartsOrEndsOutsideClickedCell) {
470
+ return;
471
+ }
472
+
473
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
474
+ // This logic originated in jira-frontend:
475
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
476
+
477
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
478
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
479
+ // return an empty selection, which will erroneously fire onUnhandledClick.
480
+
481
+ var elementToSelect = anchorInCell ? (_parentElement3 = anchorNode.parentElement) === null || _parentElement3 === void 0 ? void 0 : _parentElement3.closest('div,p') : focusInCell ? (_parentElement4 = focusNode.parentElement) === null || _parentElement4 === void 0 ? void 0 : _parentElement4.closest('div,p') : tableCell;
482
+ if (elementToSelect) {
483
+ selection.selectAllChildren(elementToSelect);
484
+ }
485
+ };
486
+
487
+ /**
488
+ * Handle clicks inside renderer. If the click isn't on media, in the media picker, or on a
489
+ * link, call the onUnhandledClick eventHandler (which in Jira for example, may switch the
490
+ * renderer out for the editor).
491
+ * @param event Click event anywhere inside renderer
492
+ */
493
+ var handleWrapperOnClick = function handleWrapperOnClick(event, props, mouseDownSelection) {
494
+ var _props$eventHandlers;
495
+ var targetElement = event.target;
496
+ handleMouseTripleClickInTables(event);
497
+
498
+ // ED-14862: When a user triple clicks to select a line of content inside a
499
+ // a table cell, but the browser incorrectly moves the selection start or end into
500
+ // a different table cell, we manually set the selection back to within the original
501
+ // table cell the user intended to target
502
+ if (!((_props$eventHandlers = props.eventHandlers) !== null && _props$eventHandlers !== void 0 && _props$eventHandlers.onUnhandledClick)) {
503
+ return;
504
+ }
505
+ if (!(targetElement instanceof window.Element)) {
506
+ return;
507
+ }
508
+ var rendererWrapper = event.currentTarget;
509
+ var isInteractiveElementInTree = findInTree(targetElement, rendererWrapper, isInteractiveElement);
510
+ if (isInteractiveElementInTree) {
511
+ return;
512
+ }
513
+
514
+ // Ensure that selecting text in the renderer doesn't trigger onUnhandledClick
515
+ // This logic originated in jira-frontend:
516
+ // src/packages/issue/issue-view/src/views/field/rich-text/rich-text-inline-edit-view.js
517
+
518
+ // The selection is required to be checked in `onMouseDown` and here. If not here, a new
519
+ // selection isn't reported; if not in `onMouseDown`, a click outside the selection will
520
+ // return an empty selection, which will erroneously fire onUnhandledClick.
521
+ var windowSelection = window.getSelection();
522
+ var selection = windowSelection !== null ? windowSelection.toString() : undefined;
523
+ var hasSelection = selection && selection.length !== 0;
524
+ var hasSelectionMouseDown = mouseDownSelection.current && mouseDownSelection.current.length !== 0;
525
+ var allowEditBasedOnSelection = !hasSelection && !hasSelectionMouseDown;
526
+ if (allowEditBasedOnSelection) {
527
+ props.eventHandlers.onUnhandledClick(event);
528
+ }
529
+ };
530
+ var RendererFunctionalComponent = function RendererFunctionalComponent(props) {
531
+ var mouseDownSelection = useRef(undefined);
532
+ var providerFactory = useMemo(function () {
533
+ return props.dataProviders || new ProviderFactory();
534
+ }, [props.dataProviders]);
535
+ var createRendererContext = useMemo(function () {
536
+ return function (featureFlags, isTopLevelRenderer) {
537
+ var normalizedFeatureFlags = normalizeFeatureFlags(featureFlags);
538
+ return {
539
+ featureFlags: normalizedFeatureFlags,
540
+ isTopLevelRenderer: isTopLevelRenderer === undefined
541
+ };
542
+ };
543
+ }, []);
544
+ var _fireAnalyticsEvent = useCallback(function (event) {
545
+ var createAnalyticsEvent = props.createAnalyticsEvent;
546
+ if (createAnalyticsEvent) {
547
+ var channel = FabricChannel.editor;
548
+ createAnalyticsEvent(event).fire(channel);
549
+ }
550
+ }, [props]);
551
+ var deriveSerializerProps = useCallback(function (props) {
552
+ var stickyHeaders = props.stickyHeaders ? props.stickyHeaders === true ? {} : props.stickyHeaders : undefined;
553
+ var annotationProvider = props.annotationProvider;
554
+ var allowAnnotationsDraftMode = Boolean(annotationProvider && annotationProvider.inlineComment && annotationProvider.inlineComment.allowDraftMode);
555
+ var _createRendererContex = createRendererContext(props.featureFlags, props.isTopLevelRenderer),
556
+ featureFlags = _createRendererContex.featureFlags;
557
+ return {
558
+ startPos: props.startPos,
559
+ providers: providerFactory,
560
+ eventHandlers: props.eventHandlers,
561
+ extensionHandlers: props.extensionHandlers,
562
+ portal: props.portal,
563
+ objectContext: _objectSpread({
564
+ adDoc: props.document,
565
+ schema: props.schema
566
+ }, props.rendererContext),
567
+ appearance: props.appearance,
568
+ disableHeadingIDs: props.disableHeadingIDs,
569
+ disableActions: props.disableActions,
570
+ allowHeadingAnchorLinks: props.allowHeadingAnchorLinks,
571
+ allowColumnSorting: props.allowColumnSorting,
572
+ fireAnalyticsEvent: _fireAnalyticsEvent,
573
+ shouldOpenMediaViewer: props.shouldOpenMediaViewer,
574
+ allowAltTextOnImages: props.allowAltTextOnImages,
575
+ stickyHeaders: stickyHeaders,
576
+ allowMediaLinking: props.media && props.media.allowLinking,
577
+ surroundTextNodesWithTextWrapper: allowAnnotationsDraftMode,
578
+ media: props.media,
579
+ emojiResourceConfig: props.emojiResourceConfig,
580
+ smartLinks: props.smartLinks,
581
+ allowCopyToClipboard: props.allowCopyToClipboard,
582
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
583
+ allowCustomPanels: props.allowCustomPanels,
584
+ allowAnnotations: props.allowAnnotations,
585
+ allowSelectAllTrap: props.allowSelectAllTrap,
586
+ allowPlaceholderText: props.allowPlaceholderText,
587
+ nodeComponents: props.nodeComponents,
588
+ allowWindowedCodeBlock: featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.allowWindowedCodeBlock,
589
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
590
+ textHighlighter: props.UNSTABLE_textHighlighter,
591
+ allowTableAlignment: props.UNSTABLE_allowTableAlignment,
592
+ allowTableResizing: props.UNSTABLE_allowTableResizing
593
+ };
594
+ }, [createRendererContext, providerFactory, _fireAnalyticsEvent]);
595
+ var serializer = useMemo(function () {
596
+ var _props$startPos;
597
+ return new ReactSerializer(deriveSerializerProps(_objectSpread(_objectSpread({}, props), {}, {
598
+ startPos: (_props$startPos = props.startPos) !== null && _props$startPos !== void 0 ? _props$startPos : 0
599
+ })));
600
+ }, [deriveSerializerProps, props]);
601
+ var localRef = useRef(null);
602
+ var editorRef = props.innerRef || localRef;
603
+ var id = useMemo(function () {
604
+ return uuid();
605
+ }, []);
606
+ var renderedMeasurementDistortedDurationMonitor = useMemo(function () {
607
+ return getDistortedDurationMonitor();
608
+ }, []);
609
+
610
+ // we are doing this to ensure it runs as
611
+ // early as possible in the React lifecycle
612
+ // to avoid any other side effects
613
+ var measureStarted = useRef(false);
614
+ var startAnalyticsMeasure = function startAnalyticsMeasure() {
615
+ startMeasure("Renderer Render Time: ".concat(id));
616
+ };
617
+ if (!measureStarted.current) {
618
+ startAnalyticsMeasure();
619
+ measureStarted.current = true;
620
+ }
621
+ var anchorLinkAnalytics = useCallback(function () {
622
+ var hash = window.location.hash && decodeURIComponent(window.location.hash.slice(1));
623
+ var disableHeadingIDs = props.disableHeadingIDs;
624
+ if (!disableHeadingIDs && hash && editorRef && editorRef.current instanceof HTMLElement) {
625
+ var anchorLinkElement = document.getElementById(hash);
626
+ if (anchorLinkElement && editorRef.current.contains(anchorLinkElement)) {
627
+ _fireAnalyticsEvent({
628
+ action: ACTION.VIEWED,
629
+ actionSubject: ACTION_SUBJECT.ANCHOR_LINK,
630
+ attributes: {
631
+ platform: PLATFORM.WEB,
632
+ mode: MODE.RENDERER
633
+ },
634
+ eventType: EVENT_TYPE.UI
635
+ });
636
+ }
637
+ }
638
+ }, [props.disableHeadingIDs, editorRef, _fireAnalyticsEvent]);
639
+ var getSchema = useMemo(function () {
640
+ return function (schema, adfStage) {
641
+ if (schema) {
642
+ return schema;
643
+ }
644
+ return getSchemaBasedOnStage(adfStage);
645
+ };
646
+ }, []);
647
+ var onMouseDownEditView = function onMouseDownEditView() {
648
+ var windowSelection = window.getSelection();
649
+ mouseDownSelection.current = windowSelection !== null ? windowSelection.toString() : undefined;
650
+ };
651
+ var dataProviders = props.dataProviders,
652
+ analyticsEventSeverityTracking = props.analyticsEventSeverityTracking;
653
+ useEffect(function () {
654
+ var rafID;
655
+ var handleAnalytics = function handleAnalytics() {
656
+ _fireAnalyticsEvent({
657
+ action: ACTION.STARTED,
658
+ actionSubject: ACTION_SUBJECT.RENDERER,
659
+ attributes: {
660
+ platform: PLATFORM.WEB
661
+ },
662
+ eventType: EVENT_TYPE.UI
663
+ });
664
+ rafID = requestAnimationFrame(function () {
665
+ stopMeasure("Renderer Render Time: ".concat(id), function (duration) {
666
+ var _analyticsEventSeveri3, _analyticsEventSeveri4;
667
+ var forceSeverityTracking = typeof analyticsEventSeverityTracking === 'undefined' && shouldForceTracking();
668
+ var severity = !!forceSeverityTracking || analyticsEventSeverityTracking !== null && analyticsEventSeverityTracking !== void 0 && analyticsEventSeverityTracking.enabled ? getAnalyticsEventSeverity(duration, (_analyticsEventSeveri3 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityNormalThreshold) !== null && _analyticsEventSeveri3 !== void 0 ? _analyticsEventSeveri3 : NORMAL_SEVERITY_THRESHOLD, (_analyticsEventSeveri4 = analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.severityDegradedThreshold) !== null && _analyticsEventSeveri4 !== void 0 ? _analyticsEventSeveri4 : DEGRADED_SEVERITY_THRESHOLD) : undefined;
669
+ var isTTRTrackingExplicitlyDisabled = (analyticsEventSeverityTracking === null || analyticsEventSeverityTracking === void 0 ? void 0 : analyticsEventSeverityTracking.enabled) === false;
670
+ if (!isTTRTrackingExplicitlyDisabled) {
671
+ _fireAnalyticsEvent({
672
+ action: ACTION.RENDERED,
673
+ actionSubject: ACTION_SUBJECT.RENDERER,
674
+ attributes: {
675
+ platform: PLATFORM.WEB,
676
+ duration: duration,
677
+ distortedDuration: renderedMeasurementDistortedDurationMonitor.distortedDuration,
678
+ ttfb: getResponseEndTime(),
679
+ nodes: countNodes(props.document),
680
+ severity: severity
681
+ },
682
+ eventType: EVENT_TYPE.OPERATIONAL
683
+ });
684
+ }
685
+ renderedMeasurementDistortedDurationMonitor.cleanup();
686
+ });
687
+ anchorLinkAnalytics();
688
+ });
689
+ };
690
+ handleAnalytics();
691
+ return function () {
692
+ if (rafID) {
693
+ window.cancelAnimationFrame(rafID);
694
+ }
695
+ if (dataProviders) {
696
+ providerFactory.destroy();
697
+ }
698
+ };
699
+ // we are going to ignore this because I'm doing this on purpose
700
+ // having a dependency array means we run stopMeasure twice per render
701
+ // eslint-disable-next-line react-hooks/exhaustive-deps
702
+ }, []);
703
+ try {
704
+ var _createRendererContex2, _props$media;
705
+ var schema = getSchema(props.schema, props.adfStage);
706
+ var _renderDocument2 = renderDocument(props.document, serializer, schema, props.adfStage, props.useSpecBasedValidator, id, _fireAnalyticsEvent, props.unsupportedContentLevelsTracking, props.appearance, props.includeNodesCountInStats),
707
+ result = _renderDocument2.result,
708
+ stat = _renderDocument2.stat,
709
+ pmDoc = _renderDocument2.pmDoc;
710
+ if (props.onComplete) {
711
+ props.onComplete(stat);
712
+ }
713
+ var rendererOutput = jsx(RendererContextProvider, {
714
+ value: createRendererContext(props.featureFlags, props.isTopLevelRenderer)
715
+ }, jsx(ActiveHeaderIdProvider, {
716
+ value: getActiveHeadingId(props.allowHeadingAnchorLinks)
717
+ }, jsx(AnalyticsContext.Provider, {
718
+ value: {
719
+ fireAnalyticsEvent: function fireAnalyticsEvent(event) {
720
+ return _fireAnalyticsEvent(event);
721
+ }
722
+ }
723
+ }, jsx(SmartCardStorageProvider, null, jsx(ProviderFactoryProvider, {
724
+ value: providerFactory
725
+ }, jsx(RendererWrapper, {
726
+ allowAnnotations: props.allowAnnotations,
727
+ appearance: props.appearance,
728
+ allowNestedHeaderLinks: isNestedHeaderLinksEnabled(props.allowHeadingAnchorLinks),
729
+ allowColumnSorting: props.allowColumnSorting,
730
+ allowCopyToClipboard: props.allowCopyToClipboard,
731
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
732
+ allowCustomPanels: props.allowCustomPanels,
733
+ allowPlaceholderText: props.allowPlaceholderText,
734
+ useBlockRenderForCodeBlock: (_createRendererContex2 = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex2 !== void 0 ? _createRendererContex2 : true,
735
+ addTelepointer: props.addTelepointer,
736
+ innerRef: editorRef,
737
+ onClick: function onClick(event) {
738
+ return handleWrapperOnClick(event, props, mouseDownSelection);
739
+ },
740
+ onMouseDown: onMouseDownEditView,
741
+ ssr: (_props$media = props.media) === null || _props$media === void 0 ? void 0 : _props$media.ssr,
742
+ isInsideOfInlineExtension: props.isInsideOfInlineExtension,
743
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
744
+ }, props.enableSsrInlineScripts ? jsx(BreakoutSSRInlineScript, null) : null, jsx(RendererActionsInternalUpdater, {
745
+ doc: pmDoc,
746
+ schema: schema,
747
+ onAnalyticsEvent: _fireAnalyticsEvent
748
+ }, result)))))));
749
+ var rendererResult = props.truncated ? jsx(TruncatedWrapper, {
750
+ height: props.maxHeight,
751
+ fadeHeight: props.fadeOutHeight
752
+ }, rendererOutput) : rendererOutput;
753
+ return jsx(Fragment, null, rendererResult);
754
+ } catch (e) {
755
+ var _createRendererContex3;
756
+ if (props.onError) {
757
+ props.onError(e);
758
+ }
759
+ return jsx(RendererWrapper, {
760
+ allowAnnotations: props.allowAnnotations,
761
+ appearance: props.appearance,
762
+ allowCopyToClipboard: props.allowCopyToClipboard,
763
+ allowWrapCodeBlock: props.allowWrapCodeBlock,
764
+ allowPlaceholderText: props.allowPlaceholderText,
765
+ allowColumnSorting: props.allowColumnSorting,
766
+ allowNestedHeaderLinks: isNestedHeaderLinksEnabled(props.allowHeadingAnchorLinks),
767
+ useBlockRenderForCodeBlock: (_createRendererContex3 = createRendererContext(props.featureFlags, props.isTopLevelRenderer).featureFlags.useBlockRenderForCodeBlock) !== null && _createRendererContex3 !== void 0 ? _createRendererContex3 : true,
768
+ addTelepointer: props.addTelepointer,
769
+ onClick: function onClick(event) {
770
+ return handleWrapperOnClick(event, props, mouseDownSelection);
771
+ },
772
+ isTopLevelRenderer: createRendererContext(props.featureFlags, props.isTopLevelRenderer).isTopLevelRenderer
773
+ }, jsx(UnsupportedBlock, null));
774
+ }
775
+ };
438
776
  export function Renderer(props) {
439
777
  var _React$useContext = React.useContext(AnnotationsPositionContext),
440
778
  startPos = _React$useContext.startPos;
441
779
  var _useRendererContext = useRendererContext(),
442
780
  isTopLevelRenderer = _useRendererContext.isTopLevelRenderer;
443
- return (
444
- // eslint-disable-next-line react/jsx-pascal-case
445
- jsx(__RendererClassComponent, _extends({}, props, {
446
- startPos: startPos,
447
- isTopLevelRenderer: isTopLevelRenderer
448
- }))
449
- );
781
+ return fg('platform_editor_react18_renderer') ? jsx(RendererFunctionalComponent, _extends({}, props, {
782
+ startPos: startPos,
783
+ isTopLevelRenderer: isTopLevelRenderer
784
+ })) :
785
+ // eslint-disable-next-line react/jsx-pascal-case
786
+ jsx(__RendererClassComponent, _extends({}, props, {
787
+ startPos: startPos,
788
+ isTopLevelRenderer: isTopLevelRenderer
789
+ }));
450
790
  }
451
791
 
452
792
  // Usage notes:
@@ -496,7 +836,7 @@ var RendererWrapper = /*#__PURE__*/React.memo(function (props) {
496
836
  return telepointer;
497
837
  };
498
838
  var initialUpdate = React.useRef(true);
499
- React.useEffect(function () {
839
+ useEffect(function () {
500
840
  // We must check if window is defined, if it isn't we are in a SSR environment
501
841
  // and we don't want to add the telepointer
502
842
  if (typeof window !== 'undefined' && addTelepointer && innerRef !== null && innerRef !== void 0 && innerRef.current) {
@@ -650,5 +990,6 @@ var RendererWithAnnotationSelection = function RendererWithAnnotationSelection(p
650
990
  }))));
651
991
  };
652
992
 
993
+ // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
653
994
  /* @deprecated using this version of the renderer causes the RendererActions to inaccessible from any consumers */
654
995
  export default RendererWithAnnotationSelection;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/renderer",
3
- "version": "112.6.12",
3
+ "version": "112.6.13",
4
4
  "description": "Renderer component",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -29,7 +29,7 @@
29
29
  "@atlaskit/analytics-next": "^10.1.0",
30
30
  "@atlaskit/button": "^20.3.0",
31
31
  "@atlaskit/code": "^15.6.0",
32
- "@atlaskit/editor-common": "^96.0.0",
32
+ "@atlaskit/editor-common": "^96.1.0",
33
33
  "@atlaskit/editor-json-transformer": "^8.21.0",
34
34
  "@atlaskit/editor-palette": "1.6.3",
35
35
  "@atlaskit/editor-prosemirror": "6.2.1",
@@ -77,7 +77,7 @@
77
77
  "@atlaskit/linking-common": "^6.0.0",
78
78
  "@atlaskit/media-core": "^34.3.0",
79
79
  "@atlaskit/media-integration-test-helpers": "^3.1.0",
80
- "@atlaskit/media-test-helpers": "^34.6.0",
80
+ "@atlaskit/media-test-helpers": "^34.7.0",
81
81
  "@atlaskit/mention": "^23.4.0",
82
82
  "@atlaskit/navigation-next": "^9.0.0",
83
83
  "@atlaskit/util-data-test": "^17.13.0",
@@ -155,6 +155,9 @@
155
155
  },
156
156
  "platform_editor_hyperlink_underline": {
157
157
  "type": "boolean"
158
+ },
159
+ "platform_editor_react18_renderer": {
160
+ "type": "boolean"
158
161
  }
159
162
  },
160
163
  "af:exports": {