@atlaskit/editor-plugin-card 0.10.10 → 0.11.1

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 (35) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/common/pulse/index.js +6 -14
  3. package/dist/cjs/messages.js +5 -0
  4. package/dist/cjs/nodeviews/inlineCardWithAwareness.js +20 -2
  5. package/dist/cjs/toolbar.js +5 -9
  6. package/dist/cjs/ui/InlineCardOverlay/index.js +187 -0
  7. package/dist/cjs/ui/InlineCardOverlay/types.js +5 -0
  8. package/dist/cjs/ui/LinkToolbarAppearance.js +19 -3
  9. package/dist/es2019/common/pulse/index.js +8 -14
  10. package/dist/es2019/messages.js +5 -0
  11. package/dist/es2019/nodeviews/inlineCardWithAwareness.js +13 -3
  12. package/dist/es2019/toolbar.js +3 -7
  13. package/dist/es2019/ui/InlineCardOverlay/index.js +175 -0
  14. package/dist/es2019/ui/InlineCardOverlay/types.js +1 -0
  15. package/dist/es2019/ui/LinkToolbarAppearance.js +18 -3
  16. package/dist/esm/common/pulse/index.js +8 -16
  17. package/dist/esm/messages.js +5 -0
  18. package/dist/esm/nodeviews/inlineCardWithAwareness.js +21 -3
  19. package/dist/esm/toolbar.js +4 -8
  20. package/dist/esm/ui/InlineCardOverlay/index.js +179 -0
  21. package/dist/esm/ui/InlineCardOverlay/types.js +1 -0
  22. package/dist/esm/ui/LinkToolbarAppearance.js +19 -3
  23. package/dist/types/common/pulse/index.d.ts +1 -5
  24. package/dist/types/messages.d.ts +5 -0
  25. package/dist/types/toolbar.d.ts +1 -0
  26. package/dist/types/ui/InlineCardOverlay/index.d.ts +5 -0
  27. package/dist/types/ui/InlineCardOverlay/types.d.ts +6 -0
  28. package/dist/types/ui/LinkToolbarAppearance.d.ts +9 -8
  29. package/dist/types-ts4.5/common/pulse/index.d.ts +1 -5
  30. package/dist/types-ts4.5/messages.d.ts +5 -0
  31. package/dist/types-ts4.5/toolbar.d.ts +1 -0
  32. package/dist/types-ts4.5/ui/InlineCardOverlay/index.d.ts +5 -0
  33. package/dist/types-ts4.5/ui/InlineCardOverlay/types.d.ts +6 -0
  34. package/dist/types-ts4.5/ui/LinkToolbarAppearance.d.ts +9 -8
  35. package/package.json +4 -4
@@ -0,0 +1,175 @@
1
+ /** @jsx jsx */
2
+
3
+ import React, { useLayoutEffect, useMemo, useRef, useState } from 'react';
4
+ import { css, jsx } from '@emotion/react';
5
+ import { useIntl } from 'react-intl-next';
6
+ import { browser } from '@atlaskit/editor-common/utils';
7
+ import HipchatChevronDownIcon from '@atlaskit/icon/glyph/hipchat/chevron-down';
8
+ import HipchatChevronUpIcon from '@atlaskit/icon/glyph/hipchat/chevron-up';
9
+ import { N20A, N800 } from '@atlaskit/theme/colors';
10
+ import { messages } from '../../messages';
11
+ const PADDING_IN_PX = 2;
12
+ const containerStyles = css({
13
+ position: 'relative'
14
+ });
15
+ const linkStyles = css({
16
+ color: "var(--ds-text, #172B4D)",
17
+ textDecoration: 'none'
18
+ });
19
+ const overlayStyles = css({
20
+ // Positioning
21
+ position: 'relative',
22
+ display: 'inline-flex',
23
+ flexWrap: 'nowrap',
24
+ alignItems: 'center',
25
+ alignSelf: 'stretch',
26
+ height: 'inherit',
27
+ lineHeight: 'initial',
28
+ width: 'max-content',
29
+ top: "var(--ds-space-0, 0)",
30
+ bottom: "var(--ds-space-0, 0)",
31
+ right: 3,
32
+ margin: `-1px ${"var(--ds-space-0, 0)"}`,
33
+ padding: "var(--ds-space-0, 0)",
34
+ // Styling
35
+ fontSize: 'inherit',
36
+ fontWeight: 'normal',
37
+ color: `var(--ds-text, ${N800})`,
38
+ background: `var(--ds-background-accent-gray-subtlest, ${N20A})`,
39
+ borderRadius: 3,
40
+ // inline card border of 4px - 1px
41
+
42
+ // Using `&` twice to increase specificity. (These are not nested styles.)
43
+ /* eslint-disable @atlaskit/design-system/no-nested-styles */
44
+ '&&:link': {
45
+ ...linkStyles
46
+ },
47
+ '&&:active': {
48
+ ...linkStyles
49
+ },
50
+ '&&:focus': {
51
+ ...linkStyles
52
+ },
53
+ '&&:hover': {
54
+ ...linkStyles
55
+ },
56
+ '&&:visited': {
57
+ ...linkStyles
58
+ },
59
+ /* eslint-enable @atlaskit/design-system/no-nested-styles */
60
+
61
+ // EDM-1717: box-shadow Safari fix bring load wrapper zIndex to 1
62
+ zIndex: 2,
63
+ // Fill lines, match heading and paragraph size
64
+ '::before': {
65
+ content: '" "',
66
+ display: 'inline-block',
67
+ verticalAlign: 'middle',
68
+ width: "var(--ds-space-0, 0)",
69
+ margin: "var(--ds-space-0, 0)",
70
+ padding: "var(--ds-space-0, 0)"
71
+ }
72
+ });
73
+ const safariOverlayStyles = css({
74
+ height: '1.1em',
75
+ paddingBottom: "var(--ds-space-025, 2px)",
76
+ right: 3
77
+ });
78
+ const textStyles = css({
79
+ paddingLeft: "var(--ds-space-050, 4px)"
80
+ });
81
+ const iconStyles = css({
82
+ // Position icon in the middle
83
+ display: 'inline-grid',
84
+ // We want to position the icon in the middle of large text type like heading 1
85
+ // eslint-disable-next-line @atlaskit/design-system/no-nested-styles
86
+ span: {
87
+ display: 'inline-grid'
88
+ }
89
+ });
90
+ const markerStyles = css({
91
+ height: "var(--ds-space-0, 0)",
92
+ width: "var(--ds-space-0, 0)",
93
+ margin: "var(--ds-space-0, 0)",
94
+ padding: "var(--ds-space-0, 0)"
95
+ });
96
+ const InlineCardOverlay = ({
97
+ children,
98
+ isToolbarOpen = false,
99
+ isVisible = false,
100
+ testId = 'inline-card-overlay',
101
+ url
102
+ }) => {
103
+ const [showLabel, setShowLabel] = useState(true);
104
+ const [overlayWidth, setOverlayWidth] = useState(0);
105
+ const containerRef = useRef(null);
106
+ const markerRef = useRef(null);
107
+ const overlayRef = useRef(null);
108
+ const labelRef = useRef(null);
109
+ useLayoutEffect(() => {
110
+ if (!isVisible) {
111
+ // Reset to default state for width calculation when the component become visible.
112
+ setShowLabel(true);
113
+ return;
114
+ }
115
+ try {
116
+ var _containerRef$current, _containerRef$current2, _containerRef$current3, _markerRef$current$ge, _markerRef$current, _markerRef$current$ge2, _overlayRef$current$g, _overlayRef$current, _overlayRef$current$g2, _labelRef$current$get, _labelRef$current, _labelRef$current$get2;
117
+ // Get the width of the available space to display overlay
118
+ const start = (_containerRef$current = containerRef === null || containerRef === void 0 ? void 0 : (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : (_containerRef$current3 = _containerRef$current2.getBoundingClientRect()) === null || _containerRef$current3 === void 0 ? void 0 : _containerRef$current3.left) !== null && _containerRef$current !== void 0 ? _containerRef$current : 0;
119
+ const end = (_markerRef$current$ge = markerRef === null || markerRef === void 0 ? void 0 : (_markerRef$current = markerRef.current) === null || _markerRef$current === void 0 ? void 0 : (_markerRef$current$ge2 = _markerRef$current.getBoundingClientRect()) === null || _markerRef$current$ge2 === void 0 ? void 0 : _markerRef$current$ge2.left) !== null && _markerRef$current$ge !== void 0 ? _markerRef$current$ge : 0;
120
+ const availableWidth = end - start - PADDING_IN_PX;
121
+
122
+ // Get overlay width and label width
123
+ const overlayWidth = (_overlayRef$current$g = overlayRef === null || overlayRef === void 0 ? void 0 : (_overlayRef$current = overlayRef.current) === null || _overlayRef$current === void 0 ? void 0 : (_overlayRef$current$g2 = _overlayRef$current.getBoundingClientRect()) === null || _overlayRef$current$g2 === void 0 ? void 0 : _overlayRef$current$g2.width) !== null && _overlayRef$current$g !== void 0 ? _overlayRef$current$g : 0;
124
+
125
+ // Show label if there is enough space to display
126
+ const shouldShowLabel = availableWidth > 0 && overlayWidth > 0 ? availableWidth > overlayWidth : false;
127
+ setShowLabel(shouldShowLabel);
128
+
129
+ // We use relative positioning and need to set
130
+ // negative margin left (ltr) as the width of the overlay
131
+ // to make the overlay position on top of inline link.
132
+ const labelWidth = (_labelRef$current$get = labelRef === null || labelRef === void 0 ? void 0 : (_labelRef$current = labelRef.current) === null || _labelRef$current === void 0 ? void 0 : (_labelRef$current$get2 = _labelRef$current.getBoundingClientRect()) === null || _labelRef$current$get2 === void 0 ? void 0 : _labelRef$current$get2.width) !== null && _labelRef$current$get !== void 0 ? _labelRef$current$get : 0;
133
+ const newOverlayWidth = shouldShowLabel ? overlayWidth : overlayWidth - labelWidth;
134
+ setOverlayWidth(newOverlayWidth);
135
+ } catch {
136
+ // If something goes wrong, play it safe by hiding label so that
137
+ // the component does not look too janky.
138
+ setShowLabel(false);
139
+ }
140
+ }, [isVisible]);
141
+ const intl = useIntl();
142
+ const label = intl.formatMessage(messages.inlineOverlay);
143
+ const icon = useMemo(() => {
144
+ const IconComponent = isToolbarOpen ? HipchatChevronUpIcon : HipchatChevronDownIcon;
145
+ return jsx(IconComponent, {
146
+ label: label,
147
+ size: "small",
148
+ testId: `${testId}-${isToolbarOpen ? 'open' : 'close'}`
149
+ });
150
+ }, [isToolbarOpen, label, testId]);
151
+ return jsx("span", {
152
+ css: containerStyles,
153
+ ref: containerRef
154
+ }, children, isVisible && jsx(React.Fragment, null, jsx("span", {
155
+ "aria-hidden": "true",
156
+ css: markerStyles,
157
+ ref: markerRef
158
+ }), jsx("a", {
159
+ css: [overlayStyles, browser.safari && safariOverlayStyles],
160
+ style: {
161
+ marginLeft: -overlayWidth
162
+ },
163
+ "data-testid": testId,
164
+ href: url,
165
+ onClick: e => e.preventDefault(),
166
+ ref: overlayRef
167
+ }, showLabel && jsx("span", {
168
+ css: textStyles,
169
+ "data-testid": `${testId}-label`,
170
+ ref: labelRef
171
+ }, label), jsx("span", {
172
+ css: iconStyles
173
+ }, icon))));
174
+ };
175
+ export default InlineCardOverlay;
@@ -0,0 +1 @@
1
+ export {};
@@ -6,12 +6,14 @@ import { commandWithMetadata, getButtonGroupOption, LinkToolbarButtonGroup } fro
6
6
  import nodeNames, { cardMessages as messages } from '@atlaskit/editor-common/messages';
7
7
  import { isSupportedInParent } from '@atlaskit/editor-common/utils';
8
8
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
9
+ import { DiscoveryPulse } from '../common/pulse';
10
+ import { shouldRenderToolbarPulse } from '../toolbar';
9
11
  // eslint-disable-next-line @repo/internal/react/no-class-components
10
12
  export class LinkToolbarAppearance extends React.Component {
11
13
  constructor(...args) {
12
14
  super(...args);
13
15
  _defineProperty(this, "renderDropdown", (view, cardContext) => {
14
- var _cardActions$setSelec, _cardActions$setSelec2, _cardActions$changeSe, _cardActions$setSelec3;
16
+ var _cardActions$setSelec, _cardActions$setSelec2, _cardActions$changeSe, _cardActions$setSelec3, _cardContext$store2, _cardContext$store2$g;
15
17
  const {
16
18
  url,
17
19
  intl,
@@ -21,7 +23,8 @@ export class LinkToolbarAppearance extends React.Component {
21
23
  allowBlockCards = true,
22
24
  platform,
23
25
  editorAnalyticsApi,
24
- cardActions
26
+ cardActions,
27
+ showInlineUpgradeDiscoverability = false
25
28
  } = this.props;
26
29
  const preview = allowEmbeds && cardContext && url && cardContext.extractors.getPreview(url, platform);
27
30
  const defaultCommand = () => false;
@@ -80,7 +83,7 @@ export class LinkToolbarAppearance extends React.Component {
80
83
  if (embedOption) {
81
84
  options.push(embedOption);
82
85
  }
83
- return /*#__PURE__*/React.createElement(LinkToolbarButtonGroup, {
86
+ const LinkToolbarButtons = /*#__PURE__*/React.createElement(LinkToolbarButtonGroup, {
84
87
  key: "link-toolbar-button-group",
85
88
  options: options.map(option => getButtonGroupOption(intl, dispatchCommand, {
86
89
  ...option,
@@ -89,6 +92,18 @@ export class LinkToolbarAppearance extends React.Component {
89
92
  })
90
93
  }))
91
94
  });
95
+ const status = url ? cardContext === null || cardContext === void 0 ? void 0 : (_cardContext$store2 = cardContext.store) === null || _cardContext$store2 === void 0 ? void 0 : (_cardContext$store2$g = _cardContext$store2.getState()[url]) === null || _cardContext$store2$g === void 0 ? void 0 : _cardContext$store2$g.status : '';
96
+ const embedEnabled = embedOption ? !embedOption.disabled : false;
97
+ if (shouldRenderToolbarPulse(embedEnabled, currentAppearance !== null && currentAppearance !== void 0 ? currentAppearance : '', status !== null && status !== void 0 ? status : '', showInlineUpgradeDiscoverability)) {
98
+ return (
99
+ /*#__PURE__*/
100
+ // This div is necessary because the toolbar uses :first-child to add margins and can't add margins to the pulse element
101
+ React.createElement("div", null, /*#__PURE__*/React.createElement(DiscoveryPulse, {
102
+ localStorageKey: "toolbar-upgrade-pulse"
103
+ }, LinkToolbarButtons))
104
+ );
105
+ }
106
+ return LinkToolbarButtons;
92
107
  });
93
108
  }
94
109
  render() {
@@ -1,28 +1,20 @@
1
- import React, { useCallback, useEffect } from 'react';
1
+ import React, { useCallback } from 'react';
2
2
  import { Pulse } from '@atlaskit/linking-common';
3
- import { markLocalStorageKeyDiscovered } from '../local-storage';
3
+ import { isLocalStorageKeyDiscovered, markLocalStorageKeyDiscovered } from '../local-storage';
4
4
  export var DiscoveryPulse = function DiscoveryPulse(_ref) {
5
5
  var children = _ref.children,
6
6
  localStorageKey = _ref.localStorageKey,
7
7
  isDiscovered = _ref.isDiscovered,
8
- timeToDiscoverInMs = _ref.timeToDiscoverInMs,
9
8
  localStorageKeyExpirationInMs = _ref.localStorageKeyExpirationInMs;
9
+ var discovered = isDiscovered || isLocalStorageKeyDiscovered(localStorageKey);
10
10
  var onDiscovery = useCallback(function () {
11
- markLocalStorageKeyDiscovered(localStorageKey, localStorageKeyExpirationInMs);
12
- }, [localStorageKey, localStorageKeyExpirationInMs]);
13
- useEffect(function () {
14
- if (timeToDiscoverInMs) {
15
- var timeoutUntilDiscovery = setTimeout(function () {
16
- onDiscovery();
17
- }, timeToDiscoverInMs);
18
- return function () {
19
- return clearTimeout(timeoutUntilDiscovery);
20
- };
11
+ if (!discovered) {
12
+ markLocalStorageKeyDiscovered(localStorageKey, localStorageKeyExpirationInMs);
21
13
  }
22
- onDiscovery();
23
- }, [isDiscovered, localStorageKey, onDiscovery, timeToDiscoverInMs]);
14
+ }, [discovered, localStorageKey, localStorageKeyExpirationInMs]);
24
15
  return /*#__PURE__*/React.createElement(Pulse, {
25
- isDiscovered: isDiscovered
16
+ onAnimationIteration: onDiscovery,
17
+ isDiscovered: discovered
26
18
  }, children);
27
19
  };
28
20
  export default Pulse;
@@ -19,5 +19,10 @@ export var messages = defineMessages({
19
19
  id: 'fabric.editor.datasource.assetsObjects.description',
20
20
  defaultMessage: 'Insert objects from Assets in Jira Service Management with search and filtering',
21
21
  description: 'Description text displayed when selecting the type of data to include onto the page, in this case: JSM Assets objects'
22
+ },
23
+ inlineOverlay: {
24
+ id: 'fabric.editor.inlineOverlay',
25
+ defaultMessage: 'Change view',
26
+ description: 'An overlay shown when hover over inline smart link to inform user that they can change link view to card and/or embed.'
22
27
  }
23
28
  });
@@ -1,8 +1,10 @@
1
- import React, { memo, useCallback, useMemo } from 'react';
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import React, { memo, useCallback, useMemo, useState } from 'react';
2
3
  import rafSchedule from 'raf-schd';
3
4
  import { findOverflowScrollParent } from '@atlaskit/editor-common/ui';
4
5
  import { Card as SmartCard } from '@atlaskit/smart-card';
5
6
  import { registerCard } from '../pm-plugins/actions';
7
+ import InlineCardOverlay from '../ui/InlineCardOverlay';
6
8
  var InlineCard = function InlineCard(_ref) {
7
9
  var node = _ref.node,
8
10
  cardContext = _ref.cardContext,
@@ -16,6 +18,13 @@ var InlineCard = function InlineCard(_ref) {
16
18
  var _node$attrs = node.attrs,
17
19
  url = _node$attrs.url,
18
20
  data = _node$attrs.data;
21
+
22
+ // A complete show/hide logic for the overlay will be implemented
23
+ // in EDM-8239 and EDM-8241
24
+ var _useState = useState(false),
25
+ _useState2 = _slicedToArray(_useState, 2),
26
+ isOverlayVisible = _useState2[0],
27
+ setIsOverlayVisible = _useState2[1];
19
28
  var onClick = function onClick() {};
20
29
  var onResolve = useCallback(function (data) {
21
30
  if (!getPos || typeof getPos === 'boolean') {
@@ -49,7 +58,16 @@ var InlineCard = function InlineCard(_ref) {
49
58
  });
50
59
  }, [onResolve]);
51
60
  var card = /*#__PURE__*/React.createElement("span", {
52
- className: "card"
61
+ className: "card",
62
+ onMouseEnter: function onMouseEnter() {
63
+ return setIsOverlayVisible(true);
64
+ },
65
+ onMouseLeave: function onMouseLeave() {
66
+ return setIsOverlayVisible(false);
67
+ }
68
+ }, /*#__PURE__*/React.createElement(InlineCardOverlay, {
69
+ isVisible: isOverlayVisible,
70
+ url: url
53
71
  }, /*#__PURE__*/React.createElement(SmartCard, {
54
72
  key: url,
55
73
  url: url,
@@ -61,7 +79,7 @@ var InlineCard = function InlineCard(_ref) {
61
79
  onError: onError,
62
80
  inlinePreloaderStyle: useAlternativePreloader ? 'on-right-without-skeleton' : undefined,
63
81
  showServerActions: showServerActions
64
- }));
82
+ })));
65
83
  // [WS-2307]: we only render card wrapped into a Provider when the value is ready,
66
84
  // otherwise if we got data, we can render the card directly since it doesn't need the Provider
67
85
  return cardContext && cardContext.value ? /*#__PURE__*/React.createElement(cardContext.Provider, {
@@ -110,14 +110,8 @@ export var floatingToolbar = function floatingToolbar(cardOptions, featureFlags,
110
110
 
111
111
  // Applies padding override for when link picker is currently displayed
112
112
  var className = pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar ? FLOATING_TOOLBAR_LINKPICKER_CLASSNAME : undefined;
113
-
114
- /**
115
- * Enable focus trap only if feature flag is enabled AND for the new version of the picker
116
- */
117
113
  var lpLinkPicker = featureFlags.lpLinkPicker,
118
- lpLinkPickerFocusTrap = featureFlags.lpLinkPickerFocusTrap,
119
114
  preventPopupOverflow = featureFlags.preventPopupOverflow;
120
- var shouldEnableFocusTrap = lpLinkPicker && lpLinkPickerFocusTrap;
121
115
  var isLinkPickerEnabled = !!lpLinkPicker;
122
116
  return _objectSpread(_objectSpread({
123
117
  title: intl.formatMessage(messages.card),
@@ -136,8 +130,7 @@ export var floatingToolbar = function floatingToolbar(cardOptions, featureFlags,
136
130
  return element;
137
131
  },
138
132
  items: generateToolbarItems(state, featureFlags, intl, providerFactory, cardOptions, platform, linkPickerOptions, pluginInjectionApi),
139
- scrollable: pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar ? false : true,
140
- focusTrap: shouldEnableFocusTrap && (pluginState === null || pluginState === void 0 ? void 0 : pluginState.showLinkingToolbar)
133
+ scrollable: pluginState !== null && pluginState !== void 0 && pluginState.showLinkingToolbar ? false : true
141
134
  }, editLinkToolbarConfig(Boolean(pluginState === null || pluginState === void 0 ? void 0 : pluginState.showLinkingToolbar), isLinkPickerEnabled));
142
135
  };
143
136
  };
@@ -397,4 +390,7 @@ var getDatasourceButtonGroup = function getDatasourceButtonGroup(metadata, intl,
397
390
  onClick: withToolbarMetadata(removeCard(editorAnalyticsApi))
398
391
  });
399
392
  return toolbarItems;
393
+ };
394
+ export var shouldRenderToolbarPulse = function shouldRenderToolbarPulse(embedEnabled, appearance, status, isDiscoverabilityEnabled) {
395
+ return embedEnabled && appearance === 'inline' && status === 'resolved' && isDiscoverabilityEnabled && getBooleanFF('platform.linking-platform.smart-card.inline-switcher');
400
396
  };
@@ -0,0 +1,179 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ /** @jsx jsx */
6
+
7
+ import React, { useLayoutEffect, useMemo, useRef, useState } from 'react';
8
+ import { css, jsx } from '@emotion/react';
9
+ import { useIntl } from 'react-intl-next';
10
+ import { browser } from '@atlaskit/editor-common/utils';
11
+ import HipchatChevronDownIcon from '@atlaskit/icon/glyph/hipchat/chevron-down';
12
+ import HipchatChevronUpIcon from '@atlaskit/icon/glyph/hipchat/chevron-up';
13
+ import { N20A, N800 } from '@atlaskit/theme/colors';
14
+ import { messages } from '../../messages';
15
+ var PADDING_IN_PX = 2;
16
+ var containerStyles = css({
17
+ position: 'relative'
18
+ });
19
+ var linkStyles = css({
20
+ color: "var(--ds-text, #172B4D)",
21
+ textDecoration: 'none'
22
+ });
23
+ var overlayStyles = css({
24
+ // Positioning
25
+ position: 'relative',
26
+ display: 'inline-flex',
27
+ flexWrap: 'nowrap',
28
+ alignItems: 'center',
29
+ alignSelf: 'stretch',
30
+ height: 'inherit',
31
+ lineHeight: 'initial',
32
+ width: 'max-content',
33
+ top: "var(--ds-space-0, 0)",
34
+ bottom: "var(--ds-space-0, 0)",
35
+ right: 3,
36
+ margin: "-1px ".concat("var(--ds-space-0, 0)"),
37
+ padding: "var(--ds-space-0, 0)",
38
+ // Styling
39
+ fontSize: 'inherit',
40
+ fontWeight: 'normal',
41
+ color: "var(--ds-text, ".concat(N800, ")"),
42
+ background: "var(--ds-background-accent-gray-subtlest, ".concat(N20A, ")"),
43
+ borderRadius: 3,
44
+ // inline card border of 4px - 1px
45
+
46
+ // Using `&` twice to increase specificity. (These are not nested styles.)
47
+ /* eslint-disable @atlaskit/design-system/no-nested-styles */
48
+ '&&:link': _objectSpread({}, linkStyles),
49
+ '&&:active': _objectSpread({}, linkStyles),
50
+ '&&:focus': _objectSpread({}, linkStyles),
51
+ '&&:hover': _objectSpread({}, linkStyles),
52
+ '&&:visited': _objectSpread({}, linkStyles),
53
+ /* eslint-enable @atlaskit/design-system/no-nested-styles */
54
+
55
+ // EDM-1717: box-shadow Safari fix bring load wrapper zIndex to 1
56
+ zIndex: 2,
57
+ // Fill lines, match heading and paragraph size
58
+ '::before': {
59
+ content: '" "',
60
+ display: 'inline-block',
61
+ verticalAlign: 'middle',
62
+ width: "var(--ds-space-0, 0)",
63
+ margin: "var(--ds-space-0, 0)",
64
+ padding: "var(--ds-space-0, 0)"
65
+ }
66
+ });
67
+ var safariOverlayStyles = css({
68
+ height: '1.1em',
69
+ paddingBottom: "var(--ds-space-025, 2px)",
70
+ right: 3
71
+ });
72
+ var textStyles = css({
73
+ paddingLeft: "var(--ds-space-050, 4px)"
74
+ });
75
+ var iconStyles = css({
76
+ // Position icon in the middle
77
+ display: 'inline-grid',
78
+ // We want to position the icon in the middle of large text type like heading 1
79
+ // eslint-disable-next-line @atlaskit/design-system/no-nested-styles
80
+ span: {
81
+ display: 'inline-grid'
82
+ }
83
+ });
84
+ var markerStyles = css({
85
+ height: "var(--ds-space-0, 0)",
86
+ width: "var(--ds-space-0, 0)",
87
+ margin: "var(--ds-space-0, 0)",
88
+ padding: "var(--ds-space-0, 0)"
89
+ });
90
+ var InlineCardOverlay = function InlineCardOverlay(_ref) {
91
+ var children = _ref.children,
92
+ _ref$isToolbarOpen = _ref.isToolbarOpen,
93
+ isToolbarOpen = _ref$isToolbarOpen === void 0 ? false : _ref$isToolbarOpen,
94
+ _ref$isVisible = _ref.isVisible,
95
+ isVisible = _ref$isVisible === void 0 ? false : _ref$isVisible,
96
+ _ref$testId = _ref.testId,
97
+ testId = _ref$testId === void 0 ? 'inline-card-overlay' : _ref$testId,
98
+ url = _ref.url;
99
+ var _useState = useState(true),
100
+ _useState2 = _slicedToArray(_useState, 2),
101
+ showLabel = _useState2[0],
102
+ setShowLabel = _useState2[1];
103
+ var _useState3 = useState(0),
104
+ _useState4 = _slicedToArray(_useState3, 2),
105
+ overlayWidth = _useState4[0],
106
+ setOverlayWidth = _useState4[1];
107
+ var containerRef = useRef(null);
108
+ var markerRef = useRef(null);
109
+ var overlayRef = useRef(null);
110
+ var labelRef = useRef(null);
111
+ useLayoutEffect(function () {
112
+ if (!isVisible) {
113
+ // Reset to default state for width calculation when the component become visible.
114
+ setShowLabel(true);
115
+ return;
116
+ }
117
+ try {
118
+ var _containerRef$current, _containerRef$current2, _markerRef$current$ge, _markerRef$current, _overlayRef$current$g, _overlayRef$current, _labelRef$current$get, _labelRef$current;
119
+ // Get the width of the available space to display overlay
120
+ var start = (_containerRef$current = containerRef === null || containerRef === void 0 || (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 || (_containerRef$current2 = _containerRef$current2.getBoundingClientRect()) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.left) !== null && _containerRef$current !== void 0 ? _containerRef$current : 0;
121
+ var end = (_markerRef$current$ge = markerRef === null || markerRef === void 0 || (_markerRef$current = markerRef.current) === null || _markerRef$current === void 0 || (_markerRef$current = _markerRef$current.getBoundingClientRect()) === null || _markerRef$current === void 0 ? void 0 : _markerRef$current.left) !== null && _markerRef$current$ge !== void 0 ? _markerRef$current$ge : 0;
122
+ var availableWidth = end - start - PADDING_IN_PX;
123
+
124
+ // Get overlay width and label width
125
+ var _overlayWidth = (_overlayRef$current$g = overlayRef === null || overlayRef === void 0 || (_overlayRef$current = overlayRef.current) === null || _overlayRef$current === void 0 || (_overlayRef$current = _overlayRef$current.getBoundingClientRect()) === null || _overlayRef$current === void 0 ? void 0 : _overlayRef$current.width) !== null && _overlayRef$current$g !== void 0 ? _overlayRef$current$g : 0;
126
+
127
+ // Show label if there is enough space to display
128
+ var shouldShowLabel = availableWidth > 0 && _overlayWidth > 0 ? availableWidth > _overlayWidth : false;
129
+ setShowLabel(shouldShowLabel);
130
+
131
+ // We use relative positioning and need to set
132
+ // negative margin left (ltr) as the width of the overlay
133
+ // to make the overlay position on top of inline link.
134
+ var labelWidth = (_labelRef$current$get = labelRef === null || labelRef === void 0 || (_labelRef$current = labelRef.current) === null || _labelRef$current === void 0 || (_labelRef$current = _labelRef$current.getBoundingClientRect()) === null || _labelRef$current === void 0 ? void 0 : _labelRef$current.width) !== null && _labelRef$current$get !== void 0 ? _labelRef$current$get : 0;
135
+ var newOverlayWidth = shouldShowLabel ? _overlayWidth : _overlayWidth - labelWidth;
136
+ setOverlayWidth(newOverlayWidth);
137
+ } catch (_unused) {
138
+ // If something goes wrong, play it safe by hiding label so that
139
+ // the component does not look too janky.
140
+ setShowLabel(false);
141
+ }
142
+ }, [isVisible]);
143
+ var intl = useIntl();
144
+ var label = intl.formatMessage(messages.inlineOverlay);
145
+ var icon = useMemo(function () {
146
+ var IconComponent = isToolbarOpen ? HipchatChevronUpIcon : HipchatChevronDownIcon;
147
+ return jsx(IconComponent, {
148
+ label: label,
149
+ size: "small",
150
+ testId: "".concat(testId, "-").concat(isToolbarOpen ? 'open' : 'close')
151
+ });
152
+ }, [isToolbarOpen, label, testId]);
153
+ return jsx("span", {
154
+ css: containerStyles,
155
+ ref: containerRef
156
+ }, children, isVisible && jsx(React.Fragment, null, jsx("span", {
157
+ "aria-hidden": "true",
158
+ css: markerStyles,
159
+ ref: markerRef
160
+ }), jsx("a", {
161
+ css: [overlayStyles, browser.safari && safariOverlayStyles],
162
+ style: {
163
+ marginLeft: -overlayWidth
164
+ },
165
+ "data-testid": testId,
166
+ href: url,
167
+ onClick: function onClick(e) {
168
+ return e.preventDefault();
169
+ },
170
+ ref: overlayRef
171
+ }, showLabel && jsx("span", {
172
+ css: textStyles,
173
+ "data-testid": "".concat(testId, "-label"),
174
+ ref: labelRef
175
+ }, label), jsx("span", {
176
+ css: iconStyles
177
+ }, icon))));
178
+ };
179
+ export default InlineCardOverlay;
@@ -0,0 +1 @@
1
+ export {};
@@ -16,6 +16,8 @@ import { commandWithMetadata, getButtonGroupOption, LinkToolbarButtonGroup } fro
16
16
  import nodeNames, { cardMessages as messages } from '@atlaskit/editor-common/messages';
17
17
  import { isSupportedInParent } from '@atlaskit/editor-common/utils';
18
18
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
19
+ import { DiscoveryPulse } from '../common/pulse';
20
+ import { shouldRenderToolbarPulse } from '../toolbar';
19
21
  // eslint-disable-next-line @repo/internal/react/no-class-components
20
22
  export var LinkToolbarAppearance = /*#__PURE__*/function (_React$Component) {
21
23
  _inherits(LinkToolbarAppearance, _React$Component);
@@ -28,7 +30,7 @@ export var LinkToolbarAppearance = /*#__PURE__*/function (_React$Component) {
28
30
  }
29
31
  _this = _super.call.apply(_super, [this].concat(args));
30
32
  _defineProperty(_assertThisInitialized(_this), "renderDropdown", function (view, cardContext) {
31
- var _cardActions$setSelec, _cardActions$setSelec2, _cardActions$changeSe, _cardActions$setSelec3;
33
+ var _cardActions$setSelec, _cardActions$setSelec2, _cardActions$changeSe, _cardActions$setSelec3, _cardContext$store2;
32
34
  var _this$props = _this.props,
33
35
  url = _this$props.url,
34
36
  intl = _this$props.intl,
@@ -39,7 +41,9 @@ export var LinkToolbarAppearance = /*#__PURE__*/function (_React$Component) {
39
41
  allowBlockCards = _this$props$allowBloc === void 0 ? true : _this$props$allowBloc,
40
42
  platform = _this$props.platform,
41
43
  editorAnalyticsApi = _this$props.editorAnalyticsApi,
42
- cardActions = _this$props.cardActions;
44
+ cardActions = _this$props.cardActions,
45
+ _this$props$showInlin = _this$props.showInlineUpgradeDiscoverability,
46
+ showInlineUpgradeDiscoverability = _this$props$showInlin === void 0 ? false : _this$props$showInlin;
43
47
  var preview = allowEmbeds && cardContext && url && cardContext.extractors.getPreview(url, platform);
44
48
  var defaultCommand = function defaultCommand() {
45
49
  return false;
@@ -99,7 +103,7 @@ export var LinkToolbarAppearance = /*#__PURE__*/function (_React$Component) {
99
103
  if (embedOption) {
100
104
  options.push(embedOption);
101
105
  }
102
- return /*#__PURE__*/React.createElement(LinkToolbarButtonGroup, {
106
+ var LinkToolbarButtons = /*#__PURE__*/React.createElement(LinkToolbarButtonGroup, {
103
107
  key: "link-toolbar-button-group",
104
108
  options: options.map(function (option) {
105
109
  return getButtonGroupOption(intl, dispatchCommand, _objectSpread(_objectSpread({}, option), {}, {
@@ -109,6 +113,18 @@ export var LinkToolbarAppearance = /*#__PURE__*/function (_React$Component) {
109
113
  }));
110
114
  })
111
115
  });
116
+ var status = url ? cardContext === null || cardContext === void 0 || (_cardContext$store2 = cardContext.store) === null || _cardContext$store2 === void 0 || (_cardContext$store2 = _cardContext$store2.getState()[url]) === null || _cardContext$store2 === void 0 ? void 0 : _cardContext$store2.status : '';
117
+ var embedEnabled = embedOption ? !embedOption.disabled : false;
118
+ if (shouldRenderToolbarPulse(embedEnabled, currentAppearance !== null && currentAppearance !== void 0 ? currentAppearance : '', status !== null && status !== void 0 ? status : '', showInlineUpgradeDiscoverability)) {
119
+ return (
120
+ /*#__PURE__*/
121
+ // This div is necessary because the toolbar uses :first-child to add margins and can't add margins to the pulse element
122
+ React.createElement("div", null, /*#__PURE__*/React.createElement(DiscoveryPulse, {
123
+ localStorageKey: "toolbar-upgrade-pulse"
124
+ }, LinkToolbarButtons))
125
+ );
126
+ }
127
+ return LinkToolbarButtons;
112
128
  });
113
129
  return _this;
114
130
  }
@@ -13,14 +13,10 @@ export interface PulseProps {
13
13
  * The time in ms after which the key in local storage will be considered expired and the Pulse will be shown again
14
14
  */
15
15
  localStorageKeyExpirationInMs?: number;
16
- /**
17
- * The time in ms since the Pulse has started after which the key will be stored in local storage.
18
- */
19
- timeToDiscoverInMs?: number;
20
16
  /**
21
17
  * And indicator that the feature was discovered externally and the pulsation needs to stop.
22
18
  */
23
19
  isDiscovered?: boolean;
24
20
  }
25
- export declare const DiscoveryPulse: ({ children, localStorageKey, isDiscovered, timeToDiscoverInMs, localStorageKeyExpirationInMs, }: PulseProps) => JSX.Element;
21
+ export declare const DiscoveryPulse: ({ children, localStorageKey, isDiscovered, localStorageKeyExpirationInMs, }: PulseProps) => JSX.Element;
26
22
  export default Pulse;
@@ -19,4 +19,9 @@ export declare const messages: {
19
19
  defaultMessage: string;
20
20
  description: string;
21
21
  };
22
+ inlineOverlay: {
23
+ id: string;
24
+ defaultMessage: string;
25
+ description: string;
26
+ };
22
27
  };
@@ -7,3 +7,4 @@ export declare const removeCard: (editorAnalyticsApi: EditorAnalyticsAPI | undef
7
7
  export declare const visitCardLink: (editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
8
8
  export declare const openLinkSettings: (editorAnalyticsApi: EditorAnalyticsAPI | undefined) => Command;
9
9
  export declare const floatingToolbar: (cardOptions: CardOptions, featureFlags: FeatureFlags, platform?: CardPlatform, linkPickerOptions?: LinkPickerOptions, pluginInjectionApi?: ExtractInjectionAPI<typeof cardPlugin>) => FloatingToolbarHandler;
10
+ export declare const shouldRenderToolbarPulse: (embedEnabled: boolean, appearance: string, status: string, isDiscoverabilityEnabled: boolean) => boolean;
@@ -0,0 +1,5 @@
1
+ /** @jsx jsx */
2
+ import type { FC } from 'react';
3
+ import type { InlineCardOverlayProps } from './types';
4
+ declare const InlineCardOverlay: FC<InlineCardOverlayProps>;
5
+ export default InlineCardOverlay;
@@ -0,0 +1,6 @@
1
+ export type InlineCardOverlayProps = {
2
+ isToolbarOpen?: boolean;
3
+ isVisible?: boolean;
4
+ testId?: string;
5
+ url: string;
6
+ };