@atlaskit/editor-plugin-mentions 13.1.1 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -0
- package/dist/cjs/mentionsPlugin.js +10 -2
- package/dist/cjs/nodeviews/disabledTooltipRenderer.compiled.css +1 -0
- package/dist/cjs/nodeviews/disabledTooltipRenderer.js +193 -0
- package/dist/cjs/nodeviews/mentionNodeView.js +128 -12
- package/dist/cjs/pm-plugins/main.js +1 -1
- package/dist/es2019/mentionsPlugin.js +10 -2
- package/dist/es2019/nodeviews/disabledTooltipRenderer.compiled.css +1 -0
- package/dist/es2019/nodeviews/disabledTooltipRenderer.js +168 -0
- package/dist/es2019/nodeviews/mentionNodeView.js +123 -12
- package/dist/es2019/pm-plugins/main.js +1 -1
- package/dist/esm/mentionsPlugin.js +10 -2
- package/dist/esm/nodeviews/disabledTooltipRenderer.compiled.css +1 -0
- package/dist/esm/nodeviews/disabledTooltipRenderer.js +184 -0
- package/dist/esm/nodeviews/mentionNodeView.js +128 -12
- package/dist/esm/pm-plugins/main.js +1 -1
- package/dist/types/mentionsPluginType.d.ts +3 -1
- package/dist/types/nodeviews/disabledTooltipRenderer.d.ts +25 -0
- package/dist/types/nodeviews/mentionNodeView.d.ts +18 -1
- package/dist/types-ts4.5/mentionsPluginType.d.ts +3 -1
- package/dist/types-ts4.5/nodeviews/disabledTooltipRenderer.d.ts +25 -0
- package/dist/types-ts4.5/nodeviews/mentionNodeView.d.ts +18 -1
- package/package.json +6 -5
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/* disabledTooltipRenderer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import "./disabledTooltipRenderer.compiled.css";
|
|
3
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
4
|
+
import React, { useEffect, useState } from 'react';
|
|
5
|
+
import { bindAll } from 'bind-event-listener';
|
|
6
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
|
|
7
|
+
import uuid from 'uuid/v4';
|
|
8
|
+
import Tooltip from '@atlaskit/tooltip';
|
|
9
|
+
const styles = {
|
|
10
|
+
hiddenTrigger: "_1e0cglyw"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* ADS `<Tooltip>` hands us a ref via its render-prop child. That ref may be
|
|
15
|
+
* either a callback ref or a mutable ref object — React supports both shapes
|
|
16
|
+
* and ADS's typing keeps both possible. This helper assigns the supplied
|
|
17
|
+
* element to whichever ref shape was provided so the tooltip ends up using
|
|
18
|
+
* the chip's bounding box for positioning and its DOM for trigger events.
|
|
19
|
+
*/
|
|
20
|
+
const assignRef = (ref, element) => {
|
|
21
|
+
if (typeof ref === 'function') {
|
|
22
|
+
ref(element);
|
|
23
|
+
} else if (ref) {
|
|
24
|
+
ref.current = element;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Names of the React-style trigger-prop handlers we forward from ADS
|
|
30
|
+
* `<Tooltip>` onto the chip element.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Maps each React-style trigger-prop handler ADS `<Tooltip>` hands us in its
|
|
35
|
+
* render-prop callback to the DOM event name we attach to the chip via
|
|
36
|
+
* `bind-event-listener`. The chip lives in the ProseMirror document and is
|
|
37
|
+
* not a React child of the tooltip, so we have to bridge React handlers to
|
|
38
|
+
* native event listeners ourselves.
|
|
39
|
+
*
|
|
40
|
+
* Names are listed in the same order ADS internally registers them.
|
|
41
|
+
*/
|
|
42
|
+
const TRIGGER_EVENT_MAP = [['onMouseOver', 'mouseover'], ['onMouseOut', 'mouseout'], ['onMouseMove', 'mousemove'], ['onMouseDown', 'mousedown'], ['onFocus', 'focusin'], ['onBlur', 'focusout']];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Anchors an ADS `<Tooltip>` to a ProseMirror chip element that is **not** a
|
|
46
|
+
* React child of the tooltip. The chip itself stays in the PM document; this
|
|
47
|
+
* renderer mounts an always-present React subtree via `portalProviderAPI` whose
|
|
48
|
+
* sole job is to host the tooltip and forward the ADS-provided trigger ref +
|
|
49
|
+
* event handlers onto the chip.
|
|
50
|
+
*
|
|
51
|
+
* The forwarding is deliberate: ADS `<Tooltip>` expects to attach its hover /
|
|
52
|
+
* focus / blur listeners to its render-prop child, but our render-prop child
|
|
53
|
+
* is a `display: none` placeholder span that no real event can reach. We bridge
|
|
54
|
+
* those listeners to the chip via `addEventListener` so the tooltip opens and
|
|
55
|
+
* closes in response to the user actually interacting with the chip — keyboard
|
|
56
|
+
* focus, mouse hover, screen-reader focus, the lot.
|
|
57
|
+
*/
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Hook that mirrors ADS Tooltip's React trigger props onto a DOM element
|
|
61
|
+
* which is not a React child of the tooltip. Re-attaches whenever ADS hands
|
|
62
|
+
* us a fresh set of props (which happens on every render of the render-prop
|
|
63
|
+
* child) and cleans up on unmount.
|
|
64
|
+
*
|
|
65
|
+
* We use `bind-event-listener`'s `bindAll` rather than raw
|
|
66
|
+
* `addEventListener` / `removeEventListener` calls so the lifetime of every
|
|
67
|
+
* subscription is paired with a single `UnbindFn` — the AFM-mandated pattern
|
|
68
|
+
* for keeping listener bookkeeping leak-free.
|
|
69
|
+
*/
|
|
70
|
+
const useBridgedTriggerListeners = (chip, triggerProps) => {
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
// Build the bindAll bindings array out of only the handlers ADS actually
|
|
73
|
+
// supplied. Each React handler is wrapped in a thin adapter so the
|
|
74
|
+
// listener signature matches the native `EventListener` shape; ADS
|
|
75
|
+
// handlers ignore the synthetic-event-only fields they don't use
|
|
76
|
+
// (target, currentTarget), so passing the raw DOM event through
|
|
77
|
+
// `unknown` is safe in practice.
|
|
78
|
+
const bindings = TRIGGER_EVENT_MAP.flatMap(([propName, eventName]) => {
|
|
79
|
+
const handler = triggerProps[propName];
|
|
80
|
+
if (!handler) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
return [{
|
|
84
|
+
type: eventName,
|
|
85
|
+
listener: event => {
|
|
86
|
+
handler(event);
|
|
87
|
+
}
|
|
88
|
+
}];
|
|
89
|
+
});
|
|
90
|
+
if (bindings.length === 0) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const unbind = bindAll(chip, bindings);
|
|
94
|
+
return unbind;
|
|
95
|
+
}, [chip, triggerProps]);
|
|
96
|
+
};
|
|
97
|
+
const AnchoredTooltip = ({
|
|
98
|
+
subscribe,
|
|
99
|
+
getInitialTooltip,
|
|
100
|
+
referenceElement
|
|
101
|
+
}) => {
|
|
102
|
+
const [tooltip, setTooltipState] = useState(getInitialTooltip);
|
|
103
|
+
useEffect(() => subscribe(setTooltipState), [subscribe]);
|
|
104
|
+
if (!tooltip) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
108
|
+
content: tooltip,
|
|
109
|
+
position: "top"
|
|
110
|
+
}, tooltipProps => /*#__PURE__*/React.createElement(TriggerBridge, {
|
|
111
|
+
referenceElement: referenceElement,
|
|
112
|
+
tooltipProps: tooltipProps
|
|
113
|
+
}));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Render-prop child for ADS `<Tooltip>`. The element it returns is a
|
|
118
|
+
* `display: none` placeholder that satisfies the render-prop API; the
|
|
119
|
+
* real trigger surface is the chip in the PM document, which receives
|
|
120
|
+
* both the ADS ref and the bridged event listeners via the side-effects
|
|
121
|
+
* declared on this component.
|
|
122
|
+
*/
|
|
123
|
+
const TriggerBridge = ({
|
|
124
|
+
referenceElement,
|
|
125
|
+
tooltipProps
|
|
126
|
+
}) => {
|
|
127
|
+
useBridgedTriggerListeners(referenceElement, tooltipProps);
|
|
128
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
129
|
+
ref: () => assignRef(tooltipProps.ref, referenceElement),
|
|
130
|
+
"aria-hidden": "true",
|
|
131
|
+
className: ax([styles.hiddenTrigger])
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
export const disabledTooltipRenderer = ({
|
|
135
|
+
chipElement,
|
|
136
|
+
portalProviderAPI
|
|
137
|
+
}) => {
|
|
138
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
|
|
139
|
+
const key = uuid();
|
|
140
|
+
let currentTooltip;
|
|
141
|
+
const listeners = new Set();
|
|
142
|
+
const broadcast = () => {
|
|
143
|
+
listeners.forEach(listener => listener(currentTooltip));
|
|
144
|
+
};
|
|
145
|
+
const getInitialTooltip = () => currentTooltip;
|
|
146
|
+
const subscribe = listener => {
|
|
147
|
+
listeners.add(listener);
|
|
148
|
+
return () => {
|
|
149
|
+
listeners.delete(listener);
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
const renderElement = () => /*#__PURE__*/React.createElement(AnchoredTooltip, {
|
|
153
|
+
referenceElement: chipElement,
|
|
154
|
+
getInitialTooltip: getInitialTooltip,
|
|
155
|
+
subscribe: subscribe
|
|
156
|
+
});
|
|
157
|
+
portalProviderAPI.render(renderElement, chipElement, key);
|
|
158
|
+
return {
|
|
159
|
+
setTooltip(text) {
|
|
160
|
+
currentTooltip = text;
|
|
161
|
+
broadcast();
|
|
162
|
+
},
|
|
163
|
+
destroy() {
|
|
164
|
+
portalProviderAPI.remove(key);
|
|
165
|
+
listeners.clear();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
1
|
import { getBrowserInfo } from '@atlaskit/editor-common/browser';
|
|
3
2
|
import { ZERO_WIDTH_SPACE } from '@atlaskit/editor-common/whitespace';
|
|
4
3
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -6,6 +5,7 @@ import { isResolvingMentionProvider, MentionNameStatus } from '@atlaskit/mention
|
|
|
6
5
|
import { isRestricted } from '@atlaskit/mention/types';
|
|
7
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
|
+
import { disabledTooltipRenderer } from './disabledTooltipRenderer';
|
|
9
9
|
import { profileCardRenderer } from './profileCardRenderer';
|
|
10
10
|
const primitiveClassName = 'editor-mention-primitive';
|
|
11
11
|
// @ts-ignore - TS1501 TypeScript 5.9.2 upgrade
|
|
@@ -55,7 +55,10 @@ const handleProviderName = async (mentionProvider, node) => {
|
|
|
55
55
|
return processName(resolvedNameDetail);
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
|
-
const getNewState = (isHighlighted, isRestricted) => {
|
|
58
|
+
const getNewState = (isHighlighted, isRestricted, isDisabled) => {
|
|
59
|
+
if (isDisabled) {
|
|
60
|
+
return 'disabled';
|
|
61
|
+
}
|
|
59
62
|
if (isHighlighted) {
|
|
60
63
|
return 'self';
|
|
61
64
|
}
|
|
@@ -67,7 +70,6 @@ const getNewState = (isHighlighted, isRestricted) => {
|
|
|
67
70
|
export class MentionNodeView {
|
|
68
71
|
constructor(node, config) {
|
|
69
72
|
var _this$domElement$quer, _api$mention$sharedSt;
|
|
70
|
-
_defineProperty(this, "state", 'default');
|
|
71
73
|
const {
|
|
72
74
|
options,
|
|
73
75
|
api,
|
|
@@ -87,10 +89,12 @@ export class MentionNodeView {
|
|
|
87
89
|
mentionProvider
|
|
88
90
|
} = (_api$mention$sharedSt = api === null || api === void 0 ? void 0 : api.mention.sharedState.currentState()) !== null && _api$mention$sharedSt !== void 0 ? _api$mention$sharedSt : {};
|
|
89
91
|
this.updateState(mentionProvider);
|
|
92
|
+
this.subscribeToProviderDisabledStateChanges(mentionProvider);
|
|
90
93
|
this.cleanup = api === null || api === void 0 ? void 0 : api.mention.sharedState.onChange(({
|
|
91
94
|
nextSharedState
|
|
92
95
|
}) => {
|
|
93
96
|
this.updateState(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.mentionProvider);
|
|
97
|
+
this.subscribeToProviderDisabledStateChanges(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.mentionProvider);
|
|
94
98
|
});
|
|
95
99
|
const {
|
|
96
100
|
destroyProfileCard,
|
|
@@ -115,10 +119,88 @@ export class MentionNodeView {
|
|
|
115
119
|
this.destroyProfileCard = destroyProfileCard;
|
|
116
120
|
this.removeProfileCard = removeProfileCard;
|
|
117
121
|
}
|
|
118
|
-
setClassList(state) {
|
|
119
|
-
var _this$mentionPrimitiv, _this$mentionPrimitiv2;
|
|
122
|
+
setClassList(state, disabledTooltip) {
|
|
123
|
+
var _this$mentionPrimitiv, _this$mentionPrimitiv2, _this$mentionPrimitiv3;
|
|
120
124
|
(_this$mentionPrimitiv = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv === void 0 ? void 0 : _this$mentionPrimitiv.classList.toggle('mention-self', state === 'self');
|
|
121
125
|
(_this$mentionPrimitiv2 = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv2 === void 0 ? void 0 : _this$mentionPrimitiv2.classList.toggle('mention-restricted', state === 'restricted');
|
|
126
|
+
(_this$mentionPrimitiv3 = this.mentionPrimitiveElement) === null || _this$mentionPrimitiv3 === void 0 ? void 0 : _this$mentionPrimitiv3.classList.toggle('mention-disabled', state === 'disabled');
|
|
127
|
+
// Mirror the React `<Mention>` a11y behaviour: when the chip is
|
|
128
|
+
// disabled, expose `aria-disabled` so assistive tech announces it as
|
|
129
|
+
// such. Also surface the tooltip text via `aria-label` so screen-reader
|
|
130
|
+
// users hear *why* the chip is disabled, matching the React `<Mention>`
|
|
131
|
+
// behaviour at `Mention/index.tsx` line 152.
|
|
132
|
+
if (this.domElement) {
|
|
133
|
+
if (state === 'disabled') {
|
|
134
|
+
this.domElement.setAttribute('aria-disabled', 'true');
|
|
135
|
+
if (disabledTooltip) {
|
|
136
|
+
const text = this.node.attrs.text || '@...';
|
|
137
|
+
this.domElement.setAttribute('aria-label', `${text} — ${disabledTooltip}`);
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
this.domElement.removeAttribute('aria-disabled');
|
|
141
|
+
this.domElement.removeAttribute('aria-label');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
getDisabledState(mentionProvider) {
|
|
146
|
+
var _mentionProvider$getM;
|
|
147
|
+
const input = {
|
|
148
|
+
id: this.node.attrs.id
|
|
149
|
+
};
|
|
150
|
+
return mentionProvider === null || mentionProvider === void 0 ? void 0 : (_mentionProvider$getM = mentionProvider.getMentionDisabledState) === null || _mentionProvider$getM === void 0 ? void 0 : _mentionProvider$getM.call(mentionProvider, input);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Subscribes this NodeView to disabled-state-change notifications on the
|
|
155
|
+
* supplied provider so already-rendered chips can re-evaluate themselves
|
|
156
|
+
* when the consumer's predicate inputs change (e.g. the active agent
|
|
157
|
+
* selection toggling in Rovo Chat). No-op for providers that don't
|
|
158
|
+
* implement `subscribeToDisabledStateChanges`.
|
|
159
|
+
*
|
|
160
|
+
* Idempotent: re-calling with the same provider keeps the existing
|
|
161
|
+
* subscription; passing a different provider tears the old subscription
|
|
162
|
+
* down before attaching the new one. Safe to call from the sharedState
|
|
163
|
+
* `onChange` handler when the editor swaps providers.
|
|
164
|
+
*/
|
|
165
|
+
subscribeToProviderDisabledStateChanges(mentionProvider) {
|
|
166
|
+
var _this$unsubscribeFrom;
|
|
167
|
+
if (this.subscribedProvider === mentionProvider) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
(_this$unsubscribeFrom = this.unsubscribeFromDisabledStateChanges) === null || _this$unsubscribeFrom === void 0 ? void 0 : _this$unsubscribeFrom.call(this);
|
|
171
|
+
this.unsubscribeFromDisabledStateChanges = undefined;
|
|
172
|
+
this.subscribedProvider = mentionProvider;
|
|
173
|
+
if (!(mentionProvider !== null && mentionProvider !== void 0 && mentionProvider.subscribeToDisabledStateChanges)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.unsubscribeFromDisabledStateChanges = mentionProvider.subscribeToDisabledStateChanges(() => {
|
|
177
|
+
this.updateState(this.subscribedProvider);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
syncDisabledTooltip(disabledState) {
|
|
181
|
+
// Capture the tooltip text into a local so the rest of the method can
|
|
182
|
+
// branch on a truthy string instead of re-asserting non-null fields
|
|
183
|
+
// off of `disabledState`.
|
|
184
|
+
const tooltipText = disabledState !== null && disabledState !== void 0 && disabledState.disabled ? disabledState.tooltip : undefined;
|
|
185
|
+
const chip = this.mentionPrimitiveElement;
|
|
186
|
+
const {
|
|
187
|
+
portalProviderAPI
|
|
188
|
+
} = this.config;
|
|
189
|
+
if (!chip || !portalProviderAPI) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (tooltipText) {
|
|
193
|
+
if (!this.disabledTooltip) {
|
|
194
|
+
this.disabledTooltip = disabledTooltipRenderer({
|
|
195
|
+
chipElement: chip,
|
|
196
|
+
portalProviderAPI
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
this.disabledTooltip.setTooltip(tooltipText);
|
|
200
|
+
} else if (this.disabledTooltip) {
|
|
201
|
+
this.disabledTooltip.destroy();
|
|
202
|
+
this.disabledTooltip = undefined;
|
|
203
|
+
}
|
|
122
204
|
}
|
|
123
205
|
setTextContent(name) {
|
|
124
206
|
if (name && !this.node.attrs.text && this.mentionPrimitiveElement) {
|
|
@@ -145,14 +227,25 @@ export class MentionNodeView {
|
|
|
145
227
|
const isHighlighted = expValEquals('platform_editor_vc90_transition_mentions', 'isEnabled', true) ? this.shouldHighlightMention(mentionProvider) : (_mentionProvider$shou2 = mentionProvider === null || mentionProvider === void 0 ? void 0 : mentionProvider.shouldHighlightMention({
|
|
146
228
|
id: this.node.attrs.id
|
|
147
229
|
})) !== null && _mentionProvider$shou2 !== void 0 ? _mentionProvider$shou2 : false;
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
230
|
+
const disabledState = this.getDisabledState(mentionProvider);
|
|
231
|
+
const isDisabled = !!(disabledState !== null && disabledState !== void 0 && disabledState.disabled);
|
|
232
|
+
const newState = getNewState(isHighlighted, isRestricted(this.node.attrs.accessLevel), isDisabled);
|
|
233
|
+
const disabledTooltip = disabledState !== null && disabledState !== void 0 && disabledState.disabled ? disabledState.tooltip : undefined;
|
|
234
|
+
// `setClassList` always runs so the aria-label (which depends on the
|
|
235
|
+
// tooltip text) stays in sync when the tooltip reason changes while
|
|
236
|
+
// the chip remains disabled. State-change-only writes would leave a
|
|
237
|
+
// stale aria-label after a tooltip-text-only update.
|
|
238
|
+
this.setClassList(newState, disabledTooltip);
|
|
239
|
+
// Tooltip wiring runs every update (not just on state change) so that
|
|
240
|
+
// the tooltip text stays in sync if the disabled reason changes while
|
|
241
|
+
// the chip is already disabled.
|
|
242
|
+
this.syncDisabledTooltip(disabledState);
|
|
153
243
|
const name = await handleProviderName(mentionProvider, this.node);
|
|
154
244
|
this.setTextContent(name);
|
|
155
|
-
|
|
245
|
+
// Only overwrite the disabled-state aria-label with the name-based one
|
|
246
|
+
// when the chip is NOT disabled; otherwise the disabled reason set in
|
|
247
|
+
// `setClassList` would be silently clobbered, regressing a11y.
|
|
248
|
+
if (name && this.domElement && (_this$config$options2 = this.config.options) !== null && _this$config$options2 !== void 0 && _this$config$options2.profilecardProvider && newState !== 'disabled') {
|
|
156
249
|
this.domElement.setAttribute('aria-label', getAccessibilityLabelFromName(name));
|
|
157
250
|
}
|
|
158
251
|
}
|
|
@@ -176,9 +269,27 @@ export class MentionNodeView {
|
|
|
176
269
|
return true;
|
|
177
270
|
}
|
|
178
271
|
destroy() {
|
|
179
|
-
var _this$cleanup, _this$destroyProfileC;
|
|
272
|
+
var _this$cleanup, _this$destroyProfileC, _this$disabledTooltip, _this$unsubscribeFrom2;
|
|
273
|
+
// Surface the destruction to the provider before tearing down so the
|
|
274
|
+
// chat layer can react (e.g. drop the agent id from `selectedAgentIds`).
|
|
275
|
+
// This is the lowest-level deletion signal — fires for backspace,
|
|
276
|
+
// select-and-delete, programmatic doc replaces, and editor unmount.
|
|
277
|
+
try {
|
|
278
|
+
var _this$subscribedProvi, _this$subscribedProvi2;
|
|
279
|
+
(_this$subscribedProvi = this.subscribedProvider) === null || _this$subscribedProvi === void 0 ? void 0 : (_this$subscribedProvi2 = _this$subscribedProvi.notifyMentionDestroyed) === null || _this$subscribedProvi2 === void 0 ? void 0 : _this$subscribedProvi2.call(_this$subscribedProvi, {
|
|
280
|
+
id: this.node.attrs.id
|
|
281
|
+
});
|
|
282
|
+
} catch (_error) {
|
|
283
|
+
// Defensive: never let consumer-side notification errors prevent
|
|
284
|
+
// the NodeView from cleaning up its own resources below.
|
|
285
|
+
}
|
|
180
286
|
(_this$cleanup = this.cleanup) === null || _this$cleanup === void 0 ? void 0 : _this$cleanup.call(this);
|
|
181
287
|
(_this$destroyProfileC = this.destroyProfileCard) === null || _this$destroyProfileC === void 0 ? void 0 : _this$destroyProfileC.call(this);
|
|
288
|
+
(_this$disabledTooltip = this.disabledTooltip) === null || _this$disabledTooltip === void 0 ? void 0 : _this$disabledTooltip.destroy();
|
|
289
|
+
this.disabledTooltip = undefined;
|
|
290
|
+
(_this$unsubscribeFrom2 = this.unsubscribeFromDisabledStateChanges) === null || _this$unsubscribeFrom2 === void 0 ? void 0 : _this$unsubscribeFrom2.call(this);
|
|
291
|
+
this.unsubscribeFromDisabledStateChanges = undefined;
|
|
292
|
+
this.subscribedProvider = undefined;
|
|
182
293
|
}
|
|
183
294
|
deselectNode() {
|
|
184
295
|
var _this$removeProfileCa;
|
|
@@ -17,7 +17,7 @@ export const ACTIONS = {
|
|
|
17
17
|
const AGENT_USER_TYPES = new Set(['APP', 'AGENT']);
|
|
18
18
|
const AI_STREAMING_TRANSFORMATION_META_KEY = 'isAIStreamingTransformation';
|
|
19
19
|
const PACKAGE_NAME = "@atlaskit/editor-plugin-mentions";
|
|
20
|
-
const PACKAGE_VERSION = "13.
|
|
20
|
+
const PACKAGE_VERSION = "13.2.0";
|
|
21
21
|
const setProvider = provider => (state, dispatch) => {
|
|
22
22
|
if (dispatch) {
|
|
23
23
|
dispatch(state.tr.setMeta(mentionPluginKey, {
|
|
@@ -14,6 +14,7 @@ import { IconMention } from '@atlaskit/editor-common/quick-insert';
|
|
|
14
14
|
import { isResolvingMentionProvider } from '@atlaskit/mention/resource';
|
|
15
15
|
import { MentionNameStatus, isPromise } from '@atlaskit/mention/types';
|
|
16
16
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
17
|
+
import { expVal } from '@atlaskit/tmp-editor-statsig/expVal';
|
|
17
18
|
import { insertMention } from './editor-commands';
|
|
18
19
|
import { mentionNodeSpec } from './nodeviews/mentionNodeSpec';
|
|
19
20
|
import { mentionPluginKey } from './pm-plugins/key';
|
|
@@ -187,6 +188,13 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
|
|
|
187
188
|
options.handleMentionsChanged(mentionChanges);
|
|
188
189
|
}
|
|
189
190
|
},
|
|
191
|
+
updateSectionTitle: function updateSectionTitle(props) {
|
|
192
|
+
var _api$typeAhead$action, _api$typeAhead2, _api$typeAhead2$updat;
|
|
193
|
+
if (!expVal('platform_editor_agent_mentions', 'isEnabled', false)) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return (_api$typeAhead$action = api === null || api === void 0 || (_api$typeAhead2 = api.typeAhead) === null || _api$typeAhead2 === void 0 || (_api$typeAhead2 = _api$typeAhead2.actions) === null || _api$typeAhead2 === void 0 || (_api$typeAhead2$updat = _api$typeAhead2.updateSectionTitle) === null || _api$typeAhead2$updat === void 0 ? void 0 : _api$typeAhead2$updat.call(_api$typeAhead2, props)) !== null && _api$typeAhead$action !== void 0 ? _api$typeAhead$action : false;
|
|
197
|
+
},
|
|
190
198
|
setProvider: function () {
|
|
191
199
|
var _setProvider = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(providerPromise) {
|
|
192
200
|
var _api$core$actions$exe;
|
|
@@ -255,13 +263,13 @@ var mentionsPlugin = function mentionsPlugin(_ref3) {
|
|
|
255
263
|
return /*#__PURE__*/React.createElement(IconMention, null);
|
|
256
264
|
},
|
|
257
265
|
action: function action(insert, state) {
|
|
258
|
-
var _api$
|
|
266
|
+
var _api$typeAhead3;
|
|
259
267
|
var tr = insert(undefined);
|
|
260
268
|
var pluginState = mentionPluginKey.getState(state);
|
|
261
269
|
if (pluginState && pluginState.canInsertMention === false) {
|
|
262
270
|
return false;
|
|
263
271
|
}
|
|
264
|
-
api === null || api === void 0 || (_api$
|
|
272
|
+
api === null || api === void 0 || (_api$typeAhead3 = api.typeAhead) === null || _api$typeAhead3 === void 0 || _api$typeAhead3.actions.openAtTransaction({
|
|
265
273
|
triggerHandler: typeAhead,
|
|
266
274
|
inputMethod: INPUT_METHOD.QUICK_INSERT
|
|
267
275
|
})(tr);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
._1e0cglyw{display:none}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/* disabledTooltipRenderer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
|
+
import "./disabledTooltipRenderer.compiled.css";
|
|
4
|
+
import { ax, ix } from "@compiled/react/runtime";
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
|
+
import { bindAll } from 'bind-event-listener';
|
|
7
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
|
|
8
|
+
import uuid from 'uuid/v4';
|
|
9
|
+
import Tooltip from '@atlaskit/tooltip';
|
|
10
|
+
var styles = {
|
|
11
|
+
hiddenTrigger: "_1e0cglyw"
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ADS `<Tooltip>` hands us a ref via its render-prop child. That ref may be
|
|
16
|
+
* either a callback ref or a mutable ref object — React supports both shapes
|
|
17
|
+
* and ADS's typing keeps both possible. This helper assigns the supplied
|
|
18
|
+
* element to whichever ref shape was provided so the tooltip ends up using
|
|
19
|
+
* the chip's bounding box for positioning and its DOM for trigger events.
|
|
20
|
+
*/
|
|
21
|
+
var assignRef = function assignRef(ref, element) {
|
|
22
|
+
if (typeof ref === 'function') {
|
|
23
|
+
ref(element);
|
|
24
|
+
} else if (ref) {
|
|
25
|
+
ref.current = element;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Names of the React-style trigger-prop handlers we forward from ADS
|
|
31
|
+
* `<Tooltip>` onto the chip element.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Maps each React-style trigger-prop handler ADS `<Tooltip>` hands us in its
|
|
36
|
+
* render-prop callback to the DOM event name we attach to the chip via
|
|
37
|
+
* `bind-event-listener`. The chip lives in the ProseMirror document and is
|
|
38
|
+
* not a React child of the tooltip, so we have to bridge React handlers to
|
|
39
|
+
* native event listeners ourselves.
|
|
40
|
+
*
|
|
41
|
+
* Names are listed in the same order ADS internally registers them.
|
|
42
|
+
*/
|
|
43
|
+
var TRIGGER_EVENT_MAP = [['onMouseOver', 'mouseover'], ['onMouseOut', 'mouseout'], ['onMouseMove', 'mousemove'], ['onMouseDown', 'mousedown'], ['onFocus', 'focusin'], ['onBlur', 'focusout']];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Anchors an ADS `<Tooltip>` to a ProseMirror chip element that is **not** a
|
|
47
|
+
* React child of the tooltip. The chip itself stays in the PM document; this
|
|
48
|
+
* renderer mounts an always-present React subtree via `portalProviderAPI` whose
|
|
49
|
+
* sole job is to host the tooltip and forward the ADS-provided trigger ref +
|
|
50
|
+
* event handlers onto the chip.
|
|
51
|
+
*
|
|
52
|
+
* The forwarding is deliberate: ADS `<Tooltip>` expects to attach its hover /
|
|
53
|
+
* focus / blur listeners to its render-prop child, but our render-prop child
|
|
54
|
+
* is a `display: none` placeholder span that no real event can reach. We bridge
|
|
55
|
+
* those listeners to the chip via `addEventListener` so the tooltip opens and
|
|
56
|
+
* closes in response to the user actually interacting with the chip — keyboard
|
|
57
|
+
* focus, mouse hover, screen-reader focus, the lot.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hook that mirrors ADS Tooltip's React trigger props onto a DOM element
|
|
62
|
+
* which is not a React child of the tooltip. Re-attaches whenever ADS hands
|
|
63
|
+
* us a fresh set of props (which happens on every render of the render-prop
|
|
64
|
+
* child) and cleans up on unmount.
|
|
65
|
+
*
|
|
66
|
+
* We use `bind-event-listener`'s `bindAll` rather than raw
|
|
67
|
+
* `addEventListener` / `removeEventListener` calls so the lifetime of every
|
|
68
|
+
* subscription is paired with a single `UnbindFn` — the AFM-mandated pattern
|
|
69
|
+
* for keeping listener bookkeeping leak-free.
|
|
70
|
+
*/
|
|
71
|
+
var useBridgedTriggerListeners = function useBridgedTriggerListeners(chip, triggerProps) {
|
|
72
|
+
useEffect(function () {
|
|
73
|
+
// Build the bindAll bindings array out of only the handlers ADS actually
|
|
74
|
+
// supplied. Each React handler is wrapped in a thin adapter so the
|
|
75
|
+
// listener signature matches the native `EventListener` shape; ADS
|
|
76
|
+
// handlers ignore the synthetic-event-only fields they don't use
|
|
77
|
+
// (target, currentTarget), so passing the raw DOM event through
|
|
78
|
+
// `unknown` is safe in practice.
|
|
79
|
+
var bindings = TRIGGER_EVENT_MAP.flatMap(function (_ref) {
|
|
80
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
81
|
+
propName = _ref2[0],
|
|
82
|
+
eventName = _ref2[1];
|
|
83
|
+
var handler = triggerProps[propName];
|
|
84
|
+
if (!handler) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
return [{
|
|
88
|
+
type: eventName,
|
|
89
|
+
listener: function listener(event) {
|
|
90
|
+
handler(event);
|
|
91
|
+
}
|
|
92
|
+
}];
|
|
93
|
+
});
|
|
94
|
+
if (bindings.length === 0) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
var unbind = bindAll(chip, bindings);
|
|
98
|
+
return unbind;
|
|
99
|
+
}, [chip, triggerProps]);
|
|
100
|
+
};
|
|
101
|
+
var AnchoredTooltip = function AnchoredTooltip(_ref3) {
|
|
102
|
+
var subscribe = _ref3.subscribe,
|
|
103
|
+
getInitialTooltip = _ref3.getInitialTooltip,
|
|
104
|
+
referenceElement = _ref3.referenceElement;
|
|
105
|
+
var _useState = useState(getInitialTooltip),
|
|
106
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
107
|
+
tooltip = _useState2[0],
|
|
108
|
+
setTooltipState = _useState2[1];
|
|
109
|
+
useEffect(function () {
|
|
110
|
+
return subscribe(setTooltipState);
|
|
111
|
+
}, [subscribe]);
|
|
112
|
+
if (!tooltip) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
116
|
+
content: tooltip,
|
|
117
|
+
position: "top"
|
|
118
|
+
}, function (tooltipProps) {
|
|
119
|
+
return /*#__PURE__*/React.createElement(TriggerBridge, {
|
|
120
|
+
referenceElement: referenceElement,
|
|
121
|
+
tooltipProps: tooltipProps
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Render-prop child for ADS `<Tooltip>`. The element it returns is a
|
|
128
|
+
* `display: none` placeholder that satisfies the render-prop API; the
|
|
129
|
+
* real trigger surface is the chip in the PM document, which receives
|
|
130
|
+
* both the ADS ref and the bridged event listeners via the side-effects
|
|
131
|
+
* declared on this component.
|
|
132
|
+
*/
|
|
133
|
+
var TriggerBridge = function TriggerBridge(_ref4) {
|
|
134
|
+
var referenceElement = _ref4.referenceElement,
|
|
135
|
+
tooltipProps = _ref4.tooltipProps;
|
|
136
|
+
useBridgedTriggerListeners(referenceElement, tooltipProps);
|
|
137
|
+
return /*#__PURE__*/React.createElement("span", {
|
|
138
|
+
ref: function ref() {
|
|
139
|
+
return assignRef(tooltipProps.ref, referenceElement);
|
|
140
|
+
},
|
|
141
|
+
"aria-hidden": "true",
|
|
142
|
+
className: ax([styles.hiddenTrigger])
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
export var disabledTooltipRenderer = function disabledTooltipRenderer(_ref5) {
|
|
146
|
+
var chipElement = _ref5.chipElement,
|
|
147
|
+
portalProviderAPI = _ref5.portalProviderAPI;
|
|
148
|
+
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- mirror existing renderer pattern
|
|
149
|
+
var key = uuid();
|
|
150
|
+
var currentTooltip;
|
|
151
|
+
var listeners = new Set();
|
|
152
|
+
var broadcast = function broadcast() {
|
|
153
|
+
listeners.forEach(function (listener) {
|
|
154
|
+
return listener(currentTooltip);
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
var getInitialTooltip = function getInitialTooltip() {
|
|
158
|
+
return currentTooltip;
|
|
159
|
+
};
|
|
160
|
+
var subscribe = function subscribe(listener) {
|
|
161
|
+
listeners.add(listener);
|
|
162
|
+
return function () {
|
|
163
|
+
listeners.delete(listener);
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
var renderElement = function renderElement() {
|
|
167
|
+
return /*#__PURE__*/React.createElement(AnchoredTooltip, {
|
|
168
|
+
referenceElement: chipElement,
|
|
169
|
+
getInitialTooltip: getInitialTooltip,
|
|
170
|
+
subscribe: subscribe
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
portalProviderAPI.render(renderElement, chipElement, key);
|
|
174
|
+
return {
|
|
175
|
+
setTooltip: function setTooltip(text) {
|
|
176
|
+
currentTooltip = text;
|
|
177
|
+
broadcast();
|
|
178
|
+
},
|
|
179
|
+
destroy: function destroy() {
|
|
180
|
+
portalProviderAPI.remove(key);
|
|
181
|
+
listeners.clear();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
};
|