@azure/communication-react 1.5.1-alpha-202306060014 → 1.5.1-alpha-202306080014
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/dist/communication-react.d.ts +17 -1
- package/dist/dist-cjs/communication-react/index.js +1627 -1506
- package/dist/dist-cjs/communication-react/index.js.map +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js +1 -1
- package/dist/dist-esm/acs-ui-common/src/telemetryVersion.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js +38 -1375
- package/dist/dist-esm/react-components/src/components/InputBoxComponent.js.map +1 -1
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.d.ts +41 -0
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js +554 -0
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/TextFieldWithMention.js.map +1 -0
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/mentionTagUtils.d.ts +167 -0
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/mentionTagUtils.js +780 -0
- package/dist/dist-esm/react-components/src/components/TextFieldWithMention/mentionTagUtils.js.map +1 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/CallComposite.js +6 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/CallComposite.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/Strings.d.ts +16 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/Strings.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js +8 -7
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/AzureCommunicationCallAdapter.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/CallAdapter.d.ts +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/adapter/CallAdapter.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/MediaGallery.js +4 -3
- package/dist/dist-esm/react-composites/src/composites/CallComposite/components/MediaGallery.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/TransferPage.d.ts +14 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/TransferPage.js +101 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/pages/TransferPage.js.map +1 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.d.ts +4 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.js +5 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/selectors/baseSelectors.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/TransferPage.styles.d.ts +26 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/TransferPage.styles.js +47 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/styles/TransferPage.styles.js.map +1 -0
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.d.ts +2 -2
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js +5 -1
- package/dist/dist-esm/react-composites/src/composites/CallComposite/utils/Utils.js.map +1 -1
- package/dist/dist-esm/react-composites/src/composites/localization/locales/en-US/strings.json +5 -1
- package/package.json +8 -8
@@ -167,7 +167,7 @@ const _toCommunicationIdentifier = (id) => {
|
|
167
167
|
// Copyright (c) Microsoft Corporation.
|
168
168
|
// Licensed under the MIT license.
|
169
169
|
// GENERATED FILE. DO NOT EDIT MANUALLY.
|
170
|
-
var telemetryVersion = '1.5.1-alpha-
|
170
|
+
var telemetryVersion = '1.5.1-alpha-202306080014';
|
171
171
|
|
172
172
|
// Copyright (c) Microsoft Corporation.
|
173
173
|
/**
|
@@ -5808,32 +5808,6 @@ const DEFAULT_COMPONENT_ICONS = {
|
|
5808
5808
|
ChangeSpokenLanguageIcon: React__default['default'].createElement(reactIcons.PersonVoice20Regular, null)
|
5809
5809
|
};
|
5810
5810
|
|
5811
|
-
// Copyright (c) Microsoft Corporation.
|
5812
|
-
/**
|
5813
|
-
* @internal
|
5814
|
-
* Announcer component to maker aria announcements on actions
|
5815
|
-
*/
|
5816
|
-
const Announcer$1 = (props) => {
|
5817
|
-
const { announcementString, ariaLive } = props;
|
5818
|
-
return React__default['default'].createElement(react.Stack, { "aria-label": announcementString, "aria-live": ariaLive, styles: announcerStyles });
|
5819
|
-
};
|
5820
|
-
/**
|
5821
|
-
* Styles to hide the announcer from view but still existing on the DOM tree it so that narration can happen.
|
5822
|
-
*/
|
5823
|
-
const announcerStyles = {
|
5824
|
-
root: {
|
5825
|
-
position: 'absolute',
|
5826
|
-
width: '1px',
|
5827
|
-
height: '1px',
|
5828
|
-
padding: 0,
|
5829
|
-
margin: '-1px',
|
5830
|
-
overflow: 'hidden',
|
5831
|
-
clip: 'rect(0,0,0,0)',
|
5832
|
-
whiteSpace: 'nowrap',
|
5833
|
-
border: 0
|
5834
|
-
}
|
5835
|
-
};
|
5836
|
-
|
5837
5811
|
// Copyright (c) Microsoft Corporation.
|
5838
5812
|
/**
|
5839
5813
|
* @private
|
@@ -5966,1605 +5940,1604 @@ const getPerceptualBrightnessOfHexColor = (hexColor) => {
|
|
5966
5940
|
|
5967
5941
|
// Copyright (c) Microsoft Corporation.
|
5968
5942
|
/**
|
5969
|
-
* @
|
5970
|
-
*
|
5971
|
-
*/
|
5972
|
-
const CHAT_CONTAINER_ZINDEX$1 = 1;
|
5973
|
-
/**
|
5974
|
-
* @private
|
5975
|
-
*/
|
5976
|
-
const mentionPopoverContainerStyle = (theme) => react.mergeStyles({
|
5977
|
-
boxShadow: theme.effects.elevation16,
|
5978
|
-
background: theme.semanticColors.bodyBackground,
|
5979
|
-
overflow: 'visible',
|
5980
|
-
// zIndex to set the mentionPopover above the chat container
|
5981
|
-
zIndex: CHAT_CONTAINER_ZINDEX$1 + 1
|
5982
|
-
});
|
5983
|
-
/**
|
5984
|
-
* @private
|
5943
|
+
* @internal
|
5944
|
+
* Announcer component to maker aria announcements on actions
|
5985
5945
|
*/
|
5986
|
-
const
|
5987
|
-
|
5988
|
-
|
5989
|
-
color: theme.palette.neutralSecondary,
|
5990
|
-
margin: '0.5rem 1rem 0.25rem',
|
5991
|
-
fontSize: theme.fonts.smallPlus.fontSize
|
5992
|
-
}
|
5993
|
-
};
|
5946
|
+
const Announcer$1 = (props) => {
|
5947
|
+
const { announcementString, ariaLive } = props;
|
5948
|
+
return React__default['default'].createElement(react.Stack, { "aria-label": announcementString, "aria-live": ariaLive, styles: announcerStyles });
|
5994
5949
|
};
|
5995
5950
|
/**
|
5996
|
-
*
|
5951
|
+
* Styles to hide the announcer from view but still existing on the DOM tree it so that narration can happen.
|
5997
5952
|
*/
|
5998
|
-
|
5999
|
-
|
6000
|
-
|
6001
|
-
|
6002
|
-
|
5953
|
+
const announcerStyles = {
|
5954
|
+
root: {
|
5955
|
+
position: 'absolute',
|
5956
|
+
width: '1px',
|
5957
|
+
height: '1px',
|
5958
|
+
padding: 0,
|
5959
|
+
margin: '-1px',
|
5960
|
+
overflow: 'hidden',
|
5961
|
+
clip: 'rect(0,0,0,0)',
|
5962
|
+
whiteSpace: 'nowrap',
|
5963
|
+
border: 0
|
5964
|
+
}
|
5965
|
+
};
|
5966
|
+
|
5967
|
+
// Copyright (c) Microsoft Corporation.
|
5968
|
+
// Licensed under the MIT license.
|
5969
|
+
const MSFT_MENTION_TAG = 'msft-mention';
|
6003
5970
|
/**
|
5971
|
+
* Get validated value for index between min and max values. If currentValue is not defined, -1 will be used instead.
|
5972
|
+
*
|
6004
5973
|
* @private
|
5974
|
+
* @param props - Props for finding a valid index in range.
|
5975
|
+
* @returns Valid index in the range.
|
6005
5976
|
*/
|
6006
|
-
const
|
6007
|
-
|
6008
|
-
|
6009
|
-
|
5977
|
+
const getValidatedIndexInRange = (props) => {
|
5978
|
+
const { min, max, currentValue } = props;
|
5979
|
+
let updatedValue = currentValue !== null && currentValue !== void 0 ? currentValue : -1;
|
5980
|
+
updatedValue = Math.max(min, updatedValue);
|
5981
|
+
updatedValue = Math.min(updatedValue, max);
|
5982
|
+
return updatedValue;
|
5983
|
+
};
|
6010
5984
|
/**
|
5985
|
+
* Find mention tag for selection if exists.
|
5986
|
+
*
|
6011
5987
|
* @private
|
5988
|
+
* @param tags - Existing list of tags.
|
5989
|
+
* @param selection - Selection index.
|
5990
|
+
* @returns Mention tag if exists, otherwise undefined.
|
6012
5991
|
*/
|
6013
|
-
const
|
6014
|
-
|
6015
|
-
|
6016
|
-
|
6017
|
-
|
5992
|
+
const findMentionTagForSelection = (tags, selection) => {
|
5993
|
+
let mentionTag = undefined;
|
5994
|
+
tags.every((tag) => {
|
5995
|
+
const closingTagInfo = getTagClosingTagInfo(tag);
|
5996
|
+
if (tag.plainTextBeginIndex !== undefined && tag.plainTextBeginIndex > selection) {
|
5997
|
+
// no need to check further as the selection is before the tag
|
5998
|
+
return false;
|
5999
|
+
}
|
6000
|
+
else if (tag.plainTextBeginIndex !== undefined &&
|
6001
|
+
tag.plainTextBeginIndex <= selection &&
|
6002
|
+
selection <= closingTagInfo.plainTextEndIndex) {
|
6003
|
+
// no need to check if tag doesn't contain selection
|
6004
|
+
if (tag.subTags !== undefined && tag.subTags.length !== 0) {
|
6005
|
+
const selectedTag = findMentionTagForSelection(tag.subTags, selection);
|
6006
|
+
if (selectedTag !== undefined) {
|
6007
|
+
mentionTag = selectedTag;
|
6008
|
+
return false;
|
6009
|
+
}
|
6010
|
+
}
|
6011
|
+
else if (tag.tagType === MSFT_MENTION_TAG) {
|
6012
|
+
mentionTag = tag;
|
6013
|
+
return false;
|
6014
|
+
}
|
6018
6015
|
}
|
6016
|
+
return true;
|
6019
6017
|
});
|
6018
|
+
return mentionTag;
|
6020
6019
|
};
|
6021
6020
|
/**
|
6021
|
+
* Get the indices of the word for the selection.
|
6022
6022
|
* @private
|
6023
|
+
*
|
6023
6024
|
*/
|
6024
|
-
const
|
6025
|
-
|
6026
|
-
|
6027
|
-
|
6028
|
-
|
6029
|
-
|
6030
|
-
|
6031
|
-
|
6032
|
-
|
6025
|
+
const rangeOfWordInSelection = ({ textInput, selectionStart, selectionEnd, tag }) => {
|
6026
|
+
var _a;
|
6027
|
+
if (tag.plainTextBeginIndex === undefined) {
|
6028
|
+
return { start: selectionStart, end: selectionEnd === undefined ? selectionStart : selectionEnd };
|
6029
|
+
}
|
6030
|
+
// Look at start word index and optionally end word index.
|
6031
|
+
// Select combination of the two and return the range.
|
6032
|
+
let start = selectionStart;
|
6033
|
+
let end = selectionEnd === undefined ? selectionStart : selectionEnd;
|
6034
|
+
const firstWordStartIndex = textInput.lastIndexOf(' ', selectionStart);
|
6035
|
+
if (firstWordStartIndex === tag.plainTextBeginIndex) {
|
6036
|
+
start = firstWordStartIndex;
|
6037
|
+
}
|
6038
|
+
else {
|
6039
|
+
start = Math.max(firstWordStartIndex + 1, tag.plainTextBeginIndex);
|
6040
|
+
}
|
6041
|
+
const firstWordEndIndex = textInput.indexOf(' ', selectionStart);
|
6042
|
+
end = Math.max(firstWordEndIndex + 1, (_a = tag.plainTextEndIndex) !== null && _a !== void 0 ? _a : firstWordEndIndex + 1);
|
6043
|
+
if (selectionEnd !== undefined && tag.plainTextEndIndex !== undefined) {
|
6044
|
+
const lastWordEndIndex = textInput.indexOf(' ', selectionEnd);
|
6045
|
+
end = Math.max(lastWordEndIndex > -1 ? lastWordEndIndex : tag.plainTextEndIndex, selectionEnd);
|
6046
|
+
}
|
6047
|
+
return { start, end };
|
6033
6048
|
};
|
6034
|
-
|
6035
|
-
// Copyright (c) Microsoft Corporation.
|
6036
6049
|
/**
|
6037
|
-
*
|
6050
|
+
* Find a new the selection index.
|
6038
6051
|
*
|
6039
|
-
* @
|
6052
|
+
* @private
|
6053
|
+
* @param props - Props for finding new selection index for mention.
|
6054
|
+
* @returns New selection index if it is inside of a mention tag, otherwise the current selection.
|
6040
6055
|
*/
|
6041
|
-
const
|
6042
|
-
|
6043
|
-
const
|
6044
|
-
|
6045
|
-
|
6046
|
-
|
6047
|
-
|
6048
|
-
|
6049
|
-
|
6050
|
-
|
6051
|
-
|
6052
|
-
|
6053
|
-
|
6054
|
-
|
6055
|
-
|
6056
|
-
|
6057
|
-
|
6058
|
-
if (changedSelection === undefined) {
|
6059
|
-
setChangedSelection(false);
|
6056
|
+
const findNewSelectionIndexForMention = (props) => {
|
6057
|
+
var _a;
|
6058
|
+
const { tag, textValue, currentSelectionIndex, previousSelectionIndex } = props;
|
6059
|
+
// check if this is a mention tag and selection should be updated
|
6060
|
+
if (tag.tagType !== MSFT_MENTION_TAG ||
|
6061
|
+
tag.plainTextBeginIndex === undefined ||
|
6062
|
+
currentSelectionIndex === previousSelectionIndex ||
|
6063
|
+
tag.plainTextEndIndex === undefined) {
|
6064
|
+
return currentSelectionIndex;
|
6065
|
+
}
|
6066
|
+
let spaceIndex = 0;
|
6067
|
+
if (currentSelectionIndex <= previousSelectionIndex) {
|
6068
|
+
// the cursor is moved to the left, find the last index before the cursor
|
6069
|
+
spaceIndex = textValue.lastIndexOf(' ', currentSelectionIndex !== null && currentSelectionIndex !== void 0 ? currentSelectionIndex : 0);
|
6070
|
+
if (spaceIndex === -1) {
|
6071
|
+
// no space before the selection, use the beginning of the tag
|
6072
|
+
spaceIndex = tag.plainTextBeginIndex;
|
6060
6073
|
}
|
6061
|
-
|
6062
|
-
|
6074
|
+
}
|
6075
|
+
else {
|
6076
|
+
// the cursor is moved to the right, find the fist index after the cursor
|
6077
|
+
spaceIndex = textValue.indexOf(' ', currentSelectionIndex !== null && currentSelectionIndex !== void 0 ? currentSelectionIndex : 0);
|
6078
|
+
if (spaceIndex === -1) {
|
6079
|
+
// no space after the selection, use the end of the tag
|
6080
|
+
spaceIndex = (_a = tag.plainTextEndIndex) !== null && _a !== void 0 ? _a : tag.plainTextBeginIndex;
|
6063
6081
|
}
|
6064
|
-
}
|
6065
|
-
|
6066
|
-
|
6067
|
-
|
6068
|
-
|
6082
|
+
}
|
6083
|
+
spaceIndex = Math.max(tag.plainTextBeginIndex, spaceIndex);
|
6084
|
+
spaceIndex = Math.min(tag.plainTextEndIndex, spaceIndex);
|
6085
|
+
return spaceIndex;
|
6086
|
+
};
|
6087
|
+
/**
|
6088
|
+
* Handle mention tag edit and by word deleting
|
6089
|
+
*
|
6090
|
+
* @private
|
6091
|
+
* @param props - Props for mention update HTML function.
|
6092
|
+
* @returns Updated texts and indexes.
|
6093
|
+
*/
|
6094
|
+
const handleMentionTagUpdate = (props) => {
|
6095
|
+
const { htmlText, oldPlainText, change, tag, closeTagIdx, closeTagLength, plainTextEndIndex, startIndex, oldPlainTextEndIndex, mentionTagLength } = props;
|
6096
|
+
let processedChange = props.processedChange;
|
6097
|
+
let lastProcessedHTMLIndex = props.lastProcessedHTMLIndex;
|
6098
|
+
if (tag.tagType !== MSFT_MENTION_TAG || tag.plainTextBeginIndex === undefined) {
|
6099
|
+
// not a mention tag
|
6100
|
+
return {
|
6101
|
+
result: '',
|
6102
|
+
updatedChange: processedChange,
|
6103
|
+
htmlIndex: lastProcessedHTMLIndex,
|
6104
|
+
plainTextSelectionEndIndex: undefined
|
6069
6105
|
};
|
6070
|
-
}
|
6071
|
-
|
6072
|
-
|
6073
|
-
|
6074
|
-
|
6075
|
-
|
6076
|
-
|
6077
|
-
|
6078
|
-
|
6079
|
-
|
6080
|
-
|
6081
|
-
|
6082
|
-
|
6083
|
-
|
6106
|
+
}
|
6107
|
+
let result = '';
|
6108
|
+
let plainTextSelectionEndIndex;
|
6109
|
+
let rangeStart;
|
6110
|
+
let rangeEnd;
|
6111
|
+
// check if space symbol is handled in case if string looks like '<1 2 3>'
|
6112
|
+
let isSpaceLengthHandled = false;
|
6113
|
+
rangeStart = oldPlainText.lastIndexOf(' ', startIndex);
|
6114
|
+
if (rangeStart !== -1 && rangeStart !== undefined && rangeStart > tag.plainTextBeginIndex) {
|
6115
|
+
isSpaceLengthHandled = true;
|
6116
|
+
}
|
6117
|
+
rangeEnd = oldPlainText.indexOf(' ', oldPlainTextEndIndex);
|
6118
|
+
if (rangeEnd === -1 || rangeEnd === undefined) {
|
6119
|
+
// check if space symbol is not found
|
6120
|
+
rangeEnd = plainTextEndIndex;
|
6121
|
+
}
|
6122
|
+
else if (!isSpaceLengthHandled) {
|
6123
|
+
// +1 to include the space symbol
|
6124
|
+
rangeEnd += 1;
|
6125
|
+
}
|
6126
|
+
isSpaceLengthHandled = true;
|
6127
|
+
if (rangeStart === -1 || rangeStart === undefined || rangeStart < tag.plainTextBeginIndex) {
|
6128
|
+
// rangeStart should be at least equal to tag.plainTextBeginIndex
|
6129
|
+
rangeStart = tag.plainTextBeginIndex;
|
6130
|
+
}
|
6131
|
+
if (rangeEnd > plainTextEndIndex) {
|
6132
|
+
// rangeEnd should be at most equal to plainTextEndIndex
|
6133
|
+
rangeEnd = plainTextEndIndex;
|
6134
|
+
}
|
6135
|
+
if (rangeStart === tag.plainTextBeginIndex && rangeEnd === plainTextEndIndex) {
|
6136
|
+
// the whole tag should be removed
|
6137
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
6138
|
+
plainTextSelectionEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
6139
|
+
processedChange = '';
|
6140
|
+
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
6141
|
+
}
|
6142
|
+
else {
|
6143
|
+
// only part of the tag should be removed
|
6144
|
+
let startChangeDiff = 0;
|
6145
|
+
let endChangeDiff = 0;
|
6146
|
+
// need to check only rangeStart > tag.plainTextBeginIndex as when rangeStart === tag.plainTextBeginIndex startChangeDiff = 0 and mentionTagLength shouldn't be subtracted
|
6147
|
+
if (rangeStart > tag.plainTextBeginIndex) {
|
6148
|
+
startChangeDiff = rangeStart - tag.plainTextBeginIndex - mentionTagLength;
|
6084
6149
|
}
|
6085
|
-
|
6086
|
-
|
6150
|
+
endChangeDiff = rangeEnd - tag.plainTextBeginIndex - mentionTagLength;
|
6151
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff);
|
6152
|
+
if (startIndex < tag.plainTextBeginIndex) {
|
6153
|
+
// if the change is before the tag, the selection should start from startIndex (rangeStart will be equal to tag.plainTextBeginIndex)
|
6154
|
+
plainTextSelectionEndIndex = startIndex + change.length;
|
6087
6155
|
}
|
6088
6156
|
else {
|
6089
|
-
//
|
6090
|
-
|
6091
|
-
}
|
6092
|
-
setPosition(finalPosition);
|
6093
|
-
}, [location, target, targetPositionOffset]);
|
6094
|
-
const handleOnKeyDown = React.useCallback((e) => {
|
6095
|
-
switch (e.key) {
|
6096
|
-
case 'Escape':
|
6097
|
-
onDismiss && onDismiss();
|
6098
|
-
break;
|
6099
|
-
}
|
6100
|
-
}, [onDismiss]);
|
6101
|
-
const personaRenderer = React.useCallback((displayName) => {
|
6102
|
-
const displayNamePlaceholder = localeStrings.participantItem.displayNamePlaceholder;
|
6103
|
-
const avatarOptions = {
|
6104
|
-
text: (displayName === null || displayName === void 0 ? void 0 : displayName.trim()) || displayNamePlaceholder,
|
6105
|
-
size: react.PersonaSize.size24,
|
6106
|
-
initialsColor: theme.palette.neutralLight,
|
6107
|
-
initialsTextColor: theme.palette.neutralSecondary,
|
6108
|
-
showOverflowTooltip: false,
|
6109
|
-
showUnknownPersonaCoin: !(displayName === null || displayName === void 0 ? void 0 : displayName.trim()) || displayName === displayNamePlaceholder
|
6110
|
-
};
|
6111
|
-
return React__default['default'].createElement(react.Persona, Object.assign({}, avatarOptions));
|
6112
|
-
}, [localeStrings, theme]);
|
6113
|
-
const defaultOnRenderSuggestionItem = React.useCallback((suggestion, onSuggestionSelected, active) => {
|
6114
|
-
return (React__default['default'].createElement("div", { "data-is-focusable": true, "data-ui-id": ids.mentionSuggestionItem, key: suggestion.id, onClick: () => onSuggestionSelected(suggestion), onMouseEnter: () => setHoveredSuggestion(suggestion), onMouseLeave: () => setHoveredSuggestion(undefined), onKeyDown: (e) => {
|
6115
|
-
handleOnKeyDown(e);
|
6116
|
-
}, className: suggestionItemWrapperStyle(theme) },
|
6117
|
-
React__default['default'].createElement(react.Stack, { horizontal: true, className: suggestionItemStackStyle(theme, (hoveredSuggestion === null || hoveredSuggestion === void 0 ? void 0 : hoveredSuggestion.id) === suggestion.id, (changedSelection !== null && changedSelection !== void 0 ? changedSelection : false) && active) }, personaRenderer(suggestion.displayText))));
|
6118
|
-
}, [
|
6119
|
-
handleOnKeyDown,
|
6120
|
-
theme,
|
6121
|
-
/* @conditional-compile-remove(mention) */
|
6122
|
-
ids,
|
6123
|
-
hoveredSuggestion,
|
6124
|
-
changedSelection,
|
6125
|
-
personaRenderer
|
6126
|
-
]);
|
6127
|
-
const getHeaderTitle = React.useCallback(() => {
|
6128
|
-
if (title) {
|
6129
|
-
return title;
|
6157
|
+
// if the change is inside the tag, the selection should start with rangeStart
|
6158
|
+
plainTextSelectionEndIndex = rangeStart + processedChange.length;
|
6130
6159
|
}
|
6131
|
-
|
6132
|
-
|
6133
|
-
}
|
6134
|
-
return
|
6135
|
-
React__default['default'].createElement(react.Stack, { className: react.mergeStyles({
|
6136
|
-
maxHeight: 212,
|
6137
|
-
maxWidth: position.maxWidth
|
6138
|
-
}, mentionPopoverContainerStyle(theme), Object.assign(Object.assign({}, position), { position: 'absolute' })) },
|
6139
|
-
React__default['default'].createElement(react.Stack.Item, { styles: headerStyleThemed(theme), "aria-label": title }, getHeaderTitle()),
|
6140
|
-
React__default['default'].createElement(react.Stack
|
6141
|
-
/* @conditional-compile-remove(mention) */
|
6142
|
-
, { "data-ui-id": ids.mentionSuggestionList, className: suggestionListStyle }, suggestions.map((suggestion, index) => {
|
6143
|
-
const active = index === activeSuggestionIndex;
|
6144
|
-
return onRenderSuggestionItem
|
6145
|
-
? onRenderSuggestionItem(suggestion, onSuggestionSelected, active)
|
6146
|
-
: defaultOnRenderSuggestionItem(suggestion, onSuggestionSelected, active);
|
6147
|
-
})))));
|
6160
|
+
lastProcessedHTMLIndex = tag.openTagIndex + tag.openTagBody.length + endChangeDiff;
|
6161
|
+
// processed change should not be changed as it should be added after the tag
|
6162
|
+
}
|
6163
|
+
return { result, updatedChange: processedChange, htmlIndex: lastProcessedHTMLIndex, plainTextSelectionEndIndex };
|
6148
6164
|
};
|
6149
|
-
|
6150
|
-
|
6151
|
-
|
6152
|
-
|
6153
|
-
|
6154
|
-
|
6155
|
-
|
6156
|
-
|
6157
|
-
|
6158
|
-
|
6159
|
-
|
6165
|
+
/**
|
6166
|
+
* Get closing tag information if exists otherwise return information as for self closing tag
|
6167
|
+
*
|
6168
|
+
* @private
|
6169
|
+
* @param tag - Tag data.
|
6170
|
+
* @returns Closing tag information for the provided tag.
|
6171
|
+
*/
|
6172
|
+
const getTagClosingTagInfo = (tag) => {
|
6173
|
+
let plainTextEndIndex = 0;
|
6174
|
+
let closeTagIdx = 0;
|
6175
|
+
let closeTagLength = 0;
|
6176
|
+
if (tag.plainTextEndIndex !== undefined && tag.closingTagIndex !== undefined) {
|
6177
|
+
// close tag exists
|
6178
|
+
plainTextEndIndex = tag.plainTextEndIndex;
|
6179
|
+
closeTagIdx = tag.closingTagIndex;
|
6180
|
+
// tag.tagType.length + </>
|
6181
|
+
closeTagLength = tag.tagType.length + 3;
|
6182
|
+
}
|
6183
|
+
else if (tag.plainTextBeginIndex !== undefined) {
|
6184
|
+
// no close tag
|
6185
|
+
plainTextEndIndex = tag.plainTextBeginIndex;
|
6186
|
+
closeTagIdx = tag.openTagIndex + tag.openTagBody.length;
|
6187
|
+
closeTagLength = 0;
|
6188
|
+
}
|
6189
|
+
return { plainTextEndIndex, closeTagIdx, closeTagLength };
|
6160
6190
|
};
|
6161
|
-
/* @conditional-compile-remove(mention) */
|
6162
|
-
const DEFAULT_MENTION_TRIGGER = '@';
|
6163
|
-
/* @conditional-compile-remove(mention) */
|
6164
|
-
const MSFT_MENTION_TAG = 'msft-mention';
|
6165
6191
|
/**
|
6192
|
+
* Go through the text and update it with the changed text
|
6193
|
+
*
|
6166
6194
|
* @private
|
6195
|
+
* @param props - Props for update HTML function.
|
6196
|
+
* @returns Updated HTML and selection index if the selection index should be set.
|
6167
6197
|
*/
|
6168
|
-
const
|
6169
|
-
const {
|
6170
|
-
|
6171
|
-
|
6172
|
-
|
6173
|
-
|
6174
|
-
|
6175
|
-
|
6176
|
-
|
6177
|
-
//
|
6178
|
-
|
6179
|
-
|
6180
|
-
//
|
6181
|
-
|
6182
|
-
|
6183
|
-
|
6184
|
-
|
6185
|
-
|
6186
|
-
|
6187
|
-
|
6188
|
-
|
6189
|
-
|
6190
|
-
|
6191
|
-
const [selectionEndValue, setSelectionEndValue] = React.useState();
|
6192
|
-
/* @conditional-compile-remove(mention) */
|
6193
|
-
// Boolean value to check if onMouseDown event should be handled during select as selection range
|
6194
|
-
// for onMouseDown event is not updated yet and the selection range for mouse click/taps will be
|
6195
|
-
// updated in onSelect event if needed.
|
6196
|
-
const [shouldHandleOnMouseDownDuringSelect, setShouldHandleOnMouseDownDuringSelect] = React.useState(true);
|
6197
|
-
/* @conditional-compile-remove(mention) */
|
6198
|
-
// Point of start of touch/mouse selection
|
6199
|
-
const [interactionStartPoint, setInteractionStartPoint] = React.useState();
|
6200
|
-
/* @conditional-compile-remove(mention) */
|
6201
|
-
// Target selection from mouse movement
|
6202
|
-
const [targetSelection, setTargetSelection] = React.useState();
|
6203
|
-
/* @conditional-compile-remove(mention) */
|
6204
|
-
// Caret position in the text field
|
6205
|
-
const [caretPosition, setCaretPosition] = React.useState(undefined);
|
6206
|
-
/* @conditional-compile-remove(mention) */
|
6207
|
-
// Index of where the caret is in the text field
|
6208
|
-
const [caretIndex, setCaretIndex] = React.useState(undefined);
|
6209
|
-
/* @conditional-compile-remove(mention) */
|
6210
|
-
const localeStrings = useLocale$1().strings;
|
6211
|
-
/* @conditional-compile-remove(mention) */
|
6212
|
-
// Set mention suggestions
|
6213
|
-
const updateMentionSuggestions = React.useCallback((suggestions) => {
|
6214
|
-
setMentionSuggestions(suggestions);
|
6215
|
-
}, [setMentionSuggestions]);
|
6216
|
-
/* @conditional-compile-remove(mention) */
|
6217
|
-
// Parse the text and get the plain text version to display in the input box
|
6218
|
-
React.useEffect(() => {
|
6219
|
-
const trigger = (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) || DEFAULT_MENTION_TRIGGER;
|
6220
|
-
const parsedHTMLData = textToTagParser(textValue, trigger);
|
6221
|
-
setInputTextValue(parsedHTMLData.plainText);
|
6222
|
-
setTagsValue(parsedHTMLData.tags);
|
6223
|
-
updateMentionSuggestions([]);
|
6224
|
-
}, [textValue, mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger, updateMentionSuggestions]);
|
6225
|
-
const mergedRootStyle = react.mergeStyles(inputBoxWrapperStyle, styles === null || styles === void 0 ? void 0 : styles.root);
|
6226
|
-
const mergedInputFieldStyle = react.mergeStyles(inputBoxStyle, inputClassName, props.inlineChildren ? {} : inputBoxNewLineSpaceAffordance);
|
6227
|
-
/* @conditional-compile-remove(mention) */
|
6228
|
-
React.useEffect(() => {
|
6229
|
-
var _a;
|
6230
|
-
// effect for caret index update
|
6231
|
-
if (caretIndex === undefined || textFieldRef === undefined || (textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === undefined) {
|
6232
|
-
return;
|
6198
|
+
const updateHTML = (props) => {
|
6199
|
+
const { htmlText, oldPlainText, newPlainText, tags, startIndex, oldPlainTextEndIndex, change, mentionTrigger } = props;
|
6200
|
+
if (tags.length === 0 || (startIndex === 0 && oldPlainTextEndIndex === oldPlainText.length - 1)) {
|
6201
|
+
// no tags added yet or the whole text is changed
|
6202
|
+
return { updatedHTML: newPlainText, updatedSelectionIndex: undefined };
|
6203
|
+
}
|
6204
|
+
let result = '';
|
6205
|
+
let lastProcessedHTMLIndex = 0;
|
6206
|
+
// the value can be updated with empty string when the change covers more than 1 place (tag + before or after the tag)
|
6207
|
+
// in this case change won't be added as part of the tag
|
6208
|
+
// e.g.: change is before and partially in tag => change will be added before the tag and outdated text in the tag will be removed
|
6209
|
+
// e.g.: change is after and partially in tag => change will be added after the tag and outdated text in the tag will be removed
|
6210
|
+
// e.g.: change is on the beginning of the tag => change will be added before the tag
|
6211
|
+
// e.g.: change is on the end of the tag => change will be added to the tag if it's not mention and after the tag if it's mention
|
6212
|
+
let processedChange = change;
|
6213
|
+
// end tag plain text index of the last processed tag
|
6214
|
+
let lastProcessedPlainTextTagEndIndex = 0;
|
6215
|
+
// as some tags/text can be removed fully, selection should be updated correctly
|
6216
|
+
let changeNewEndIndex;
|
6217
|
+
for (let i = 0; i < tags.length; i++) {
|
6218
|
+
const tag = tags[i];
|
6219
|
+
if (tag.plainTextBeginIndex === undefined) {
|
6220
|
+
continue;
|
6233
6221
|
}
|
6234
|
-
//
|
6235
|
-
|
6236
|
-
|
6237
|
-
|
6238
|
-
|
6239
|
-
|
6240
|
-
|
6241
|
-
|
6242
|
-
setSelectionEndValue(updatedCaretIndex);
|
6243
|
-
}, [caretIndex, inputTextValue.length, textFieldRef, setSelectionStartValue, setSelectionEndValue]);
|
6244
|
-
const mergedTextContainerStyle = react.mergeStyles(textContainerStyle, styles === null || styles === void 0 ? void 0 : styles.textFieldContainer);
|
6245
|
-
const mergedTextFieldStyle = react.concatStyleSets(textFieldStyle, {
|
6246
|
-
fieldGroup: styles === null || styles === void 0 ? void 0 : styles.textField,
|
6247
|
-
errorMessage: styles === null || styles === void 0 ? void 0 : styles.systemMessage,
|
6248
|
-
suffix: {
|
6249
|
-
backgroundColor: 'transparent',
|
6250
|
-
// Remove empty space in the suffix area when adding newline-style buttons
|
6251
|
-
display: props.inlineChildren ? 'flex' : 'contents',
|
6252
|
-
padding: '0 0.25rem'
|
6253
|
-
}
|
6254
|
-
});
|
6255
|
-
const mergedChildrenStyle = react.mergeStyles(props.inlineChildren ? {} : newLineButtonsContainerStyle);
|
6256
|
-
/* @conditional-compile-remove(mention) */
|
6257
|
-
const onSuggestionSelected = React.useCallback((suggestion) => {
|
6258
|
-
var _a, _b, _c;
|
6259
|
-
let selectionEnd = ((_a = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _a === void 0 ? void 0 : _a.selectionEnd) || -1;
|
6260
|
-
if (selectionEnd < 0) {
|
6261
|
-
selectionEnd = 0;
|
6262
|
-
}
|
6263
|
-
else if (selectionEnd > inputTextValue.length) {
|
6264
|
-
selectionEnd = inputTextValue.length;
|
6265
|
-
}
|
6266
|
-
const oldPlainText = inputTextValue;
|
6267
|
-
const mention = htmlStringForMentionSuggestion(suggestion, localeStrings);
|
6268
|
-
// update plain text with the mention html text
|
6269
|
-
const newPlainText = inputTextValue.substring(0, currentTriggerStartIndex) + mention + inputTextValue.substring(selectionEnd);
|
6270
|
-
const triggerText = (_b = mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) !== null && _b !== void 0 ? _b : DEFAULT_MENTION_TRIGGER;
|
6271
|
-
// update html text with updated plain text
|
6272
|
-
const updatedContent = updateHTML({
|
6273
|
-
htmlText: textValue,
|
6274
|
-
oldPlainText,
|
6275
|
-
newPlainText,
|
6276
|
-
tags: tagsValue,
|
6277
|
-
startIndex: currentTriggerStartIndex,
|
6278
|
-
oldPlainTextEndIndex: selectionEnd,
|
6279
|
-
change: mention,
|
6280
|
-
mentionTrigger: triggerText
|
6281
|
-
});
|
6282
|
-
const displayName = getDisplayNameForMentionSuggestion(suggestion, localeStrings);
|
6283
|
-
const newCaretIndex = currentTriggerStartIndex + displayName.length + triggerText.length;
|
6284
|
-
// move the caret in the text field to the end of the mention plain text
|
6285
|
-
setCaretIndex(newCaretIndex);
|
6286
|
-
setSelectionEndValue(newCaretIndex);
|
6287
|
-
setSelectionStartValue(newCaretIndex);
|
6288
|
-
setCurrentTriggerStartIndex(-1);
|
6289
|
-
updateMentionSuggestions([]);
|
6290
|
-
// set focus back to text field
|
6291
|
-
(_c = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _c === void 0 ? void 0 : _c.focus();
|
6292
|
-
setActiveSuggestionIndex(undefined);
|
6293
|
-
onChange && onChange(undefined, updatedContent.updatedHTML);
|
6294
|
-
}, [
|
6295
|
-
textFieldRef,
|
6296
|
-
inputTextValue,
|
6297
|
-
currentTriggerStartIndex,
|
6298
|
-
mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger,
|
6299
|
-
onChange,
|
6300
|
-
textValue,
|
6301
|
-
tagsValue,
|
6302
|
-
/* @conditional-compile-remove(mention) */
|
6303
|
-
updateMentionSuggestions,
|
6304
|
-
/* @conditional-compile-remove(mention) */
|
6305
|
-
localeStrings
|
6306
|
-
]);
|
6307
|
-
const onTextFieldKeyDown = React.useCallback((ev) => {
|
6308
|
-
/* @conditional-compile-remove(mention) */
|
6309
|
-
// caretIndex should be set to undefined when the user is typing
|
6310
|
-
setCaretIndex(undefined);
|
6311
|
-
// shouldHandleOnMouseDownDuringSelect should be set to false after the last mouse down event.
|
6312
|
-
// it shouldn't be updated in onMouseUp
|
6313
|
-
// as onMouseUp can be triggered before or after onSelect event
|
6314
|
-
// because its order depends on mouse events not selection.
|
6315
|
-
/* @conditional-compile-remove(mention) */
|
6316
|
-
setShouldHandleOnMouseDownDuringSelect(false);
|
6317
|
-
if (isEnterKeyEventFromCompositionSession(ev)) {
|
6318
|
-
return;
|
6222
|
+
// all plain text indexes includes trigger length for the mention that shouldn't be included in
|
6223
|
+
// htmlText.substring because html strings don't include the trigger
|
6224
|
+
// mentionTagLength will be set only for mention tag, otherwise should be 0
|
6225
|
+
let mentionTagLength = 0;
|
6226
|
+
let isMentionTag = false;
|
6227
|
+
if (tag.tagType === MSFT_MENTION_TAG) {
|
6228
|
+
mentionTagLength = mentionTrigger.length;
|
6229
|
+
isMentionTag = true;
|
6319
6230
|
}
|
6320
|
-
|
6321
|
-
|
6322
|
-
|
6323
|
-
|
6324
|
-
|
6325
|
-
|
6326
|
-
|
6327
|
-
|
6328
|
-
|
6329
|
-
|
6330
|
-
|
6331
|
-
|
6332
|
-
|
6333
|
-
: Math.min(activeSuggestionIndex + 1, mentionSuggestions.length - 1);
|
6334
|
-
setActiveSuggestionIndex(newActiveIndex);
|
6231
|
+
if (startIndex <= tag.plainTextBeginIndex) {
|
6232
|
+
// change start is before the open tag
|
6233
|
+
// Math.max(lastProcessedPlainTextTagEndIndex, startIndex) is used as startIndex may not be in [[previous tag].plainTextEndIndex - tag.plainTextBeginIndex] range
|
6234
|
+
const startChangeDiff = tag.plainTextBeginIndex - Math.max(lastProcessedPlainTextTagEndIndex, startIndex);
|
6235
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex - startChangeDiff) + processedChange;
|
6236
|
+
processedChange = '';
|
6237
|
+
if (oldPlainTextEndIndex <= tag.plainTextBeginIndex) {
|
6238
|
+
// the whole change is before tag start
|
6239
|
+
// mentionTag length can be ignored here as the change is before the tag
|
6240
|
+
const endChangeDiff = tag.plainTextBeginIndex - oldPlainTextEndIndex;
|
6241
|
+
lastProcessedHTMLIndex = tag.openTagIndex - endChangeDiff;
|
6242
|
+
// the change is handled; exit
|
6243
|
+
break;
|
6335
6244
|
}
|
6336
|
-
else
|
6337
|
-
|
6245
|
+
else {
|
6246
|
+
// change continues in the tag
|
6247
|
+
lastProcessedHTMLIndex = tag.openTagIndex;
|
6248
|
+
// proceed to the next check
|
6338
6249
|
}
|
6339
6250
|
}
|
6340
|
-
|
6341
|
-
|
6342
|
-
//
|
6343
|
-
|
6344
|
-
|
6345
|
-
|
6346
|
-
|
6347
|
-
|
6348
|
-
|
6251
|
+
const closingTagInfo = getTagClosingTagInfo(tag);
|
6252
|
+
if (startIndex <= closingTagInfo.plainTextEndIndex) {
|
6253
|
+
// change started before the end tag
|
6254
|
+
if (startIndex <= tag.plainTextBeginIndex && oldPlainTextEndIndex === closingTagInfo.plainTextEndIndex) {
|
6255
|
+
// the change is a tag or starts before the tag
|
6256
|
+
// tag should be removed, no matter if there are sub-tags
|
6257
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
6258
|
+
processedChange = '';
|
6259
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
6260
|
+
// the change is handled; exit
|
6261
|
+
break;
|
6262
|
+
}
|
6263
|
+
else if (startIndex >= tag.plainTextBeginIndex && oldPlainTextEndIndex <= closingTagInfo.plainTextEndIndex) {
|
6264
|
+
// the change is between the tag
|
6265
|
+
if (isMentionTag) {
|
6266
|
+
if (change !== '') {
|
6267
|
+
if (startIndex !== tag.plainTextBeginIndex && startIndex !== closingTagInfo.plainTextEndIndex) {
|
6268
|
+
// mention tag should be deleted when user tries to edit it in the middle
|
6269
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
6270
|
+
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
6271
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
6272
|
+
}
|
6273
|
+
else if (startIndex === tag.plainTextBeginIndex) {
|
6274
|
+
// non empty change at the beginning of the mention tag to be added before the mention tag
|
6275
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
6276
|
+
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
6277
|
+
lastProcessedHTMLIndex = tag.openTagIndex;
|
6278
|
+
}
|
6279
|
+
else if (startIndex === closingTagInfo.plainTextEndIndex) {
|
6280
|
+
// non empty change at the end of the mention tag to be added after the mention tag
|
6281
|
+
result +=
|
6282
|
+
htmlText.substring(lastProcessedHTMLIndex, closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength) +
|
6283
|
+
processedChange;
|
6284
|
+
changeNewEndIndex = closingTagInfo.plainTextEndIndex + processedChange.length;
|
6285
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
6286
|
+
}
|
6287
|
+
processedChange = '';
|
6288
|
+
}
|
6289
|
+
else {
|
6290
|
+
const updateMentionTagResult = handleMentionTagUpdate({
|
6291
|
+
htmlText,
|
6292
|
+
oldPlainText,
|
6293
|
+
lastProcessedHTMLIndex,
|
6294
|
+
processedChange,
|
6295
|
+
change,
|
6296
|
+
tag,
|
6297
|
+
closeTagIdx: closingTagInfo.closeTagIdx,
|
6298
|
+
closeTagLength: closingTagInfo.closeTagLength,
|
6299
|
+
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
6300
|
+
startIndex,
|
6301
|
+
oldPlainTextEndIndex,
|
6302
|
+
mentionTagLength
|
6303
|
+
});
|
6304
|
+
result += updateMentionTagResult.result;
|
6305
|
+
changeNewEndIndex = updateMentionTagResult.plainTextSelectionEndIndex;
|
6306
|
+
processedChange = updateMentionTagResult.updatedChange;
|
6307
|
+
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
6308
|
+
}
|
6309
|
+
}
|
6310
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
6311
|
+
// with subtags
|
6312
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
6313
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
6314
|
+
const updatedContent = updateHTML({
|
6315
|
+
htmlText: tag.content,
|
6316
|
+
oldPlainText,
|
6317
|
+
newPlainText,
|
6318
|
+
tags: tag.subTags,
|
6319
|
+
startIndex,
|
6320
|
+
oldPlainTextEndIndex,
|
6321
|
+
change: processedChange,
|
6322
|
+
mentionTrigger
|
6323
|
+
});
|
6324
|
+
result += stringBefore + updatedContent.updatedHTML;
|
6325
|
+
changeNewEndIndex = updatedContent.updatedSelectionIndex;
|
6326
|
+
}
|
6327
|
+
else {
|
6328
|
+
// no subtags
|
6329
|
+
const startChangeDiff = startIndex - tag.plainTextBeginIndex;
|
6330
|
+
result +=
|
6331
|
+
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff) +
|
6332
|
+
processedChange;
|
6333
|
+
processedChange = '';
|
6334
|
+
if (oldPlainTextEndIndex < closingTagInfo.plainTextEndIndex) {
|
6335
|
+
const endChangeDiff = oldPlainTextEndIndex - tag.plainTextBeginIndex;
|
6336
|
+
lastProcessedHTMLIndex = tag.openTagIndex + tag.openTagBody.length + endChangeDiff;
|
6337
|
+
}
|
6338
|
+
else if (oldPlainTextEndIndex === closingTagInfo.plainTextEndIndex) {
|
6339
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
6340
|
+
}
|
6349
6341
|
}
|
6342
|
+
// the change is handled; exit
|
6343
|
+
break;
|
6350
6344
|
}
|
6351
|
-
|
6352
|
-
|
6353
|
-
|
6354
|
-
|
6355
|
-
|
6356
|
-
|
6357
|
-
|
6358
|
-
|
6359
|
-
|
6360
|
-
|
6361
|
-
|
6362
|
-
|
6363
|
-
|
6364
|
-
|
6365
|
-
|
6366
|
-
|
6367
|
-
|
6368
|
-
return (React__default['default'].createElement(react.Stack, { horizontal: true, className: mergedChildrenStyle }, children));
|
6369
|
-
};
|
6370
|
-
/* @conditional-compile-remove(mention) */
|
6371
|
-
const debouncedQueryUpdate = useDebounce.useDebouncedCallback((query) => __awaiter$w(void 0, void 0, void 0, function* () {
|
6372
|
-
var _a;
|
6373
|
-
const suggestions = (_a = (yield (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onQueryUpdated(query)))) !== null && _a !== void 0 ? _a : [];
|
6374
|
-
if (suggestions.length === 0) {
|
6375
|
-
setActiveSuggestionIndex(undefined);
|
6376
|
-
}
|
6377
|
-
else if (activeSuggestionIndex === undefined) {
|
6378
|
-
// Set the active to the first, if it's not already set
|
6379
|
-
setActiveSuggestionIndex(0);
|
6380
|
-
}
|
6381
|
-
updateMentionSuggestions(suggestions);
|
6382
|
-
}), 500);
|
6383
|
-
/* @conditional-compile-remove(mention) */
|
6384
|
-
// Update selections index in mention to navigate by words
|
6385
|
-
const updateSelectionIndexesWithMentionIfNeeded = React.useCallback(({ event, inputTextValue, selectionEndValue, selectionStartValue, tagsValue }) => {
|
6386
|
-
var _a, _b, _c;
|
6387
|
-
let updatedStartIndex = event.currentTarget.selectionStart;
|
6388
|
-
let updatedEndIndex = event.currentTarget.selectionEnd;
|
6389
|
-
if (event.currentTarget.selectionStart === event.currentTarget.selectionEnd &&
|
6390
|
-
event.currentTarget.selectionStart !== null &&
|
6391
|
-
event.currentTarget.selectionStart !== -1) {
|
6392
|
-
// just a caret movement/usual typing or deleting
|
6393
|
-
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
6394
|
-
// don't include boundary cases to show correct selection, otherwise it will show selection at mention boundaries
|
6395
|
-
if (mentionTag !== undefined &&
|
6396
|
-
mentionTag.plainTextBeginIndex !== undefined &&
|
6397
|
-
event.currentTarget.selectionStart > mentionTag.plainTextBeginIndex &&
|
6398
|
-
event.currentTarget.selectionStart < ((_a = mentionTag.plainTextEndIndex) !== null && _a !== void 0 ? _a : mentionTag.plainTextBeginIndex)) {
|
6399
|
-
// get updated selection index
|
6400
|
-
const newSelectionIndex = findNewSelectionIndexForMention({
|
6401
|
-
tag: mentionTag,
|
6402
|
-
textValue: inputTextValue,
|
6403
|
-
currentSelectionIndex: event.currentTarget.selectionStart,
|
6404
|
-
previousSelectionIndex: selectionStartValue !== null && selectionStartValue !== void 0 ? selectionStartValue : inputTextValue.length
|
6405
|
-
});
|
6406
|
-
updatedStartIndex = newSelectionIndex;
|
6407
|
-
updatedEndIndex = newSelectionIndex;
|
6408
|
-
}
|
6409
|
-
}
|
6410
|
-
else if (event.currentTarget.selectionStart !== event.currentTarget.selectionEnd) {
|
6411
|
-
// Both e.currentTarget.selectionStart !== selectionStartValue and e.currentTarget.selectionEnd !== selectionEndValue can be true when a user selects a text by double click
|
6412
|
-
if (event.currentTarget.selectionStart !== null && event.currentTarget.selectionStart !== selectionStartValue) {
|
6413
|
-
// the selection start is changed
|
6414
|
-
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
6415
|
-
// don't include boundary cases to show correct selection, otherwise it will show selection at mention boundaries
|
6416
|
-
if (mentionTag !== undefined &&
|
6417
|
-
mentionTag.plainTextBeginIndex !== undefined &&
|
6418
|
-
event.currentTarget.selectionStart > mentionTag.plainTextBeginIndex &&
|
6419
|
-
event.currentTarget.selectionStart < ((_b = mentionTag.plainTextEndIndex) !== null && _b !== void 0 ? _b : mentionTag.plainTextBeginIndex)) {
|
6420
|
-
updatedStartIndex = findNewSelectionIndexForMention({
|
6421
|
-
tag: mentionTag,
|
6422
|
-
textValue: inputTextValue,
|
6423
|
-
currentSelectionIndex: event.currentTarget.selectionStart,
|
6424
|
-
previousSelectionIndex: selectionStartValue !== null && selectionStartValue !== void 0 ? selectionStartValue : inputTextValue.length
|
6345
|
+
else if (startIndex > tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
6346
|
+
// the change started in the tag but finishes somewhere further
|
6347
|
+
const startChangeDiff = startIndex - tag.plainTextBeginIndex - mentionTagLength;
|
6348
|
+
if (isMentionTag) {
|
6349
|
+
const updateMentionTagResult = handleMentionTagUpdate({
|
6350
|
+
htmlText,
|
6351
|
+
oldPlainText,
|
6352
|
+
lastProcessedHTMLIndex,
|
6353
|
+
processedChange: '',
|
6354
|
+
change,
|
6355
|
+
tag,
|
6356
|
+
closeTagIdx: closingTagInfo.closeTagIdx,
|
6357
|
+
closeTagLength: closingTagInfo.closeTagLength,
|
6358
|
+
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
6359
|
+
startIndex,
|
6360
|
+
oldPlainTextEndIndex,
|
6361
|
+
mentionTagLength
|
6425
6362
|
});
|
6363
|
+
result += updateMentionTagResult.result;
|
6364
|
+
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
6365
|
+
// no need to handle plainTextSelectionEndIndex as the change will be added later
|
6426
6366
|
}
|
6427
|
-
|
6428
|
-
|
6429
|
-
|
6430
|
-
|
6431
|
-
|
6432
|
-
|
6433
|
-
|
6434
|
-
|
6435
|
-
|
6436
|
-
|
6437
|
-
|
6438
|
-
|
6439
|
-
|
6440
|
-
previousSelectionIndex: selectionEndValue !== null && selectionEndValue !== void 0 ? selectionEndValue : inputTextValue.length
|
6367
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
6368
|
+
// with subtags
|
6369
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
6370
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
6371
|
+
const updatedContent = updateHTML({
|
6372
|
+
htmlText: tag.content,
|
6373
|
+
oldPlainText,
|
6374
|
+
newPlainText,
|
6375
|
+
tags: tag.subTags,
|
6376
|
+
startIndex,
|
6377
|
+
oldPlainTextEndIndex,
|
6378
|
+
change: '',
|
6379
|
+
mentionTrigger
|
6441
6380
|
});
|
6381
|
+
result += stringBefore + updatedContent.updatedHTML;
|
6382
|
+
}
|
6383
|
+
else {
|
6384
|
+
// no subtags
|
6385
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff);
|
6386
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
6442
6387
|
}
|
6388
|
+
// proceed with the next calculations
|
6443
6389
|
}
|
6444
|
-
|
6445
|
-
|
6446
|
-
|
6447
|
-
|
6448
|
-
|
6449
|
-
|
6450
|
-
event.currentTarget.setSelectionRange(updatedStartIndex, updatedEndIndex, event.currentTarget.selectionDirection);
|
6451
|
-
}
|
6452
|
-
setSelectionStartValue(nullToUndefined(updatedStartIndex));
|
6453
|
-
setSelectionEndValue(nullToUndefined(updatedEndIndex));
|
6454
|
-
}, [setSelectionStartValue, setSelectionEndValue]);
|
6455
|
-
/* @conditional-compile-remove(mention) */
|
6456
|
-
const handleOnSelect = React.useCallback(({ event, inputTextValue, tags, shouldHandleOnMouseDownDuringSelect, selectionStartValue, selectionEndValue }) => {
|
6457
|
-
if (shouldHandleOnMouseDownDuringSelect) {
|
6458
|
-
if (targetSelection !== undefined) {
|
6459
|
-
setSelectionStartValue(targetSelection.start);
|
6460
|
-
setSelectionEndValue(targetSelection.end);
|
6461
|
-
event.currentTarget.setSelectionRange(targetSelection.start, undefinedToNull(targetSelection.end));
|
6462
|
-
setTargetSelection(undefined);
|
6390
|
+
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
6391
|
+
// the change starts before the tag and finishes after it
|
6392
|
+
// tag should be removed, no matter if there are subtags
|
6393
|
+
// no need to save anything between lastProcessedHTMLIndex and closeTagIdx + closeTagLength
|
6394
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
6395
|
+
// proceed with the next calculations
|
6463
6396
|
}
|
6464
|
-
else if (
|
6465
|
-
//
|
6466
|
-
|
6467
|
-
|
6468
|
-
|
6469
|
-
|
6470
|
-
|
6471
|
-
|
6472
|
-
|
6473
|
-
|
6474
|
-
|
6397
|
+
else if (startIndex === tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
6398
|
+
// the change starts in the tag and finishes after it
|
6399
|
+
// tag should be removed, no matter if there are subtags
|
6400
|
+
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex);
|
6401
|
+
// processedChange shouldn't be updated as it will be added after the tag
|
6402
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
6403
|
+
// proceed with the next calculations
|
6404
|
+
}
|
6405
|
+
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex < closingTagInfo.plainTextEndIndex) {
|
6406
|
+
// the change starts before the tag and ends in a tag
|
6407
|
+
if (isMentionTag) {
|
6408
|
+
// mention tag
|
6409
|
+
const updateMentionTagResult = handleMentionTagUpdate({
|
6410
|
+
htmlText,
|
6411
|
+
oldPlainText,
|
6412
|
+
lastProcessedHTMLIndex,
|
6413
|
+
processedChange: '',
|
6414
|
+
change,
|
6415
|
+
tag,
|
6416
|
+
closeTagIdx: closingTagInfo.closeTagIdx,
|
6417
|
+
closeTagLength: closingTagInfo.closeTagLength,
|
6418
|
+
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
6419
|
+
startIndex,
|
6420
|
+
oldPlainTextEndIndex,
|
6421
|
+
mentionTagLength
|
6475
6422
|
});
|
6476
|
-
|
6477
|
-
|
6478
|
-
|
6479
|
-
|
6480
|
-
|
6481
|
-
|
6482
|
-
|
6483
|
-
|
6423
|
+
changeNewEndIndex = updateMentionTagResult.plainTextSelectionEndIndex;
|
6424
|
+
result += updateMentionTagResult.result;
|
6425
|
+
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
6426
|
+
}
|
6427
|
+
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
6428
|
+
// with subtags
|
6429
|
+
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
6430
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
6431
|
+
const updatedContent = updateHTML({
|
6432
|
+
htmlText: tag.content,
|
6433
|
+
oldPlainText,
|
6434
|
+
newPlainText,
|
6435
|
+
tags: tag.subTags,
|
6436
|
+
startIndex,
|
6437
|
+
oldPlainTextEndIndex,
|
6438
|
+
change: processedChange,
|
6439
|
+
mentionTrigger
|
6440
|
+
});
|
6441
|
+
processedChange = '';
|
6442
|
+
result += stringBefore + updatedContent.updatedHTML;
|
6484
6443
|
}
|
6485
6444
|
else {
|
6486
|
-
|
6487
|
-
|
6445
|
+
// no subtags
|
6446
|
+
result +=
|
6447
|
+
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length) + processedChange;
|
6448
|
+
processedChange = '';
|
6449
|
+
// oldPlainTextEndIndex already includes mentionTag length
|
6450
|
+
const endChangeDiff = closingTagInfo.plainTextEndIndex - oldPlainTextEndIndex;
|
6451
|
+
// as change may be before the end of the tag, we need to add the rest of the tag
|
6452
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx - endChangeDiff;
|
6488
6453
|
}
|
6454
|
+
// the change is handled; exit
|
6455
|
+
break;
|
6489
6456
|
}
|
6457
|
+
lastProcessedPlainTextTagEndIndex = closingTagInfo.plainTextEndIndex;
|
6490
6458
|
}
|
6491
|
-
|
6492
|
-
//
|
6493
|
-
|
6494
|
-
|
6495
|
-
|
6496
|
-
|
6497
|
-
|
6498
|
-
|
6499
|
-
}
|
6500
|
-
|
6501
|
-
|
6502
|
-
|
6503
|
-
|
6504
|
-
|
6505
|
-
|
6506
|
-
|
6507
|
-
|
6508
|
-
|
6509
|
-
|
6510
|
-
]);
|
6511
|
-
/* @conditional-compile-remove(mention) */
|
6512
|
-
const handleOnChange = React.useCallback(({ currentSelectionEnd, currentSelectionStart, currentTriggerStartIndex, event, htmlTextValue, inputTextValue, previousSelectionEnd, previousSelectionStart, tagsValue, updatedValue }) => __awaiter$w(void 0, void 0, void 0, function* () {
|
6513
|
-
var _b;
|
6514
|
-
debouncedQueryUpdate.cancel();
|
6515
|
-
if (event.currentTarget === null) {
|
6516
|
-
return;
|
6459
|
+
if (i === tags.length - 1 && oldPlainTextEndIndex >= closingTagInfo.plainTextEndIndex) {
|
6460
|
+
// the last tag should handle the end of the change if needed
|
6461
|
+
// oldPlainTextEndIndex already includes mentionTag length
|
6462
|
+
const endChangeDiff = oldPlainTextEndIndex - closingTagInfo.plainTextEndIndex;
|
6463
|
+
if (startIndex >= closingTagInfo.plainTextEndIndex) {
|
6464
|
+
const startChangeDiff = startIndex - closingTagInfo.plainTextEndIndex;
|
6465
|
+
result +=
|
6466
|
+
htmlText.substring(lastProcessedHTMLIndex, closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength + startChangeDiff) + processedChange;
|
6467
|
+
}
|
6468
|
+
else {
|
6469
|
+
result +=
|
6470
|
+
htmlText.substring(lastProcessedHTMLIndex, closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength) +
|
6471
|
+
processedChange;
|
6472
|
+
}
|
6473
|
+
processedChange = '';
|
6474
|
+
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength + endChangeDiff;
|
6475
|
+
// the change is handled; exit
|
6476
|
+
// break is not required here as this is the last element but added for consistency
|
6477
|
+
break;
|
6517
6478
|
}
|
6518
|
-
|
6519
|
-
|
6520
|
-
|
6521
|
-
|
6522
|
-
|
6523
|
-
|
6524
|
-
|
6525
|
-
|
6526
|
-
|
6527
|
-
|
6528
|
-
|
6529
|
-
|
6530
|
-
|
6531
|
-
|
6532
|
-
|
6533
|
-
|
6534
|
-
|
6535
|
-
|
6536
|
-
|
6537
|
-
|
6538
|
-
|
6539
|
-
|
6540
|
-
|
6541
|
-
|
6542
|
-
|
6543
|
-
|
6544
|
-
|
6545
|
-
//
|
6546
|
-
if (
|
6547
|
-
//
|
6548
|
-
|
6549
|
-
|
6550
|
-
|
6551
|
-
|
6552
|
-
|
6553
|
-
|
6554
|
-
|
6555
|
-
|
6556
|
-
if (
|
6557
|
-
//
|
6558
|
-
|
6559
|
-
setCurrentTriggerStartIndex(tagIndex);
|
6560
|
-
}
|
6561
|
-
else if (wordAtSelection === triggerText) {
|
6562
|
-
// start of the mention
|
6563
|
-
tagIndex = currentSelectionEndValue - triggerText.length;
|
6564
|
-
if (tagIndex < 0) {
|
6565
|
-
tagIndex = 0;
|
6566
|
-
}
|
6567
|
-
setCurrentTriggerStartIndex(tagIndex);
|
6568
|
-
}
|
6569
|
-
if (tagIndex === -1) {
|
6570
|
-
updateMentionSuggestions([]);
|
6571
|
-
}
|
6572
|
-
else {
|
6573
|
-
// In the middle of a @mention lookup
|
6574
|
-
if (tagIndex > -1) {
|
6575
|
-
const query = wordAtSelection.substring(triggerText.length, wordAtSelection.length);
|
6576
|
-
if (query !== undefined) {
|
6577
|
-
yield debouncedQueryUpdate(query);
|
6578
|
-
}
|
6579
|
-
}
|
6479
|
+
}
|
6480
|
+
if (lastProcessedHTMLIndex < htmlText.length) {
|
6481
|
+
// add the rest of the html string
|
6482
|
+
result += htmlText.substring(lastProcessedHTMLIndex);
|
6483
|
+
}
|
6484
|
+
return { updatedHTML: result, updatedSelectionIndex: changeNewEndIndex };
|
6485
|
+
};
|
6486
|
+
/**
|
6487
|
+
* Given the oldText and newText, find the start index, old end index and new end index for the changes
|
6488
|
+
*
|
6489
|
+
* @private
|
6490
|
+
* @param props - Props for finding stings diff indexes function.
|
6491
|
+
* @returns Indexes for change start and ends in new and old texts. The old and new end indexes are exclusive.
|
6492
|
+
*/
|
6493
|
+
const findStringsDiffIndexes = (props) => {
|
6494
|
+
const { oldText, newText, previousSelectionStart, previousSelectionEnd, currentSelectionStart, currentSelectionEnd } = props;
|
6495
|
+
const newTextLength = newText.length;
|
6496
|
+
const oldTextLength = oldText.length;
|
6497
|
+
// let changeStart = 0;
|
6498
|
+
let newChangeEnd = newTextLength;
|
6499
|
+
let oldChangeEnd = oldTextLength;
|
6500
|
+
const previousSelectionStartValue = previousSelectionStart > -1 ? previousSelectionStart : oldTextLength;
|
6501
|
+
const previousSelectionEndValue = previousSelectionEnd > -1 ? previousSelectionEnd : oldTextLength;
|
6502
|
+
const currentSelectionStartValue = currentSelectionStart > -1 ? currentSelectionStart : newTextLength;
|
6503
|
+
const currentSelectionEndValue = currentSelectionEnd > -1 ? currentSelectionEnd : newTextLength;
|
6504
|
+
const changeStart = Math.min(previousSelectionStartValue, previousSelectionEndValue, currentSelectionStartValue, currentSelectionEndValue, newTextLength, oldTextLength);
|
6505
|
+
if (oldTextLength < newTextLength) {
|
6506
|
+
//insert or replacement
|
6507
|
+
if (oldTextLength === changeStart) {
|
6508
|
+
// when change was at the end of string
|
6509
|
+
// change is found
|
6510
|
+
newChangeEnd = newTextLength;
|
6511
|
+
oldChangeEnd = oldTextLength;
|
6512
|
+
}
|
6513
|
+
else {
|
6514
|
+
for (let i = 1; i < newTextLength && oldTextLength - i >= changeStart; i++) {
|
6515
|
+
newChangeEnd = newTextLength - i - 1;
|
6516
|
+
oldChangeEnd = oldTextLength - i - 1;
|
6517
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
6518
|
+
// change is found
|
6519
|
+
break;
|
6580
6520
|
}
|
6581
6521
|
}
|
6522
|
+
// make indexes exclusive
|
6523
|
+
newChangeEnd += 1;
|
6524
|
+
oldChangeEnd += 1;
|
6582
6525
|
}
|
6583
|
-
|
6584
|
-
|
6585
|
-
|
6586
|
-
|
6526
|
+
}
|
6527
|
+
else if (oldTextLength > newTextLength) {
|
6528
|
+
//deletion or replacement
|
6529
|
+
if (newTextLength === changeStart) {
|
6530
|
+
// when change was at the end of string
|
6531
|
+
// change is found
|
6532
|
+
newChangeEnd = newTextLength;
|
6533
|
+
oldChangeEnd = oldTextLength;
|
6587
6534
|
}
|
6588
6535
|
else {
|
6589
|
-
|
6590
|
-
|
6591
|
-
|
6592
|
-
oldText
|
6593
|
-
|
6594
|
-
|
6595
|
-
previousSelectionEnd: previousSelectionEndValue,
|
6596
|
-
currentSelectionStart: currentSelectionStartValue,
|
6597
|
-
currentSelectionEnd: currentSelectionEndValue
|
6598
|
-
});
|
6599
|
-
const change = newValue.substring(changeStart, newChangeEnd);
|
6600
|
-
// get updated html string
|
6601
|
-
const updatedContent = updateHTML({
|
6602
|
-
htmlText: htmlTextValue,
|
6603
|
-
oldPlainText: inputTextValue,
|
6604
|
-
newPlainText: newValue,
|
6605
|
-
tags: tagsValue,
|
6606
|
-
startIndex: changeStart,
|
6607
|
-
oldPlainTextEndIndex: oldChangeEnd,
|
6608
|
-
change,
|
6609
|
-
mentionTrigger: triggerText
|
6610
|
-
});
|
6611
|
-
result = updatedContent.updatedHTML;
|
6612
|
-
// update caret index if needed
|
6613
|
-
if (updatedContent.updatedSelectionIndex !== undefined) {
|
6614
|
-
setCaretIndex(updatedContent.updatedSelectionIndex);
|
6615
|
-
setSelectionEndValue(updatedContent.updatedSelectionIndex);
|
6616
|
-
setSelectionStartValue(updatedContent.updatedSelectionIndex);
|
6617
|
-
}
|
6618
|
-
}
|
6619
|
-
onChange && onChange(event, result);
|
6620
|
-
}), [onChange, mentionLookupOptions, setCaretIndex, setCaretPosition, updateMentionSuggestions, debouncedQueryUpdate]);
|
6621
|
-
const getInputFieldTextValue = () => {
|
6622
|
-
/* @conditional-compile-remove(mention) */
|
6623
|
-
return inputTextValue;
|
6624
|
-
};
|
6625
|
-
/* @conditional-compile-remove(mention) */
|
6626
|
-
// Adjust the selection range based on a mouse / touch interaction
|
6627
|
-
const handleOnMove = React.useCallback((event) => {
|
6628
|
-
var _a;
|
6629
|
-
let targetStart = event.currentTarget.selectionStart;
|
6630
|
-
let targetEnd = event.currentTarget.selectionEnd;
|
6631
|
-
// Should we do anything?
|
6632
|
-
if (interactionStartPoint !== undefined &&
|
6633
|
-
// And did selection change?
|
6634
|
-
targetStart !== null &&
|
6635
|
-
(targetStart !== (targetSelection === null || targetSelection === void 0 ? void 0 : targetSelection.start) || targetEnd !== (targetSelection === null || targetSelection === void 0 ? void 0 : targetSelection.end))) {
|
6636
|
-
const direction = event.clientX > interactionStartPoint.x ? 'forward' : 'backward';
|
6637
|
-
const mentionTag = findMentionTagForSelection(tagsValue, direction === 'backward'
|
6638
|
-
? event.currentTarget.selectionStart
|
6639
|
-
: (_a = event.currentTarget.selectionEnd) !== null && _a !== void 0 ? _a : event.currentTarget.selectionStart);
|
6640
|
-
let updateCurrentTarget = false;
|
6641
|
-
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
6642
|
-
targetStart = Math.min(mentionTag.plainTextBeginIndex, targetStart);
|
6643
|
-
if (mentionTag.plainTextEndIndex !== undefined && targetEnd !== null) {
|
6644
|
-
targetEnd = Math.max(mentionTag.plainTextEndIndex, targetEnd);
|
6536
|
+
for (let i = 1; i < oldTextLength && newTextLength - i >= changeStart; i++) {
|
6537
|
+
newChangeEnd = newTextLength - i - 1;
|
6538
|
+
oldChangeEnd = oldTextLength - i - 1;
|
6539
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
6540
|
+
// change is found
|
6541
|
+
break;
|
6645
6542
|
}
|
6646
|
-
updateCurrentTarget = true;
|
6647
|
-
setShouldHandleOnMouseDownDuringSelect(false);
|
6648
6543
|
}
|
6649
|
-
//
|
6650
|
-
|
6651
|
-
|
6652
|
-
|
6653
|
-
|
6544
|
+
// make indexes exclusive
|
6545
|
+
newChangeEnd += 1;
|
6546
|
+
oldChangeEnd += 1;
|
6547
|
+
}
|
6548
|
+
}
|
6549
|
+
else {
|
6550
|
+
// replacement
|
6551
|
+
for (let i = 1; i < oldTextLength && oldTextLength - i >= changeStart; i++) {
|
6552
|
+
newChangeEnd = newTextLength - i - 1;
|
6553
|
+
oldChangeEnd = oldTextLength - i - 1;
|
6554
|
+
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
6555
|
+
// change is found
|
6556
|
+
break;
|
6654
6557
|
}
|
6655
6558
|
}
|
6656
|
-
|
6657
|
-
|
6658
|
-
|
6659
|
-
if (activeSuggestionIndex === undefined) {
|
6660
|
-
return undefined;
|
6559
|
+
// make indexes exclusive if they aren't equal to the length of the string
|
6560
|
+
if (newChangeEnd !== newText.length) {
|
6561
|
+
newChangeEnd += 1;
|
6661
6562
|
}
|
6662
|
-
|
6663
|
-
|
6664
|
-
|
6665
|
-
|
6666
|
-
|
6667
|
-
return (React__default['default'].createElement(react.Stack, { className: mergedRootStyle },
|
6668
|
-
React__default['default'].createElement("div", { className: mergedTextContainerStyle },
|
6669
|
-
/* @conditional-compile-remove(mention) */ mentionSuggestions.length > 0 && (React__default['default'].createElement(_MentionPopover, { suggestions: mentionSuggestions, activeSuggestionIndex: activeSuggestionIndex, target: inputBoxRef, targetPositionOffset: caretPosition, onRenderSuggestionItem: mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onRenderSuggestionItem, onSuggestionSelected: onSuggestionSelected, onDismiss: () => {
|
6670
|
-
updateMentionSuggestions([]);
|
6671
|
-
} })),
|
6672
|
-
/* @conditional-compile-remove(mention) */ announcerText !== undefined && (React__default['default'].createElement(Announcer$1, { announcementString: announcerText, ariaLive: 'polite' })),
|
6673
|
-
React__default['default'].createElement(react.TextField, { autoFocus: props.autoFocus === 'sendBoxTextField', "data-ui-id": dataUiId, multiline: true, autoAdjustHeight: true, multiple: false, resizable: false, componentRef: textFieldRef, id: id, inputClassName: mergedInputFieldStyle, placeholder: placeholderText, value: getInputFieldTextValue(), onChange: (e, newValue) => {
|
6674
|
-
// Remove when switching to react 17+, currently needed because of https://legacy.reactjs.org/docs/legacy-event-pooling.html
|
6675
|
-
/* @conditional-compile-remove(mention) */
|
6676
|
-
// Prevents React from resetting event's properties
|
6677
|
-
e.persist();
|
6678
|
-
/* @conditional-compile-remove(mention) */
|
6679
|
-
setInputTextValue(newValue !== null && newValue !== void 0 ? newValue : '');
|
6680
|
-
/* @conditional-compile-remove(mention) */
|
6681
|
-
handleOnChange({
|
6682
|
-
event: e,
|
6683
|
-
tagsValue,
|
6684
|
-
htmlTextValue: textValue,
|
6685
|
-
inputTextValue,
|
6686
|
-
currentTriggerStartIndex,
|
6687
|
-
previousSelectionStart: nullToUndefined(selectionStartValue),
|
6688
|
-
previousSelectionEnd: nullToUndefined(selectionEndValue),
|
6689
|
-
currentSelectionStart: nullToUndefined(e.currentTarget.selectionStart),
|
6690
|
-
currentSelectionEnd: nullToUndefined(e.currentTarget.selectionEnd),
|
6691
|
-
updatedValue: newValue
|
6692
|
-
});
|
6693
|
-
/* @conditional-compile-remove(mention) */
|
6694
|
-
return;
|
6695
|
-
},
|
6696
|
-
/* @conditional-compile-remove(mention) */
|
6697
|
-
onSelect: (e) => {
|
6698
|
-
// update selection if needed
|
6699
|
-
if (caretIndex !== undefined) {
|
6700
|
-
setCaretIndex(undefined);
|
6701
|
-
// sometimes setting selectionRage in effect for updating caretIndex doesn't work as expected and onSelect should handle this case
|
6702
|
-
if (caretIndex !== e.currentTarget.selectionStart || caretIndex !== e.currentTarget.selectionEnd) {
|
6703
|
-
e.currentTarget.setSelectionRange(caretIndex, caretIndex);
|
6704
|
-
}
|
6705
|
-
return;
|
6706
|
-
}
|
6707
|
-
handleOnSelect({
|
6708
|
-
event: e,
|
6709
|
-
inputTextValue,
|
6710
|
-
shouldHandleOnMouseDownDuringSelect,
|
6711
|
-
selectionEndValue,
|
6712
|
-
selectionStartValue,
|
6713
|
-
tags: tagsValue
|
6714
|
-
});
|
6715
|
-
},
|
6716
|
-
/* @conditional-compile-remove(mention) */
|
6717
|
-
onMouseDown: (e) => {
|
6718
|
-
setInteractionStartPoint({ x: e.clientX, y: e.clientY });
|
6719
|
-
// as events order is onMouseDown -> onMouseMove -> onMouseUp -> onSelect -> onClick
|
6720
|
-
// onClick and onMouseDown can't handle clicking on mention event because
|
6721
|
-
// onMouseDown doesn't have correct selectionRange yet and
|
6722
|
-
// onClick already has wrong range as it's called after onSelect that updates the selection range
|
6723
|
-
// so we need to handle onMouseDown to prevent onSelect default behavior
|
6724
|
-
setShouldHandleOnMouseDownDuringSelect(true);
|
6725
|
-
},
|
6726
|
-
/* @conditional-compile-remove(mention) */
|
6727
|
-
onMouseMove: handleOnMove,
|
6728
|
-
/* @conditional-compile-remove(mention) */
|
6729
|
-
onMouseUp: () => {
|
6730
|
-
setInteractionStartPoint(undefined);
|
6731
|
-
},
|
6732
|
-
/* @conditional-compile-remove(mention) */
|
6733
|
-
onTouchStart: (e) => {
|
6734
|
-
setInteractionStartPoint({
|
6735
|
-
x: e.targetTouches.item(0).clientX,
|
6736
|
-
y: e.targetTouches.item(0).clientY
|
6737
|
-
});
|
6738
|
-
// see onMouseDown for more details
|
6739
|
-
setShouldHandleOnMouseDownDuringSelect(true);
|
6740
|
-
},
|
6741
|
-
/* @conditional-compile-remove(mention) */
|
6742
|
-
onTouchMove: handleOnMove,
|
6743
|
-
/* @conditional-compile-remove(mention) */
|
6744
|
-
onTouchEnd: () => {
|
6745
|
-
setInteractionStartPoint(undefined);
|
6746
|
-
},
|
6747
|
-
/* @conditional-compile-remove(mention) */
|
6748
|
-
onBlur: () => {
|
6749
|
-
// setup all flags to default values when text field loses focus
|
6750
|
-
setShouldHandleOnMouseDownDuringSelect(false);
|
6751
|
-
setCaretIndex(undefined);
|
6752
|
-
setSelectionStartValue(undefined);
|
6753
|
-
setSelectionEndValue(undefined);
|
6754
|
-
// Dismiss the suggestions on blur, after enough time to select by mouse if needed
|
6755
|
-
setTimeout(() => {
|
6756
|
-
setMentionSuggestions([]);
|
6757
|
-
}, 200);
|
6758
|
-
}, autoComplete: "off", onKeyDown: onTextFieldKeyDown, styles: mergedTextFieldStyle, disabled: disabled, errorMessage: errorMessage, onRenderSuffix: onRenderChildren, elementRef: inputBoxRef }))));
|
6563
|
+
if (oldChangeEnd !== oldText.length) {
|
6564
|
+
oldChangeEnd += 1;
|
6565
|
+
}
|
6566
|
+
}
|
6567
|
+
return { changeStart, oldChangeEnd, newChangeEnd };
|
6759
6568
|
};
|
6760
6569
|
/**
|
6570
|
+
* Get the html string for the mention suggestion.
|
6571
|
+
*
|
6761
6572
|
* @private
|
6573
|
+
* @param suggestion - The mention suggestion.
|
6574
|
+
* @param localeStrings - The locale strings.
|
6575
|
+
* @returns The html string for the mention suggestion.
|
6762
6576
|
*/
|
6763
|
-
const
|
6764
|
-
const
|
6765
|
-
const
|
6766
|
-
const
|
6767
|
-
|
6768
|
-
const calloutStyle = { root: { padding: 0 }, calloutMain: { padding: '0.5rem' } };
|
6769
|
-
// Place callout with no gap between it and the button.
|
6770
|
-
const calloutProps = {
|
6771
|
-
gapSpace: 0,
|
6772
|
-
styles: calloutStyle,
|
6773
|
-
backgroundColor: isDarkThemed(theme) ? theme.palette.neutralLighter : ''
|
6774
|
-
};
|
6775
|
-
return (React__default['default'].createElement(react.TooltipHost, { hostClassName: inputButtonTooltipStyle, content: tooltipContent, calloutProps: Object.assign({}, calloutProps) },
|
6776
|
-
React__default['default'].createElement(react.IconButton, { className: mergedButtonStyle, ariaLabel: ariaLabel, onClick: onClick, id: id, onMouseEnter: () => {
|
6777
|
-
setIsHover(true);
|
6778
|
-
}, onMouseLeave: () => {
|
6779
|
-
setIsHover(false);
|
6780
|
-
},
|
6781
|
-
// VoiceOver fix: Avoid icon from stealing focus when IconButton is double-tapped to send message by wrapping with Stack with pointerEvents style to none
|
6782
|
-
onRenderIcon: () => React__default['default'].createElement(react.Stack, { className: iconWrapperStyle$1 }, onRenderIcon(isHover)) })));
|
6577
|
+
const htmlStringForMentionSuggestion = (suggestion, localeStrings) => {
|
6578
|
+
const idHTML = ' id="' + suggestion.id + '"';
|
6579
|
+
const displayTextHTML = ' displayText="' + suggestion.displayText + '"';
|
6580
|
+
const displayText = getDisplayNameForMentionSuggestion(suggestion, localeStrings);
|
6581
|
+
return '<' + MSFT_MENTION_TAG + idHTML + displayTextHTML + '>' + displayText + '</' + MSFT_MENTION_TAG + '>';
|
6783
6582
|
};
|
6784
|
-
/* @conditional-compile-remove(mention) */
|
6785
6583
|
/**
|
6786
|
-
* Get
|
6584
|
+
* Get display name for the mention suggestion.
|
6787
6585
|
*
|
6788
6586
|
* @private
|
6789
|
-
*
|
6790
|
-
* @
|
6587
|
+
*
|
6588
|
+
* @param suggestion - The mention suggestion.
|
6589
|
+
* @param localeStrings - The locale strings.
|
6590
|
+
* @returns The display name for the mention suggestion or display name placeholder if display name is empty.
|
6791
6591
|
*/
|
6792
|
-
const
|
6793
|
-
const
|
6794
|
-
|
6795
|
-
updatedValue = Math.max(min, updatedValue);
|
6796
|
-
updatedValue = Math.min(updatedValue, max);
|
6797
|
-
return updatedValue;
|
6592
|
+
const getDisplayNameForMentionSuggestion = (suggestion, localeStrings) => {
|
6593
|
+
const displayNamePlaceholder = localeStrings.participantItem.displayNamePlaceholder;
|
6594
|
+
return suggestion.displayText !== '' ? suggestion.displayText : displayNamePlaceholder !== null && displayNamePlaceholder !== void 0 ? displayNamePlaceholder : '';
|
6798
6595
|
};
|
6799
|
-
/* @conditional-compile-remove(mention) */
|
6800
6596
|
/**
|
6801
|
-
*
|
6802
|
-
*
|
6597
|
+
* Parse the text and return the tags and the plain text in one go
|
6803
6598
|
* @private
|
6804
|
-
* @param
|
6805
|
-
* @param
|
6806
|
-
*
|
6599
|
+
* @param text - The text to parse for HTML tags
|
6600
|
+
* @param trigger The trigger to show for the mention tag in plain text
|
6601
|
+
*
|
6602
|
+
* @returns An array of tags and the plain text representation
|
6807
6603
|
*/
|
6808
|
-
const
|
6809
|
-
|
6810
|
-
tags
|
6811
|
-
|
6812
|
-
|
6813
|
-
|
6814
|
-
|
6604
|
+
const textToTagParser = (text, trigger) => {
|
6605
|
+
var _a, _b;
|
6606
|
+
const tags = []; // Tags passed back to the caller
|
6607
|
+
const tagParseStack = []; // Local stack to use while parsing
|
6608
|
+
let plainTextRepresentation = '';
|
6609
|
+
let parseIndex = 0;
|
6610
|
+
while (parseIndex < text.length) {
|
6611
|
+
const foundHtmlTag = findNextHtmlTag(text, parseIndex);
|
6612
|
+
if (!foundHtmlTag) {
|
6613
|
+
if (parseIndex !== 0) {
|
6614
|
+
// Add the remaining text to the plain text representation
|
6615
|
+
plainTextRepresentation += text.substring(parseIndex);
|
6616
|
+
}
|
6617
|
+
else {
|
6618
|
+
plainTextRepresentation = text;
|
6619
|
+
}
|
6620
|
+
break;
|
6815
6621
|
}
|
6816
|
-
|
6817
|
-
|
6818
|
-
|
6819
|
-
|
6820
|
-
|
6821
|
-
|
6822
|
-
|
6823
|
-
|
6824
|
-
|
6622
|
+
if (foundHtmlTag.type === 'open' || foundHtmlTag.type === 'self-closing') {
|
6623
|
+
const nextTag = parseOpenTag(foundHtmlTag.content, foundHtmlTag.startIdx);
|
6624
|
+
// Add the plain text between the last tag and this one found
|
6625
|
+
plainTextRepresentation += text.substring(parseIndex, foundHtmlTag.startIdx);
|
6626
|
+
nextTag.plainTextBeginIndex = plainTextRepresentation.length;
|
6627
|
+
if (foundHtmlTag.type === 'open') {
|
6628
|
+
tagParseStack.push(nextTag);
|
6629
|
+
}
|
6630
|
+
else {
|
6631
|
+
nextTag.content = '';
|
6632
|
+
nextTag.plainTextBeginIndex = plainTextRepresentation.length;
|
6633
|
+
nextTag.plainTextEndIndex = plainTextRepresentation.length;
|
6634
|
+
addTag(nextTag, tagParseStack, tags);
|
6635
|
+
}
|
6636
|
+
}
|
6637
|
+
if (foundHtmlTag.type === 'close') {
|
6638
|
+
const currentOpenTag = tagParseStack.pop();
|
6639
|
+
const closeTagType = foundHtmlTag.content.substring(2, foundHtmlTag.content.length - 1).toLowerCase();
|
6640
|
+
if (currentOpenTag && currentOpenTag.tagType === closeTagType) {
|
6641
|
+
// Tag startIdx is absolute to the text. This is updated later to be relative to the parent tag
|
6642
|
+
currentOpenTag.content = text.substring(currentOpenTag.openTagIndex + currentOpenTag.openTagBody.length, foundHtmlTag.startIdx);
|
6643
|
+
// Insert the plain text pieces for the sub tags
|
6644
|
+
if (currentOpenTag.tagType === MSFT_MENTION_TAG) {
|
6645
|
+
plainTextRepresentation =
|
6646
|
+
plainTextRepresentation.slice(0, currentOpenTag.plainTextBeginIndex) +
|
6647
|
+
trigger +
|
6648
|
+
plainTextRepresentation.slice(currentOpenTag.plainTextBeginIndex);
|
6649
|
+
}
|
6650
|
+
if (!currentOpenTag.subTags) {
|
6651
|
+
plainTextRepresentation += currentOpenTag.content;
|
6652
|
+
}
|
6653
|
+
else if (currentOpenTag.subTags.length > 0) {
|
6654
|
+
// Add text after the last tag
|
6655
|
+
const lastSubTag = currentOpenTag.subTags[currentOpenTag.subTags.length - 1];
|
6656
|
+
const startOfRemainingText = ((_a = lastSubTag.closingTagIndex) !== null && _a !== void 0 ? _a : lastSubTag.openTagIndex) + lastSubTag.tagType.length + 3;
|
6657
|
+
const trailingText = currentOpenTag.content.substring(startOfRemainingText);
|
6658
|
+
plainTextRepresentation += trailingText;
|
6825
6659
|
}
|
6660
|
+
currentOpenTag.plainTextEndIndex = plainTextRepresentation.length;
|
6661
|
+
addTag(currentOpenTag, tagParseStack, tags);
|
6826
6662
|
}
|
6827
|
-
else
|
6828
|
-
|
6829
|
-
|
6663
|
+
else {
|
6664
|
+
throw new Error('Unexpected close tag found. Got "' +
|
6665
|
+
closeTagType +
|
6666
|
+
'" but expected "' +
|
6667
|
+
((_b = tagParseStack[tagParseStack.length - 1]) === null || _b === void 0 ? void 0 : _b.tagType) +
|
6668
|
+
'"');
|
6830
6669
|
}
|
6831
6670
|
}
|
6832
|
-
|
6833
|
-
|
6834
|
-
|
6671
|
+
// Update parsing index; move past the end of the close tag
|
6672
|
+
parseIndex = foundHtmlTag.startIdx + foundHtmlTag.content.length;
|
6673
|
+
} // While parseIndex < text.length loop
|
6674
|
+
return { tags, plainText: plainTextRepresentation };
|
6835
6675
|
};
|
6836
|
-
|
6837
|
-
const
|
6838
|
-
|
6839
|
-
|
6840
|
-
|
6676
|
+
const parseOpenTag = (tag, startIdx) => {
|
6677
|
+
const tagType = tag
|
6678
|
+
.substring(1, tag.length - 1)
|
6679
|
+
.split(' ')[0]
|
6680
|
+
.toLowerCase()
|
6681
|
+
.replace('/', '');
|
6682
|
+
return {
|
6683
|
+
tagType,
|
6684
|
+
openTagIndex: startIdx,
|
6685
|
+
openTagBody: tag
|
6686
|
+
};
|
6687
|
+
};
|
6688
|
+
const findNextHtmlTag = (text, startIndex) => {
|
6689
|
+
const tagStartIndex = text.indexOf('<', startIndex);
|
6690
|
+
if (tagStartIndex === -1) {
|
6691
|
+
// No more tags
|
6692
|
+
return undefined;
|
6841
6693
|
}
|
6842
|
-
|
6843
|
-
|
6844
|
-
|
6845
|
-
|
6846
|
-
const firstWordStartIndex = textInput.lastIndexOf(' ', selectionStart);
|
6847
|
-
if (firstWordStartIndex === tag.plainTextBeginIndex) {
|
6848
|
-
start = firstWordStartIndex;
|
6694
|
+
const tagEndIndex = text.indexOf('>', tagStartIndex);
|
6695
|
+
if (tagEndIndex === -1) {
|
6696
|
+
// No close tag
|
6697
|
+
return undefined;
|
6849
6698
|
}
|
6850
|
-
|
6851
|
-
|
6699
|
+
const tag = text.substring(tagStartIndex, tagEndIndex + 1);
|
6700
|
+
let type = 'open';
|
6701
|
+
if (tag[1] === '/') {
|
6702
|
+
type = 'close';
|
6852
6703
|
}
|
6853
|
-
|
6854
|
-
|
6855
|
-
if (selectionEnd !== undefined && tag.plainTextEndIndex !== undefined) {
|
6856
|
-
const lastWordEndIndex = textInput.indexOf(' ', selectionEnd);
|
6857
|
-
end = Math.max(lastWordEndIndex > -1 ? lastWordEndIndex : tag.plainTextEndIndex, selectionEnd);
|
6704
|
+
else if (tag[tag.length - 2] === '/') {
|
6705
|
+
type = 'self-closing';
|
6858
6706
|
}
|
6859
|
-
return {
|
6707
|
+
return {
|
6708
|
+
content: tag,
|
6709
|
+
startIdx: tagStartIndex,
|
6710
|
+
type
|
6711
|
+
};
|
6860
6712
|
};
|
6861
|
-
|
6862
|
-
/**
|
6863
|
-
* Find a new the selection index.
|
6864
|
-
*
|
6865
|
-
* @private
|
6866
|
-
* @param props - Props for finding new selection index for mention.
|
6867
|
-
* @returns New selection index if it is inside of a mention tag, otherwise the current selection.
|
6868
|
-
*/
|
6869
|
-
const findNewSelectionIndexForMention = (props) => {
|
6713
|
+
const addTag = (tag, parseStack, tags) => {
|
6870
6714
|
var _a;
|
6871
|
-
|
6872
|
-
|
6873
|
-
if (
|
6874
|
-
tag
|
6875
|
-
|
6876
|
-
tag.
|
6877
|
-
|
6715
|
+
// Add as sub-tag to the parent stack tag, if there is one
|
6716
|
+
const parentTag = parseStack[parseStack.length - 1];
|
6717
|
+
if (parentTag) {
|
6718
|
+
// Adjust the open tag index to be relative to the parent tag
|
6719
|
+
const parentContentStartIdx = parentTag.openTagIndex + parentTag.openTagBody.length;
|
6720
|
+
const relativeIdx = tag.openTagIndex - parentContentStartIdx;
|
6721
|
+
tag.openTagIndex = relativeIdx;
|
6878
6722
|
}
|
6879
|
-
|
6880
|
-
|
6881
|
-
|
6882
|
-
|
6883
|
-
|
6884
|
-
|
6885
|
-
|
6723
|
+
if (!tag.closingTagIndex) {
|
6724
|
+
// If the tag is self-closing, the close tag is the same as the open tag
|
6725
|
+
if (tag.openTagBody[tag.openTagBody.length - 2] === '/') {
|
6726
|
+
tag.closingTagIndex = tag.openTagIndex;
|
6727
|
+
}
|
6728
|
+
else {
|
6729
|
+
// Otherwise, the close tag index is the open tag index + the open tag body + the content length
|
6730
|
+
tag.closingTagIndex = tag.openTagIndex + tag.openTagBody.length + ((_a = tag.content) !== null && _a !== void 0 ? _a : []).length;
|
6886
6731
|
}
|
6887
6732
|
}
|
6733
|
+
// Put the tag where it belongs
|
6734
|
+
if (!parentTag) {
|
6735
|
+
tags.push(tag);
|
6736
|
+
}
|
6888
6737
|
else {
|
6889
|
-
|
6890
|
-
|
6891
|
-
|
6892
|
-
|
6893
|
-
|
6738
|
+
if (!parentTag.subTags) {
|
6739
|
+
parentTag.subTags = [tag];
|
6740
|
+
}
|
6741
|
+
else {
|
6742
|
+
parentTag.subTags.push(tag);
|
6894
6743
|
}
|
6895
6744
|
}
|
6896
|
-
spaceIndex = Math.max(tag.plainTextBeginIndex, spaceIndex);
|
6897
|
-
spaceIndex = Math.min(tag.plainTextEndIndex, spaceIndex);
|
6898
|
-
return spaceIndex;
|
6899
6745
|
};
|
6900
|
-
|
6746
|
+
|
6747
|
+
// Copyright (c) Microsoft Corporation.
|
6901
6748
|
/**
|
6902
|
-
* Handle mention tag edit and by word deleting
|
6903
|
-
*
|
6904
6749
|
* @private
|
6905
|
-
*
|
6906
|
-
* @returns Updated texts and indexes.
|
6750
|
+
* z-index to ensure that chat container has lower z-index than mention popover
|
6907
6751
|
*/
|
6908
|
-
const
|
6909
|
-
|
6910
|
-
|
6911
|
-
|
6912
|
-
|
6913
|
-
|
6914
|
-
|
6915
|
-
|
6916
|
-
|
6917
|
-
|
6918
|
-
|
6919
|
-
|
6920
|
-
|
6921
|
-
|
6922
|
-
|
6923
|
-
|
6924
|
-
|
6925
|
-
|
6926
|
-
|
6927
|
-
|
6928
|
-
if (rangeStart !== -1 && rangeStart !== undefined && rangeStart > tag.plainTextBeginIndex) {
|
6929
|
-
isSpaceLengthHandled = true;
|
6930
|
-
}
|
6931
|
-
rangeEnd = oldPlainText.indexOf(' ', oldPlainTextEndIndex);
|
6932
|
-
if (rangeEnd === -1 || rangeEnd === undefined) {
|
6933
|
-
// check if space symbol is not found
|
6934
|
-
rangeEnd = plainTextEndIndex;
|
6935
|
-
}
|
6936
|
-
else if (!isSpaceLengthHandled) {
|
6937
|
-
// +1 to include the space symbol
|
6938
|
-
rangeEnd += 1;
|
6939
|
-
}
|
6940
|
-
isSpaceLengthHandled = true;
|
6941
|
-
if (rangeStart === -1 || rangeStart === undefined || rangeStart < tag.plainTextBeginIndex) {
|
6942
|
-
// rangeStart should be at least equal to tag.plainTextBeginIndex
|
6943
|
-
rangeStart = tag.plainTextBeginIndex;
|
6944
|
-
}
|
6945
|
-
if (rangeEnd > plainTextEndIndex) {
|
6946
|
-
// rangeEnd should be at most equal to plainTextEndIndex
|
6947
|
-
rangeEnd = plainTextEndIndex;
|
6948
|
-
}
|
6949
|
-
if (rangeStart === tag.plainTextBeginIndex && rangeEnd === plainTextEndIndex) {
|
6950
|
-
// the whole tag should be removed
|
6951
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
6952
|
-
plainTextSelectionEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
6953
|
-
processedChange = '';
|
6954
|
-
lastProcessedHTMLIndex = closeTagIdx + closeTagLength;
|
6955
|
-
}
|
6956
|
-
else {
|
6957
|
-
// only part of the tag should be removed
|
6958
|
-
let startChangeDiff = 0;
|
6959
|
-
let endChangeDiff = 0;
|
6960
|
-
// need to check only rangeStart > tag.plainTextBeginIndex as when rangeStart === tag.plainTextBeginIndex startChangeDiff = 0 and mentionTagLength shouldn't be subtracted
|
6961
|
-
if (rangeStart > tag.plainTextBeginIndex) {
|
6962
|
-
startChangeDiff = rangeStart - tag.plainTextBeginIndex - mentionTagLength;
|
6963
|
-
}
|
6964
|
-
endChangeDiff = rangeEnd - tag.plainTextBeginIndex - mentionTagLength;
|
6965
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff);
|
6966
|
-
if (startIndex < tag.plainTextBeginIndex) {
|
6967
|
-
// if the change is before the tag, the selection should start from startIndex (rangeStart will be equal to tag.plainTextBeginIndex)
|
6968
|
-
plainTextSelectionEndIndex = startIndex + change.length;
|
6752
|
+
const CHAT_CONTAINER_ZINDEX$1 = 1;
|
6753
|
+
/**
|
6754
|
+
* @private
|
6755
|
+
*/
|
6756
|
+
const mentionPopoverContainerStyle = (theme) => react.mergeStyles({
|
6757
|
+
boxShadow: theme.effects.elevation16,
|
6758
|
+
background: theme.semanticColors.bodyBackground,
|
6759
|
+
overflow: 'visible',
|
6760
|
+
// zIndex to set the mentionPopover above the chat container
|
6761
|
+
zIndex: CHAT_CONTAINER_ZINDEX$1 + 1
|
6762
|
+
});
|
6763
|
+
/**
|
6764
|
+
* @private
|
6765
|
+
*/
|
6766
|
+
const headerStyleThemed = (theme) => {
|
6767
|
+
return {
|
6768
|
+
root: {
|
6769
|
+
color: theme.palette.neutralSecondary,
|
6770
|
+
margin: '0.5rem 1rem 0.25rem',
|
6771
|
+
fontSize: theme.fonts.smallPlus.fontSize
|
6969
6772
|
}
|
6970
|
-
|
6971
|
-
|
6972
|
-
|
6773
|
+
};
|
6774
|
+
};
|
6775
|
+
/**
|
6776
|
+
* @private
|
6777
|
+
*/
|
6778
|
+
react.mergeStyles({
|
6779
|
+
height: '100%',
|
6780
|
+
overflowY: 'visible',
|
6781
|
+
overflowX: 'hidden'
|
6782
|
+
});
|
6783
|
+
/**
|
6784
|
+
* @private
|
6785
|
+
*/
|
6786
|
+
const suggestionListStyle = react.mergeStyles({
|
6787
|
+
padding: '0.25rem 0rem 0',
|
6788
|
+
overflow: 'visible'
|
6789
|
+
});
|
6790
|
+
/**
|
6791
|
+
* @private
|
6792
|
+
*/
|
6793
|
+
const suggestionItemWrapperStyle = (theme) => {
|
6794
|
+
return react.mergeStyles({
|
6795
|
+
margin: '0.05rem 0.1rem',
|
6796
|
+
'&:focus-visible': {
|
6797
|
+
outline: `${theme.palette.black} solid 0.1rem`
|
6973
6798
|
}
|
6974
|
-
|
6975
|
-
// processed change should not be changed as it should be added after the tag
|
6976
|
-
}
|
6977
|
-
return { result, updatedChange: processedChange, htmlIndex: lastProcessedHTMLIndex, plainTextSelectionEndIndex };
|
6799
|
+
});
|
6978
6800
|
};
|
6979
|
-
/* @conditional-compile-remove(mention) */
|
6980
6801
|
/**
|
6981
|
-
* Get closing tag information if exists otherwise return information as for self closing tag
|
6982
|
-
*
|
6983
6802
|
* @private
|
6984
|
-
* @param tag - Tag data.
|
6985
|
-
* @returns Closing tag information for the provided tag.
|
6986
6803
|
*/
|
6987
|
-
const
|
6988
|
-
|
6989
|
-
|
6990
|
-
|
6991
|
-
|
6992
|
-
|
6993
|
-
|
6994
|
-
|
6995
|
-
|
6996
|
-
closeTagLength = tag.tagType.length + 3;
|
6997
|
-
}
|
6998
|
-
else if (tag.plainTextBeginIndex !== undefined) {
|
6999
|
-
// no close tag
|
7000
|
-
plainTextEndIndex = tag.plainTextBeginIndex;
|
7001
|
-
closeTagIdx = tag.openTagIndex + tag.openTagBody.length;
|
7002
|
-
closeTagLength = 0;
|
7003
|
-
}
|
7004
|
-
return { plainTextEndIndex, closeTagIdx, closeTagLength };
|
6804
|
+
const suggestionItemStackStyle = (theme, isSuggestionHovered, activeBorder) => {
|
6805
|
+
return react.mergeStyles({
|
6806
|
+
width: '10rem',
|
6807
|
+
alignItems: 'center',
|
6808
|
+
height: '36px',
|
6809
|
+
padding: '0 0.75rem',
|
6810
|
+
background: isSuggestionHovered ? theme.palette.neutralLight : theme.palette.white,
|
6811
|
+
border: activeBorder ? `0.0625rem solid ${theme.palette.neutralSecondary}` : 'none'
|
6812
|
+
});
|
7005
6813
|
};
|
7006
|
-
|
6814
|
+
|
6815
|
+
// Copyright (c) Microsoft Corporation.
|
7007
6816
|
/**
|
7008
|
-
*
|
6817
|
+
* Component to render a pop-up of mention suggestions.
|
7009
6818
|
*
|
7010
|
-
* @
|
7011
|
-
* @param props - Props for update HTML function.
|
7012
|
-
* @returns Updated HTML and selection index if the selection index should be set.
|
6819
|
+
* @internal
|
7013
6820
|
*/
|
7014
|
-
const
|
7015
|
-
const {
|
7016
|
-
|
7017
|
-
|
7018
|
-
|
7019
|
-
|
7020
|
-
|
7021
|
-
|
7022
|
-
|
7023
|
-
|
7024
|
-
|
7025
|
-
|
7026
|
-
|
7027
|
-
|
7028
|
-
let processedChange = change;
|
7029
|
-
// end tag plain text index of the last processed tag
|
7030
|
-
let lastProcessedPlainTextTagEndIndex = 0;
|
7031
|
-
// as some tags/text can be removed fully, selection should be updated correctly
|
7032
|
-
let changeNewEndIndex;
|
7033
|
-
for (let i = 0; i < tags.length; i++) {
|
7034
|
-
const tag = tags[i];
|
7035
|
-
if (tag.plainTextBeginIndex === undefined) {
|
7036
|
-
continue;
|
6821
|
+
const _MentionPopover = (props) => {
|
6822
|
+
const { suggestions, activeSuggestionIndex, title, target, targetPositionOffset, onRenderSuggestionItem, onSuggestionSelected, onDismiss, location } = props;
|
6823
|
+
const theme = react.useTheme();
|
6824
|
+
/* @conditional-compile-remove(mention) */
|
6825
|
+
const ids = useIdentifiers();
|
6826
|
+
const localeStrings = useLocale$1().strings;
|
6827
|
+
const popoverRef = React.useRef();
|
6828
|
+
const [position, setPosition] = React.useState({ left: 0 });
|
6829
|
+
const [hoveredSuggestion, setHoveredSuggestion] = React.useState(undefined);
|
6830
|
+
const [changedSelection, setChangedSelection] = React.useState(undefined); // Selection UI as per teams
|
6831
|
+
const dismissPopoverWhenClickingOutside = React.useCallback((e) => {
|
6832
|
+
const target = e.target;
|
6833
|
+
if (popoverRef.current && !popoverRef.current.contains(target)) {
|
6834
|
+
onDismiss && onDismiss();
|
7037
6835
|
}
|
7038
|
-
|
7039
|
-
|
7040
|
-
|
7041
|
-
|
7042
|
-
let isMentionTag = false;
|
7043
|
-
if (tag.tagType === MSFT_MENTION_TAG) {
|
7044
|
-
mentionTagLength = mentionTrigger.length;
|
7045
|
-
isMentionTag = true;
|
6836
|
+
}, [onDismiss]);
|
6837
|
+
React.useEffect(() => {
|
6838
|
+
if (changedSelection === undefined) {
|
6839
|
+
setChangedSelection(false);
|
7046
6840
|
}
|
7047
|
-
if (
|
7048
|
-
|
7049
|
-
// Math.max(lastProcessedPlainTextTagEndIndex, startIndex) is used as startIndex may not be in [[previous tag].plainTextEndIndex - tag.plainTextBeginIndex] range
|
7050
|
-
const startChangeDiff = tag.plainTextBeginIndex - Math.max(lastProcessedPlainTextTagEndIndex, startIndex);
|
7051
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex - startChangeDiff) + processedChange;
|
7052
|
-
processedChange = '';
|
7053
|
-
if (oldPlainTextEndIndex <= tag.plainTextBeginIndex) {
|
7054
|
-
// the whole change is before tag start
|
7055
|
-
// mentionTag length can be ignored here as the change is before the tag
|
7056
|
-
const endChangeDiff = tag.plainTextBeginIndex - oldPlainTextEndIndex;
|
7057
|
-
lastProcessedHTMLIndex = tag.openTagIndex - endChangeDiff;
|
7058
|
-
// the change is handled; exit
|
7059
|
-
break;
|
7060
|
-
}
|
7061
|
-
else {
|
7062
|
-
// change continues in the tag
|
7063
|
-
lastProcessedHTMLIndex = tag.openTagIndex;
|
7064
|
-
// proceed to the next check
|
7065
|
-
}
|
6841
|
+
else if (changedSelection === false) {
|
6842
|
+
setChangedSelection(true);
|
7066
6843
|
}
|
7067
|
-
|
7068
|
-
|
7069
|
-
|
7070
|
-
|
7071
|
-
|
7072
|
-
|
7073
|
-
|
7074
|
-
|
7075
|
-
|
7076
|
-
|
6844
|
+
}, [activeSuggestionIndex, changedSelection]);
|
6845
|
+
React.useEffect(() => {
|
6846
|
+
window && window.addEventListener('click', dismissPopoverWhenClickingOutside);
|
6847
|
+
return () => {
|
6848
|
+
window && window.removeEventListener('click', dismissPopoverWhenClickingOutside);
|
6849
|
+
};
|
6850
|
+
}, [dismissPopoverWhenClickingOutside]);
|
6851
|
+
// Determine popover position
|
6852
|
+
React.useEffect(() => {
|
6853
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
6854
|
+
const rect = (_a = target === null || target === void 0 ? void 0 : target.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
6855
|
+
const maxWidth = 200;
|
6856
|
+
const finalPosition = { maxWidth };
|
6857
|
+
// Figure out whether it will fit horizontally
|
6858
|
+
const leftOffset = (_b = targetPositionOffset === null || targetPositionOffset === void 0 ? void 0 : targetPositionOffset.left) !== null && _b !== void 0 ? _b : 0;
|
6859
|
+
if (leftOffset + maxWidth > ((_c = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _c !== void 0 ? _c : 0)) {
|
6860
|
+
finalPosition.right = ((_d = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _d !== void 0 ? _d : 0) - leftOffset;
|
6861
|
+
}
|
6862
|
+
else {
|
6863
|
+
finalPosition.left = leftOffset;
|
6864
|
+
}
|
6865
|
+
if (location === 'below') {
|
6866
|
+
finalPosition.top = ((_e = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _e !== void 0 ? _e : 0) + ((_f = targetPositionOffset === null || targetPositionOffset === void 0 ? void 0 : targetPositionOffset.top) !== null && _f !== void 0 ? _f : 0);
|
6867
|
+
}
|
6868
|
+
else {
|
6869
|
+
// (location === 'above')
|
6870
|
+
finalPosition.bottom = ((_g = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _g !== void 0 ? _g : 0) - ((_h = targetPositionOffset === null || targetPositionOffset === void 0 ? void 0 : targetPositionOffset.top) !== null && _h !== void 0 ? _h : 0);
|
6871
|
+
}
|
6872
|
+
setPosition(finalPosition);
|
6873
|
+
}, [location, target, targetPositionOffset]);
|
6874
|
+
const handleOnKeyDown = React.useCallback((e) => {
|
6875
|
+
switch (e.key) {
|
6876
|
+
case 'Escape':
|
6877
|
+
onDismiss && onDismiss();
|
7077
6878
|
break;
|
7078
|
-
}
|
7079
|
-
else if (startIndex >= tag.plainTextBeginIndex && oldPlainTextEndIndex <= closingTagInfo.plainTextEndIndex) {
|
7080
|
-
// the change is between the tag
|
7081
|
-
if (isMentionTag) {
|
7082
|
-
if (change !== '') {
|
7083
|
-
if (startIndex !== tag.plainTextBeginIndex && startIndex !== closingTagInfo.plainTextEndIndex) {
|
7084
|
-
// mention tag should be deleted when user tries to edit it in the middle
|
7085
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
7086
|
-
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
7087
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
7088
|
-
}
|
7089
|
-
else if (startIndex === tag.plainTextBeginIndex) {
|
7090
|
-
// non empty change at the beginning of the mention tag to be added before the mention tag
|
7091
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex) + processedChange;
|
7092
|
-
changeNewEndIndex = tag.plainTextBeginIndex + processedChange.length;
|
7093
|
-
lastProcessedHTMLIndex = tag.openTagIndex;
|
7094
|
-
}
|
7095
|
-
else if (startIndex === closingTagInfo.plainTextEndIndex) {
|
7096
|
-
// non empty change at the end of the mention tag to be added after the mention tag
|
7097
|
-
result +=
|
7098
|
-
htmlText.substring(lastProcessedHTMLIndex, closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength) +
|
7099
|
-
processedChange;
|
7100
|
-
changeNewEndIndex = closingTagInfo.plainTextEndIndex + processedChange.length;
|
7101
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
7102
|
-
}
|
7103
|
-
processedChange = '';
|
7104
|
-
}
|
7105
|
-
else {
|
7106
|
-
const updateMentionTagResult = handleMentionTagUpdate({
|
7107
|
-
htmlText,
|
7108
|
-
oldPlainText,
|
7109
|
-
lastProcessedHTMLIndex,
|
7110
|
-
processedChange,
|
7111
|
-
change,
|
7112
|
-
tag,
|
7113
|
-
closeTagIdx: closingTagInfo.closeTagIdx,
|
7114
|
-
closeTagLength: closingTagInfo.closeTagLength,
|
7115
|
-
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
7116
|
-
startIndex,
|
7117
|
-
oldPlainTextEndIndex,
|
7118
|
-
mentionTagLength
|
7119
|
-
});
|
7120
|
-
result += updateMentionTagResult.result;
|
7121
|
-
changeNewEndIndex = updateMentionTagResult.plainTextSelectionEndIndex;
|
7122
|
-
processedChange = updateMentionTagResult.updatedChange;
|
7123
|
-
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
7124
|
-
}
|
7125
|
-
}
|
7126
|
-
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
7127
|
-
// with subtags
|
7128
|
-
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
7129
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
7130
|
-
const updatedContent = updateHTML({
|
7131
|
-
htmlText: tag.content,
|
7132
|
-
oldPlainText,
|
7133
|
-
newPlainText,
|
7134
|
-
tags: tag.subTags,
|
7135
|
-
startIndex,
|
7136
|
-
oldPlainTextEndIndex,
|
7137
|
-
change: processedChange,
|
7138
|
-
mentionTrigger
|
7139
|
-
});
|
7140
|
-
result += stringBefore + updatedContent.updatedHTML;
|
7141
|
-
changeNewEndIndex = updatedContent.updatedSelectionIndex;
|
7142
|
-
}
|
7143
|
-
else {
|
7144
|
-
// no subtags
|
7145
|
-
const startChangeDiff = startIndex - tag.plainTextBeginIndex;
|
7146
|
-
result +=
|
7147
|
-
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff) +
|
7148
|
-
processedChange;
|
7149
|
-
processedChange = '';
|
7150
|
-
if (oldPlainTextEndIndex < closingTagInfo.plainTextEndIndex) {
|
7151
|
-
const endChangeDiff = oldPlainTextEndIndex - tag.plainTextBeginIndex;
|
7152
|
-
lastProcessedHTMLIndex = tag.openTagIndex + tag.openTagBody.length + endChangeDiff;
|
7153
|
-
}
|
7154
|
-
else if (oldPlainTextEndIndex === closingTagInfo.plainTextEndIndex) {
|
7155
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
7156
|
-
}
|
7157
|
-
}
|
7158
|
-
// the change is handled; exit
|
7159
|
-
break;
|
7160
|
-
}
|
7161
|
-
else if (startIndex > tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
7162
|
-
// the change started in the tag but finishes somewhere further
|
7163
|
-
const startChangeDiff = startIndex - tag.plainTextBeginIndex - mentionTagLength;
|
7164
|
-
if (isMentionTag) {
|
7165
|
-
const updateMentionTagResult = handleMentionTagUpdate({
|
7166
|
-
htmlText,
|
7167
|
-
oldPlainText,
|
7168
|
-
lastProcessedHTMLIndex,
|
7169
|
-
processedChange: '',
|
7170
|
-
change,
|
7171
|
-
tag,
|
7172
|
-
closeTagIdx: closingTagInfo.closeTagIdx,
|
7173
|
-
closeTagLength: closingTagInfo.closeTagLength,
|
7174
|
-
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
7175
|
-
startIndex,
|
7176
|
-
oldPlainTextEndIndex,
|
7177
|
-
mentionTagLength
|
7178
|
-
});
|
7179
|
-
result += updateMentionTagResult.result;
|
7180
|
-
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
7181
|
-
// no need to handle plainTextSelectionEndIndex as the change will be added later
|
7182
|
-
}
|
7183
|
-
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
7184
|
-
// with subtags
|
7185
|
-
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
7186
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
7187
|
-
const updatedContent = updateHTML({
|
7188
|
-
htmlText: tag.content,
|
7189
|
-
oldPlainText,
|
7190
|
-
newPlainText,
|
7191
|
-
tags: tag.subTags,
|
7192
|
-
startIndex,
|
7193
|
-
oldPlainTextEndIndex,
|
7194
|
-
change: '',
|
7195
|
-
mentionTrigger
|
7196
|
-
});
|
7197
|
-
result += stringBefore + updatedContent.updatedHTML;
|
7198
|
-
}
|
7199
|
-
else {
|
7200
|
-
// no subtags
|
7201
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length + startChangeDiff);
|
7202
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
7203
|
-
}
|
7204
|
-
// proceed with the next calculations
|
7205
|
-
}
|
7206
|
-
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
7207
|
-
// the change starts before the tag and finishes after it
|
7208
|
-
// tag should be removed, no matter if there are subtags
|
7209
|
-
// no need to save anything between lastProcessedHTMLIndex and closeTagIdx + closeTagLength
|
7210
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
7211
|
-
// proceed with the next calculations
|
7212
|
-
}
|
7213
|
-
else if (startIndex === tag.plainTextBeginIndex && oldPlainTextEndIndex > closingTagInfo.plainTextEndIndex) {
|
7214
|
-
// the change starts in the tag and finishes after it
|
7215
|
-
// tag should be removed, no matter if there are subtags
|
7216
|
-
result += htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex);
|
7217
|
-
// processedChange shouldn't be updated as it will be added after the tag
|
7218
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx + closingTagInfo.closeTagLength;
|
7219
|
-
// proceed with the next calculations
|
7220
|
-
}
|
7221
|
-
else if (startIndex < tag.plainTextBeginIndex && oldPlainTextEndIndex < closingTagInfo.plainTextEndIndex) {
|
7222
|
-
// the change starts before the tag and ends in a tag
|
7223
|
-
if (isMentionTag) {
|
7224
|
-
// mention tag
|
7225
|
-
const updateMentionTagResult = handleMentionTagUpdate({
|
7226
|
-
htmlText,
|
7227
|
-
oldPlainText,
|
7228
|
-
lastProcessedHTMLIndex,
|
7229
|
-
processedChange: '',
|
7230
|
-
change,
|
7231
|
-
tag,
|
7232
|
-
closeTagIdx: closingTagInfo.closeTagIdx,
|
7233
|
-
closeTagLength: closingTagInfo.closeTagLength,
|
7234
|
-
plainTextEndIndex: closingTagInfo.plainTextEndIndex,
|
7235
|
-
startIndex,
|
7236
|
-
oldPlainTextEndIndex,
|
7237
|
-
mentionTagLength
|
7238
|
-
});
|
7239
|
-
changeNewEndIndex = updateMentionTagResult.plainTextSelectionEndIndex;
|
7240
|
-
result += updateMentionTagResult.result;
|
7241
|
-
lastProcessedHTMLIndex = updateMentionTagResult.htmlIndex;
|
7242
|
-
}
|
7243
|
-
else if (tag.subTags !== undefined && tag.subTags.length !== 0 && tag.content !== undefined) {
|
7244
|
-
// with subtags
|
7245
|
-
const stringBefore = htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length);
|
7246
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx;
|
7247
|
-
const updatedContent = updateHTML({
|
7248
|
-
htmlText: tag.content,
|
7249
|
-
oldPlainText,
|
7250
|
-
newPlainText,
|
7251
|
-
tags: tag.subTags,
|
7252
|
-
startIndex,
|
7253
|
-
oldPlainTextEndIndex,
|
7254
|
-
change: processedChange,
|
7255
|
-
mentionTrigger
|
7256
|
-
});
|
7257
|
-
processedChange = '';
|
7258
|
-
result += stringBefore + updatedContent.updatedHTML;
|
7259
|
-
}
|
7260
|
-
else {
|
7261
|
-
// no subtags
|
7262
|
-
result +=
|
7263
|
-
htmlText.substring(lastProcessedHTMLIndex, tag.openTagIndex + tag.openTagBody.length) + processedChange;
|
7264
|
-
processedChange = '';
|
7265
|
-
// oldPlainTextEndIndex already includes mentionTag length
|
7266
|
-
const endChangeDiff = closingTagInfo.plainTextEndIndex - oldPlainTextEndIndex;
|
7267
|
-
// as change may be before the end of the tag, we need to add the rest of the tag
|
7268
|
-
lastProcessedHTMLIndex = closingTagInfo.closeTagIdx - endChangeDiff;
|
7269
|
-
}
|
7270
|
-
// the change is handled; exit
|
7271
|
-
break;
|
7272
|
-
}
|
7273
|
-
lastProcessedPlainTextTagEndIndex = closingTagInfo.plainTextEndIndex;
|
7274
6879
|
}
|
7275
|
-
|
7276
|
-
|
7277
|
-
|
7278
|
-
|
7279
|
-
|
7280
|
-
|
7281
|
-
|
7282
|
-
|
6880
|
+
}, [onDismiss]);
|
6881
|
+
const personaRenderer = React.useCallback((displayName) => {
|
6882
|
+
const displayNamePlaceholder = localeStrings.participantItem.displayNamePlaceholder;
|
6883
|
+
const avatarOptions = {
|
6884
|
+
text: (displayName === null || displayName === void 0 ? void 0 : displayName.trim()) || displayNamePlaceholder,
|
6885
|
+
size: react.PersonaSize.size24,
|
6886
|
+
initialsColor: theme.palette.neutralLight,
|
6887
|
+
initialsTextColor: theme.palette.neutralSecondary,
|
6888
|
+
showOverflowTooltip: false,
|
6889
|
+
showUnknownPersonaCoin: !(displayName === null || displayName === void 0 ? void 0 : displayName.trim()) || displayName === displayNamePlaceholder
|
6890
|
+
};
|
6891
|
+
return React__default['default'].createElement(react.Persona, Object.assign({}, avatarOptions));
|
6892
|
+
}, [localeStrings, theme]);
|
6893
|
+
const defaultOnRenderSuggestionItem = React.useCallback((suggestion, onSuggestionSelected, active) => {
|
6894
|
+
return (React__default['default'].createElement("div", { "data-is-focusable": true, "data-ui-id": ids.mentionSuggestionItem, key: suggestion.id, onClick: () => onSuggestionSelected(suggestion), onMouseEnter: () => setHoveredSuggestion(suggestion), onMouseLeave: () => setHoveredSuggestion(undefined), onKeyDown: (e) => {
|
6895
|
+
handleOnKeyDown(e);
|
6896
|
+
}, className: suggestionItemWrapperStyle(theme) },
|
6897
|
+
React__default['default'].createElement(react.Stack, { horizontal: true, className: suggestionItemStackStyle(theme, (hoveredSuggestion === null || hoveredSuggestion === void 0 ? void 0 : hoveredSuggestion.id) === suggestion.id, (changedSelection !== null && changedSelection !== void 0 ? changedSelection : false) && active) }, personaRenderer(suggestion.displayText))));
|
6898
|
+
}, [
|
6899
|
+
handleOnKeyDown,
|
6900
|
+
theme,
|
6901
|
+
/* @conditional-compile-remove(mention) */
|
6902
|
+
ids,
|
6903
|
+
hoveredSuggestion,
|
6904
|
+
changedSelection,
|
6905
|
+
personaRenderer
|
6906
|
+
]);
|
6907
|
+
const getHeaderTitle = React.useCallback(() => {
|
6908
|
+
if (title) {
|
6909
|
+
return title;
|
6910
|
+
}
|
6911
|
+
/* @conditional-compile-remove(mention) */
|
6912
|
+
return localeStrings.mentionPopover.mentionPopoverHeader;
|
6913
|
+
}, [localeStrings, title]);
|
6914
|
+
return (React__default['default'].createElement("div", { ref: popoverRef },
|
6915
|
+
React__default['default'].createElement(react.Stack, { className: react.mergeStyles({
|
6916
|
+
maxHeight: 212,
|
6917
|
+
maxWidth: position.maxWidth
|
6918
|
+
}, mentionPopoverContainerStyle(theme), Object.assign(Object.assign({}, position), { position: 'absolute' })) },
|
6919
|
+
React__default['default'].createElement(react.Stack.Item, { styles: headerStyleThemed(theme), "aria-label": title }, getHeaderTitle()),
|
6920
|
+
React__default['default'].createElement(react.Stack
|
6921
|
+
/* @conditional-compile-remove(mention) */
|
6922
|
+
, { "data-ui-id": ids.mentionSuggestionList, className: suggestionListStyle }, suggestions.map((suggestion, index) => {
|
6923
|
+
const active = index === activeSuggestionIndex;
|
6924
|
+
return onRenderSuggestionItem
|
6925
|
+
? onRenderSuggestionItem(suggestion, onSuggestionSelected, active)
|
6926
|
+
: defaultOnRenderSuggestionItem(suggestion, onSuggestionSelected, active);
|
6927
|
+
})))));
|
6928
|
+
};
|
6929
|
+
|
6930
|
+
// Copyright (c) Microsoft Corporation.
|
6931
|
+
// Licensed under the MIT license.
|
6932
|
+
var __awaiter$w = (window && window.__awaiter) || function (thisArg, _arguments, P, generator) {
|
6933
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
6934
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
6935
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6936
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6937
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
6938
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
6939
|
+
});
|
6940
|
+
};
|
6941
|
+
const DEFAULT_MENTION_TRIGGER = '@';
|
6942
|
+
/**
|
6943
|
+
* @private
|
6944
|
+
*/
|
6945
|
+
const TextFieldWithMention = (props) => {
|
6946
|
+
const { textFieldProps, dataUiId, textValue, onChange, textFieldRef, onKeyDown, onEnterKeyDown, supportNewline, mentionLookupOptions } = props;
|
6947
|
+
const inputBoxRef = React.useRef(null);
|
6948
|
+
// Current suggestion list, provided by the callback
|
6949
|
+
const [mentionSuggestions, setMentionSuggestions] = React.useState([]);
|
6950
|
+
// Current suggestion list, provided by the callback
|
6951
|
+
const [activeSuggestionIndex, setActiveSuggestionIndex] = React.useState(undefined);
|
6952
|
+
// Index of the current trigger character in the text field
|
6953
|
+
const [currentTriggerStartIndex, setCurrentTriggerStartIndex] = React.useState(-1);
|
6954
|
+
const [inputTextValue, setInputTextValue] = React.useState('');
|
6955
|
+
const [tagsValue, setTagsValue] = React.useState([]);
|
6956
|
+
// Index of the previous selection start in the text field
|
6957
|
+
const [selectionStartValue, setSelectionStartValue] = React.useState();
|
6958
|
+
// Index of the previous selection end in the text field
|
6959
|
+
const [selectionEndValue, setSelectionEndValue] = React.useState();
|
6960
|
+
// Boolean value to check if onMouseDown event should be handled during select as selection range
|
6961
|
+
// for onMouseDown event is not updated yet and the selection range for mouse click/taps will be
|
6962
|
+
// updated in onSelect event if needed.
|
6963
|
+
const [shouldHandleOnMouseDownDuringSelect, setShouldHandleOnMouseDownDuringSelect] = React.useState(true);
|
6964
|
+
// Point of start of touch/mouse selection
|
6965
|
+
const [interactionStartPoint, setInteractionStartPoint] = React.useState();
|
6966
|
+
// Target selection from mouse movement
|
6967
|
+
const [targetSelection, setTargetSelection] = React.useState();
|
6968
|
+
// Caret position in the text field
|
6969
|
+
const [caretPosition, setCaretPosition] = React.useState(undefined);
|
6970
|
+
// Index of where the caret is in the text field
|
6971
|
+
const [caretIndex, setCaretIndex] = React.useState(undefined);
|
6972
|
+
const localeStrings = useLocale$1().strings;
|
6973
|
+
// Set mention suggestions
|
6974
|
+
const updateMentionSuggestions = React.useCallback((suggestions) => {
|
6975
|
+
setMentionSuggestions(suggestions);
|
6976
|
+
}, [setMentionSuggestions]);
|
6977
|
+
// Parse the text and get the plain text version to display in the input box
|
6978
|
+
React.useEffect(() => {
|
6979
|
+
const trigger = (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) || DEFAULT_MENTION_TRIGGER;
|
6980
|
+
const parsedHTMLData = textToTagParser(textValue, trigger);
|
6981
|
+
setInputTextValue(parsedHTMLData.plainText);
|
6982
|
+
setTagsValue(parsedHTMLData.tags);
|
6983
|
+
updateMentionSuggestions([]);
|
6984
|
+
}, [textValue, mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger, updateMentionSuggestions]);
|
6985
|
+
React.useEffect(() => {
|
6986
|
+
var _a;
|
6987
|
+
// effect for caret index update
|
6988
|
+
if (caretIndex === undefined || textFieldRef === undefined || (textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === undefined) {
|
6989
|
+
return;
|
6990
|
+
}
|
6991
|
+
// get validated caret index between 0 and inputTextValue.length otherwise caret will be set to incorrect index
|
6992
|
+
const updatedCaretIndex = getValidatedIndexInRange({
|
6993
|
+
min: 0,
|
6994
|
+
max: inputTextValue.length,
|
6995
|
+
currentValue: caretIndex
|
6996
|
+
});
|
6997
|
+
(_a = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _a === void 0 ? void 0 : _a.setSelectionRange(updatedCaretIndex, updatedCaretIndex);
|
6998
|
+
setSelectionStartValue(updatedCaretIndex);
|
6999
|
+
setSelectionEndValue(updatedCaretIndex);
|
7000
|
+
}, [caretIndex, inputTextValue.length, textFieldRef, setSelectionStartValue, setSelectionEndValue]);
|
7001
|
+
const onSuggestionSelected = React.useCallback((suggestion) => {
|
7002
|
+
var _a, _b, _c;
|
7003
|
+
let selectionEnd = ((_a = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _a === void 0 ? void 0 : _a.selectionEnd) || -1;
|
7004
|
+
if (selectionEnd < 0) {
|
7005
|
+
selectionEnd = 0;
|
7006
|
+
}
|
7007
|
+
else if (selectionEnd > inputTextValue.length) {
|
7008
|
+
selectionEnd = inputTextValue.length;
|
7009
|
+
}
|
7010
|
+
const oldPlainText = inputTextValue;
|
7011
|
+
const mention = htmlStringForMentionSuggestion(suggestion, localeStrings);
|
7012
|
+
// update plain text with the mention html text
|
7013
|
+
const newPlainText = inputTextValue.substring(0, currentTriggerStartIndex) + mention + inputTextValue.substring(selectionEnd);
|
7014
|
+
const triggerText = (_b = mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) !== null && _b !== void 0 ? _b : DEFAULT_MENTION_TRIGGER;
|
7015
|
+
// update html text with updated plain text
|
7016
|
+
const updatedContent = updateHTML({
|
7017
|
+
htmlText: textValue,
|
7018
|
+
oldPlainText,
|
7019
|
+
newPlainText,
|
7020
|
+
tags: tagsValue,
|
7021
|
+
startIndex: currentTriggerStartIndex,
|
7022
|
+
oldPlainTextEndIndex: selectionEnd,
|
7023
|
+
change: mention,
|
7024
|
+
mentionTrigger: triggerText
|
7025
|
+
});
|
7026
|
+
const displayName = getDisplayNameForMentionSuggestion(suggestion, localeStrings);
|
7027
|
+
const newCaretIndex = currentTriggerStartIndex + displayName.length + triggerText.length;
|
7028
|
+
// move the caret in the text field to the end of the mention plain text
|
7029
|
+
setCaretIndex(newCaretIndex);
|
7030
|
+
setSelectionEndValue(newCaretIndex);
|
7031
|
+
setSelectionStartValue(newCaretIndex);
|
7032
|
+
setCurrentTriggerStartIndex(-1);
|
7033
|
+
updateMentionSuggestions([]);
|
7034
|
+
// set focus back to text field
|
7035
|
+
(_c = textFieldRef === null || textFieldRef === void 0 ? void 0 : textFieldRef.current) === null || _c === void 0 ? void 0 : _c.focus();
|
7036
|
+
setActiveSuggestionIndex(undefined);
|
7037
|
+
onChange && onChange(undefined, updatedContent.updatedHTML);
|
7038
|
+
}, [
|
7039
|
+
textFieldRef,
|
7040
|
+
inputTextValue,
|
7041
|
+
currentTriggerStartIndex,
|
7042
|
+
mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger,
|
7043
|
+
onChange,
|
7044
|
+
textValue,
|
7045
|
+
tagsValue,
|
7046
|
+
updateMentionSuggestions,
|
7047
|
+
localeStrings
|
7048
|
+
]);
|
7049
|
+
const onTextFieldKeyDown = React.useCallback((ev) => {
|
7050
|
+
// caretIndex should be set to undefined when the user is typing
|
7051
|
+
setCaretIndex(undefined);
|
7052
|
+
// shouldHandleOnMouseDownDuringSelect should be set to false after the last mouse down event.
|
7053
|
+
// it shouldn't be updated in onMouseUp
|
7054
|
+
// as onMouseUp can be triggered before or after onSelect event
|
7055
|
+
// because its order depends on mouse events not selection.
|
7056
|
+
setShouldHandleOnMouseDownDuringSelect(false);
|
7057
|
+
if (isEnterKeyEventFromCompositionSession(ev)) {
|
7058
|
+
return;
|
7059
|
+
}
|
7060
|
+
if (mentionSuggestions.length > 0) {
|
7061
|
+
if (ev.key === 'ArrowUp') {
|
7062
|
+
ev.preventDefault();
|
7063
|
+
const newActiveIndex = activeSuggestionIndex === undefined
|
7064
|
+
? mentionSuggestions.length - 1
|
7065
|
+
: Math.max(activeSuggestionIndex - 1, 0);
|
7066
|
+
setActiveSuggestionIndex(newActiveIndex);
|
7283
7067
|
}
|
7284
|
-
else {
|
7285
|
-
|
7286
|
-
|
7287
|
-
|
7068
|
+
else if (ev.key === 'ArrowDown') {
|
7069
|
+
ev.preventDefault();
|
7070
|
+
const newActiveIndex = activeSuggestionIndex === undefined
|
7071
|
+
? 0
|
7072
|
+
: Math.min(activeSuggestionIndex + 1, mentionSuggestions.length - 1);
|
7073
|
+
setActiveSuggestionIndex(newActiveIndex);
|
7288
7074
|
}
|
7289
|
-
|
7290
|
-
|
7291
|
-
// the change is handled; exit
|
7292
|
-
// break is not required here as this is the last element but added for consistency
|
7293
|
-
break;
|
7294
|
-
}
|
7295
|
-
}
|
7296
|
-
if (lastProcessedHTMLIndex < htmlText.length) {
|
7297
|
-
// add the rest of the html string
|
7298
|
-
result += htmlText.substring(lastProcessedHTMLIndex);
|
7299
|
-
}
|
7300
|
-
return { updatedHTML: result, updatedSelectionIndex: changeNewEndIndex };
|
7301
|
-
};
|
7302
|
-
/* @conditional-compile-remove(mention) */
|
7303
|
-
/**
|
7304
|
-
* Given the oldText and newText, find the start index, old end index and new end index for the changes
|
7305
|
-
*
|
7306
|
-
* @private
|
7307
|
-
* @param props - Props for finding stings diff indexes function.
|
7308
|
-
* @returns Indexes for change start and ends in new and old texts. The old and new end indexes are exclusive.
|
7309
|
-
*/
|
7310
|
-
const findStringsDiffIndexes = (props) => {
|
7311
|
-
const { oldText, newText, previousSelectionStart, previousSelectionEnd, currentSelectionStart, currentSelectionEnd } = props;
|
7312
|
-
const newTextLength = newText.length;
|
7313
|
-
const oldTextLength = oldText.length;
|
7314
|
-
// let changeStart = 0;
|
7315
|
-
let newChangeEnd = newTextLength;
|
7316
|
-
let oldChangeEnd = oldTextLength;
|
7317
|
-
const previousSelectionStartValue = previousSelectionStart > -1 ? previousSelectionStart : oldTextLength;
|
7318
|
-
const previousSelectionEndValue = previousSelectionEnd > -1 ? previousSelectionEnd : oldTextLength;
|
7319
|
-
const currentSelectionStartValue = currentSelectionStart > -1 ? currentSelectionStart : newTextLength;
|
7320
|
-
const currentSelectionEndValue = currentSelectionEnd > -1 ? currentSelectionEnd : newTextLength;
|
7321
|
-
const changeStart = Math.min(previousSelectionStartValue, previousSelectionEndValue, currentSelectionStartValue, currentSelectionEndValue, newTextLength, oldTextLength);
|
7322
|
-
if (oldTextLength < newTextLength) {
|
7323
|
-
//insert or replacement
|
7324
|
-
if (oldTextLength === changeStart) {
|
7325
|
-
// when change was at the end of string
|
7326
|
-
// change is found
|
7327
|
-
newChangeEnd = newTextLength;
|
7328
|
-
oldChangeEnd = oldTextLength;
|
7329
|
-
}
|
7330
|
-
else {
|
7331
|
-
for (let i = 1; i < newTextLength && oldTextLength - i >= changeStart; i++) {
|
7332
|
-
newChangeEnd = newTextLength - i - 1;
|
7333
|
-
oldChangeEnd = oldTextLength - i - 1;
|
7334
|
-
if (newText[newChangeEnd] !== oldText[oldChangeEnd]) {
|
7335
|
-
// change is found
|
7336
|
-
break;
|
7337
|
-
}
|
7075
|
+
else if (ev.key === 'Escape') {
|
7076
|
+
updateMentionSuggestions([]);
|
7338
7077
|
}
|
7339
|
-
// make indexes exclusive
|
7340
|
-
newChangeEnd += 1;
|
7341
|
-
oldChangeEnd += 1;
|
7342
|
-
}
|
7343
|
-
}
|
7344
|
-
else if (oldTextLength > newTextLength) {
|
7345
|
-
//deletion or replacement
|
7346
|
-
if (newTextLength === changeStart) {
|
7347
|
-
// when change was at the end of string
|
7348
|
-
// change is found
|
7349
|
-
newChangeEnd = newTextLength;
|
7350
|
-
oldChangeEnd = oldTextLength;
|
7351
7078
|
}
|
7352
|
-
|
7353
|
-
|
7354
|
-
|
7355
|
-
|
7356
|
-
|
7357
|
-
|
7358
|
-
|
7079
|
+
if (ev.key === 'Enter' && (ev.shiftKey === false || !supportNewline)) {
|
7080
|
+
ev.preventDefault();
|
7081
|
+
// If we are looking up a mention, select the focused suggestion
|
7082
|
+
if (mentionSuggestions.length > 0 && activeSuggestionIndex !== undefined) {
|
7083
|
+
const selectedMention = mentionSuggestions[activeSuggestionIndex];
|
7084
|
+
if (selectedMention) {
|
7085
|
+
onSuggestionSelected(selectedMention);
|
7086
|
+
return;
|
7359
7087
|
}
|
7360
7088
|
}
|
7361
|
-
|
7362
|
-
newChangeEnd += 1;
|
7363
|
-
oldChangeEnd += 1;
|
7089
|
+
onEnterKeyDown && onEnterKeyDown();
|
7364
7090
|
}
|
7365
|
-
|
7366
|
-
|
7367
|
-
|
7368
|
-
|
7369
|
-
|
7370
|
-
|
7371
|
-
|
7372
|
-
|
7373
|
-
|
7374
|
-
|
7091
|
+
onKeyDown && onKeyDown(ev);
|
7092
|
+
}, [
|
7093
|
+
onEnterKeyDown,
|
7094
|
+
onKeyDown,
|
7095
|
+
supportNewline,
|
7096
|
+
mentionSuggestions,
|
7097
|
+
activeSuggestionIndex,
|
7098
|
+
onSuggestionSelected,
|
7099
|
+
updateMentionSuggestions
|
7100
|
+
]);
|
7101
|
+
const debouncedQueryUpdate = useDebounce.useDebouncedCallback((query) => __awaiter$w(void 0, void 0, void 0, function* () {
|
7102
|
+
var _a;
|
7103
|
+
const suggestions = (_a = (yield (mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onQueryUpdated(query)))) !== null && _a !== void 0 ? _a : [];
|
7104
|
+
if (suggestions.length === 0) {
|
7105
|
+
setActiveSuggestionIndex(undefined);
|
7375
7106
|
}
|
7376
|
-
|
7377
|
-
|
7378
|
-
|
7107
|
+
else if (activeSuggestionIndex === undefined) {
|
7108
|
+
// Set the active to the first, if it's not already set
|
7109
|
+
setActiveSuggestionIndex(0);
|
7379
7110
|
}
|
7380
|
-
|
7381
|
-
|
7111
|
+
updateMentionSuggestions(suggestions);
|
7112
|
+
}), 500);
|
7113
|
+
// Update selections index in mention to navigate by words
|
7114
|
+
const updateSelectionIndexesWithMentionIfNeeded = React.useCallback(({ event, inputTextValue, selectionEndValue, selectionStartValue, tagsValue }) => {
|
7115
|
+
var _a, _b, _c;
|
7116
|
+
let updatedStartIndex = event.currentTarget.selectionStart;
|
7117
|
+
let updatedEndIndex = event.currentTarget.selectionEnd;
|
7118
|
+
if (event.currentTarget.selectionStart === event.currentTarget.selectionEnd &&
|
7119
|
+
event.currentTarget.selectionStart !== null &&
|
7120
|
+
event.currentTarget.selectionStart !== -1) {
|
7121
|
+
// just a caret movement/usual typing or deleting
|
7122
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
7123
|
+
// don't include boundary cases to show correct selection, otherwise it will show selection at mention boundaries
|
7124
|
+
if (mentionTag !== undefined &&
|
7125
|
+
mentionTag.plainTextBeginIndex !== undefined &&
|
7126
|
+
event.currentTarget.selectionStart > mentionTag.plainTextBeginIndex &&
|
7127
|
+
event.currentTarget.selectionStart < ((_a = mentionTag.plainTextEndIndex) !== null && _a !== void 0 ? _a : mentionTag.plainTextBeginIndex)) {
|
7128
|
+
// get updated selection index
|
7129
|
+
const newSelectionIndex = findNewSelectionIndexForMention({
|
7130
|
+
tag: mentionTag,
|
7131
|
+
textValue: inputTextValue,
|
7132
|
+
currentSelectionIndex: event.currentTarget.selectionStart,
|
7133
|
+
previousSelectionIndex: selectionStartValue !== null && selectionStartValue !== void 0 ? selectionStartValue : inputTextValue.length
|
7134
|
+
});
|
7135
|
+
updatedStartIndex = newSelectionIndex;
|
7136
|
+
updatedEndIndex = newSelectionIndex;
|
7137
|
+
}
|
7382
7138
|
}
|
7383
|
-
|
7384
|
-
|
7385
|
-
|
7386
|
-
|
7387
|
-
|
7388
|
-
|
7389
|
-
|
7390
|
-
|
7391
|
-
|
7392
|
-
|
7393
|
-
|
7394
|
-
|
7395
|
-
|
7396
|
-
|
7397
|
-
|
7398
|
-
|
7399
|
-
|
7400
|
-
};
|
7401
|
-
/* @conditional-compile-remove(mention) */
|
7402
|
-
/**
|
7403
|
-
* Get display name for the mention suggestion.
|
7404
|
-
*
|
7405
|
-
* @private
|
7406
|
-
*
|
7407
|
-
* @param suggestion - The mention suggestion.
|
7408
|
-
* @param localeStrings - The locale strings.
|
7409
|
-
* @returns The display name for the mention suggestion or display name placeholder if display name is empty.
|
7410
|
-
*/
|
7411
|
-
const getDisplayNameForMentionSuggestion = (suggestion, localeStrings) => {
|
7412
|
-
const displayNamePlaceholder = localeStrings.participantItem.displayNamePlaceholder;
|
7413
|
-
return suggestion.displayText !== '' ? suggestion.displayText : displayNamePlaceholder !== null && displayNamePlaceholder !== void 0 ? displayNamePlaceholder : '';
|
7414
|
-
};
|
7415
|
-
/* @conditional-compile-remove(mention) */
|
7416
|
-
/**
|
7417
|
-
* Parse the text and return the tags and the plain text in one go
|
7418
|
-
* @private
|
7419
|
-
* @param text - The text to parse for HTML tags
|
7420
|
-
* @param trigger The trigger to show for the mention tag in plain text
|
7421
|
-
*
|
7422
|
-
* @returns An array of tags and the plain text representation
|
7423
|
-
*/
|
7424
|
-
const textToTagParser = (text, trigger) => {
|
7425
|
-
var _a, _b;
|
7426
|
-
const tags = []; // Tags passed back to the caller
|
7427
|
-
const tagParseStack = []; // Local stack to use while parsing
|
7428
|
-
let plainTextRepresentation = '';
|
7429
|
-
let parseIndex = 0;
|
7430
|
-
while (parseIndex < text.length) {
|
7431
|
-
const foundHtmlTag = findNextHtmlTag(text, parseIndex);
|
7432
|
-
if (!foundHtmlTag) {
|
7433
|
-
if (parseIndex !== 0) {
|
7434
|
-
// Add the remaining text to the plain text representation
|
7435
|
-
plainTextRepresentation += text.substring(parseIndex);
|
7139
|
+
else if (event.currentTarget.selectionStart !== event.currentTarget.selectionEnd) {
|
7140
|
+
// Both e.currentTarget.selectionStart !== selectionStartValue and e.currentTarget.selectionEnd !== selectionEndValue can be true when a user selects a text by double click
|
7141
|
+
if (event.currentTarget.selectionStart !== null && event.currentTarget.selectionStart !== selectionStartValue) {
|
7142
|
+
// the selection start is changed
|
7143
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionStart);
|
7144
|
+
// don't include boundary cases to show correct selection, otherwise it will show selection at mention boundaries
|
7145
|
+
if (mentionTag !== undefined &&
|
7146
|
+
mentionTag.plainTextBeginIndex !== undefined &&
|
7147
|
+
event.currentTarget.selectionStart > mentionTag.plainTextBeginIndex &&
|
7148
|
+
event.currentTarget.selectionStart < ((_b = mentionTag.plainTextEndIndex) !== null && _b !== void 0 ? _b : mentionTag.plainTextBeginIndex)) {
|
7149
|
+
updatedStartIndex = findNewSelectionIndexForMention({
|
7150
|
+
tag: mentionTag,
|
7151
|
+
textValue: inputTextValue,
|
7152
|
+
currentSelectionIndex: event.currentTarget.selectionStart,
|
7153
|
+
previousSelectionIndex: selectionStartValue !== null && selectionStartValue !== void 0 ? selectionStartValue : inputTextValue.length
|
7154
|
+
});
|
7155
|
+
}
|
7436
7156
|
}
|
7437
|
-
|
7438
|
-
|
7157
|
+
if (event.currentTarget.selectionEnd !== null && event.currentTarget.selectionEnd !== selectionEndValue) {
|
7158
|
+
// the selection end is changed
|
7159
|
+
const mentionTag = findMentionTagForSelection(tagsValue, event.currentTarget.selectionEnd);
|
7160
|
+
// don't include boundary cases to show correct selection, otherwise it will show selection at mention boundaries
|
7161
|
+
if (mentionTag !== undefined &&
|
7162
|
+
mentionTag.plainTextBeginIndex !== undefined &&
|
7163
|
+
event.currentTarget.selectionEnd > mentionTag.plainTextBeginIndex &&
|
7164
|
+
event.currentTarget.selectionEnd < ((_c = mentionTag.plainTextEndIndex) !== null && _c !== void 0 ? _c : mentionTag.plainTextBeginIndex)) {
|
7165
|
+
updatedEndIndex = findNewSelectionIndexForMention({
|
7166
|
+
tag: mentionTag,
|
7167
|
+
textValue: inputTextValue,
|
7168
|
+
currentSelectionIndex: event.currentTarget.selectionEnd,
|
7169
|
+
previousSelectionIndex: selectionEndValue !== null && selectionEndValue !== void 0 ? selectionEndValue : inputTextValue.length
|
7170
|
+
});
|
7171
|
+
}
|
7439
7172
|
}
|
7440
|
-
break;
|
7441
7173
|
}
|
7442
|
-
|
7443
|
-
|
7444
|
-
|
7445
|
-
|
7446
|
-
|
7447
|
-
|
7448
|
-
|
7174
|
+
// e.currentTarget.selectionDirection should be set to handle shift + arrow keys
|
7175
|
+
if (event.currentTarget.selectionDirection === null) {
|
7176
|
+
event.currentTarget.setSelectionRange(updatedStartIndex, updatedEndIndex);
|
7177
|
+
}
|
7178
|
+
else {
|
7179
|
+
event.currentTarget.setSelectionRange(updatedStartIndex, updatedEndIndex, event.currentTarget.selectionDirection);
|
7180
|
+
}
|
7181
|
+
setSelectionStartValue(nullToUndefined(updatedStartIndex));
|
7182
|
+
setSelectionEndValue(nullToUndefined(updatedEndIndex));
|
7183
|
+
}, [setSelectionStartValue, setSelectionEndValue]);
|
7184
|
+
const handleOnSelect = React.useCallback(({ event, inputTextValue, tags, shouldHandleOnMouseDownDuringSelect, selectionStartValue, selectionEndValue }) => {
|
7185
|
+
if (shouldHandleOnMouseDownDuringSelect) {
|
7186
|
+
if (targetSelection !== undefined) {
|
7187
|
+
setSelectionStartValue(targetSelection.start);
|
7188
|
+
setSelectionEndValue(targetSelection.end);
|
7189
|
+
event.currentTarget.setSelectionRange(targetSelection.start, undefinedToNull(targetSelection.end));
|
7190
|
+
setTargetSelection(undefined);
|
7449
7191
|
}
|
7450
|
-
else {
|
7451
|
-
|
7452
|
-
|
7453
|
-
|
7454
|
-
|
7192
|
+
else if (event.currentTarget.selectionStart !== null) {
|
7193
|
+
// on select was triggered by mouse down/up with no movement
|
7194
|
+
const mentionTag = findMentionTagForSelection(tags, event.currentTarget.selectionStart);
|
7195
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
7196
|
+
// handle mention click
|
7197
|
+
// Get range of word that was clicked on
|
7198
|
+
const selectionRange = rangeOfWordInSelection({
|
7199
|
+
textInput: inputTextValue,
|
7200
|
+
selectionStart: event.currentTarget.selectionStart,
|
7201
|
+
selectionEnd: nullToUndefined(event.currentTarget.selectionEnd),
|
7202
|
+
tag: mentionTag
|
7203
|
+
});
|
7204
|
+
if (event.currentTarget.selectionDirection === null) {
|
7205
|
+
event.currentTarget.setSelectionRange(selectionRange.start, selectionRange.end);
|
7206
|
+
}
|
7207
|
+
else {
|
7208
|
+
event.currentTarget.setSelectionRange(selectionRange.start, selectionRange.end, event.currentTarget.selectionDirection);
|
7209
|
+
}
|
7210
|
+
setSelectionStartValue(selectionRange.start);
|
7211
|
+
setSelectionEndValue(selectionRange.end);
|
7212
|
+
}
|
7213
|
+
else {
|
7214
|
+
setSelectionStartValue(event.currentTarget.selectionStart);
|
7215
|
+
setSelectionEndValue(nullToUndefined(event.currentTarget.selectionEnd));
|
7216
|
+
}
|
7455
7217
|
}
|
7456
7218
|
}
|
7457
|
-
|
7458
|
-
|
7459
|
-
|
7460
|
-
|
7461
|
-
|
7462
|
-
|
7463
|
-
|
7464
|
-
|
7465
|
-
|
7466
|
-
|
7467
|
-
|
7468
|
-
|
7219
|
+
else {
|
7220
|
+
// selection was changed by keyboard
|
7221
|
+
updateSelectionIndexesWithMentionIfNeeded({
|
7222
|
+
event,
|
7223
|
+
inputTextValue,
|
7224
|
+
selectionStartValue,
|
7225
|
+
selectionEndValue,
|
7226
|
+
tagsValue: tags
|
7227
|
+
});
|
7228
|
+
}
|
7229
|
+
// don't set setShouldHandleOnMouseDownDuringSelect(false) here as setSelectionRange
|
7230
|
+
// could trigger additional calls of onSelect event and they may not be handled correctly
|
7231
|
+
// (because of setSelectionRange calls or rerender)
|
7232
|
+
}, [
|
7233
|
+
updateSelectionIndexesWithMentionIfNeeded,
|
7234
|
+
targetSelection,
|
7235
|
+
setTargetSelection,
|
7236
|
+
setSelectionStartValue,
|
7237
|
+
setSelectionEndValue
|
7238
|
+
]);
|
7239
|
+
const handleOnChange = React.useCallback(({ currentSelectionEnd, currentSelectionStart, currentTriggerStartIndex, event, htmlTextValue, inputTextValue, previousSelectionEnd, previousSelectionStart, tagsValue, updatedValue }) => __awaiter$w(void 0, void 0, void 0, function* () {
|
7240
|
+
var _b;
|
7241
|
+
debouncedQueryUpdate.cancel();
|
7242
|
+
if (event.currentTarget === null) {
|
7243
|
+
return;
|
7244
|
+
}
|
7245
|
+
// handle backspace change
|
7246
|
+
// onSelect is not called for backspace as selection is not changed and local caret index is outdated
|
7247
|
+
setCaretIndex(undefined);
|
7248
|
+
const newValue = updatedValue !== null && updatedValue !== void 0 ? updatedValue : '';
|
7249
|
+
const triggerText = (_b = mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.trigger) !== null && _b !== void 0 ? _b : DEFAULT_MENTION_TRIGGER;
|
7250
|
+
const newTextLength = newValue.length;
|
7251
|
+
// updating indexes to set between 0 and text length, otherwise selectionRange won't be set correctly
|
7252
|
+
const currentSelectionEndValue = getValidatedIndexInRange({
|
7253
|
+
min: 0,
|
7254
|
+
max: newTextLength,
|
7255
|
+
currentValue: currentSelectionEnd
|
7256
|
+
});
|
7257
|
+
const currentSelectionStartValue = getValidatedIndexInRange({
|
7258
|
+
min: 0,
|
7259
|
+
max: newTextLength,
|
7260
|
+
currentValue: currentSelectionStart
|
7261
|
+
});
|
7262
|
+
const previousSelectionStartValue = getValidatedIndexInRange({
|
7263
|
+
min: 0,
|
7264
|
+
max: inputTextValue.length,
|
7265
|
+
currentValue: previousSelectionStart
|
7266
|
+
});
|
7267
|
+
const previousSelectionEndValue = getValidatedIndexInRange({
|
7268
|
+
min: 0,
|
7269
|
+
max: inputTextValue.length,
|
7270
|
+
currentValue: previousSelectionEnd
|
7271
|
+
});
|
7272
|
+
// If we are enabled for lookups,
|
7273
|
+
if (mentionLookupOptions !== undefined) {
|
7274
|
+
// Look at the range of the change for a trigger character
|
7275
|
+
const triggerPriorIndex = newValue.lastIndexOf(triggerText, currentSelectionEndValue - 1);
|
7276
|
+
// Update the caret position, if not doing a lookup
|
7277
|
+
setCaretPosition(textareaCaretTs.Caret.getRelativePosition(event.currentTarget));
|
7278
|
+
if (triggerPriorIndex !== undefined) {
|
7279
|
+
// trigger is found
|
7280
|
+
const isSpaceBeforeTrigger = newValue.substring(triggerPriorIndex - 1, triggerPriorIndex) === ' ';
|
7281
|
+
const wordAtSelection = newValue.substring(triggerPriorIndex, currentSelectionEndValue);
|
7282
|
+
let tagIndex = currentTriggerStartIndex;
|
7283
|
+
if (!isSpaceBeforeTrigger && triggerPriorIndex !== 0) {
|
7284
|
+
//no space before the trigger <- continuation of the previous word
|
7285
|
+
tagIndex = -1;
|
7286
|
+
setCurrentTriggerStartIndex(tagIndex);
|
7469
7287
|
}
|
7470
|
-
if (
|
7471
|
-
|
7288
|
+
else if (wordAtSelection === triggerText) {
|
7289
|
+
// start of the mention
|
7290
|
+
tagIndex = currentSelectionEndValue - triggerText.length;
|
7291
|
+
if (tagIndex < 0) {
|
7292
|
+
tagIndex = 0;
|
7293
|
+
}
|
7294
|
+
setCurrentTriggerStartIndex(tagIndex);
|
7472
7295
|
}
|
7473
|
-
|
7474
|
-
|
7475
|
-
|
7476
|
-
|
7477
|
-
|
7478
|
-
|
7296
|
+
if (tagIndex === -1) {
|
7297
|
+
updateMentionSuggestions([]);
|
7298
|
+
}
|
7299
|
+
else {
|
7300
|
+
// In the middle of a @mention lookup
|
7301
|
+
if (tagIndex > -1) {
|
7302
|
+
const query = wordAtSelection.substring(triggerText.length, wordAtSelection.length);
|
7303
|
+
if (query !== undefined) {
|
7304
|
+
yield debouncedQueryUpdate(query);
|
7305
|
+
}
|
7306
|
+
}
|
7479
7307
|
}
|
7480
|
-
currentOpenTag.plainTextEndIndex = plainTextRepresentation.length;
|
7481
|
-
addTag(currentOpenTag, tagParseStack, tags);
|
7482
7308
|
}
|
7483
|
-
|
7484
|
-
|
7485
|
-
|
7486
|
-
|
7487
|
-
|
7488
|
-
|
7309
|
+
}
|
7310
|
+
let result = '';
|
7311
|
+
if (tagsValue.length === 0) {
|
7312
|
+
// no tags in the string and newValue should be used as a result string
|
7313
|
+
result = newValue;
|
7314
|
+
}
|
7315
|
+
else {
|
7316
|
+
// there are tags in the text value and htmlTextValue is html string
|
7317
|
+
// find diff between old and new text
|
7318
|
+
const { changeStart, oldChangeEnd, newChangeEnd } = findStringsDiffIndexes({
|
7319
|
+
oldText: inputTextValue,
|
7320
|
+
newText: newValue,
|
7321
|
+
previousSelectionStart: previousSelectionStartValue,
|
7322
|
+
previousSelectionEnd: previousSelectionEndValue,
|
7323
|
+
currentSelectionStart: currentSelectionStartValue,
|
7324
|
+
currentSelectionEnd: currentSelectionEndValue
|
7325
|
+
});
|
7326
|
+
const change = newValue.substring(changeStart, newChangeEnd);
|
7327
|
+
// get updated html string
|
7328
|
+
const updatedContent = updateHTML({
|
7329
|
+
htmlText: htmlTextValue,
|
7330
|
+
oldPlainText: inputTextValue,
|
7331
|
+
newPlainText: newValue,
|
7332
|
+
tags: tagsValue,
|
7333
|
+
startIndex: changeStart,
|
7334
|
+
oldPlainTextEndIndex: oldChangeEnd,
|
7335
|
+
change,
|
7336
|
+
mentionTrigger: triggerText
|
7337
|
+
});
|
7338
|
+
result = updatedContent.updatedHTML;
|
7339
|
+
// update caret index if needed
|
7340
|
+
if (updatedContent.updatedSelectionIndex !== undefined) {
|
7341
|
+
setCaretIndex(updatedContent.updatedSelectionIndex);
|
7342
|
+
setSelectionEndValue(updatedContent.updatedSelectionIndex);
|
7343
|
+
setSelectionStartValue(updatedContent.updatedSelectionIndex);
|
7344
|
+
}
|
7345
|
+
}
|
7346
|
+
onChange && onChange(event, result);
|
7347
|
+
}), [onChange, mentionLookupOptions, setCaretIndex, setCaretPosition, updateMentionSuggestions, debouncedQueryUpdate]);
|
7348
|
+
// Adjust the selection range based on a mouse / touch interaction
|
7349
|
+
const handleOnMove = React.useCallback((event) => {
|
7350
|
+
var _a;
|
7351
|
+
let targetStart = event.currentTarget.selectionStart;
|
7352
|
+
let targetEnd = event.currentTarget.selectionEnd;
|
7353
|
+
// Should we do anything?
|
7354
|
+
if (interactionStartPoint !== undefined &&
|
7355
|
+
// And did selection change?
|
7356
|
+
targetStart !== null &&
|
7357
|
+
(targetStart !== (targetSelection === null || targetSelection === void 0 ? void 0 : targetSelection.start) || targetEnd !== (targetSelection === null || targetSelection === void 0 ? void 0 : targetSelection.end))) {
|
7358
|
+
const direction = event.clientX > interactionStartPoint.x ? 'forward' : 'backward';
|
7359
|
+
const mentionTag = findMentionTagForSelection(tagsValue, direction === 'backward'
|
7360
|
+
? event.currentTarget.selectionStart
|
7361
|
+
: (_a = event.currentTarget.selectionEnd) !== null && _a !== void 0 ? _a : event.currentTarget.selectionStart);
|
7362
|
+
let updateCurrentTarget = false;
|
7363
|
+
if (mentionTag !== undefined && mentionTag.plainTextBeginIndex !== undefined) {
|
7364
|
+
targetStart = Math.min(mentionTag.plainTextBeginIndex, targetStart);
|
7365
|
+
if (mentionTag.plainTextEndIndex !== undefined && targetEnd !== null) {
|
7366
|
+
targetEnd = Math.max(mentionTag.plainTextEndIndex, targetEnd);
|
7367
|
+
}
|
7368
|
+
updateCurrentTarget = true;
|
7369
|
+
setShouldHandleOnMouseDownDuringSelect(false);
|
7370
|
+
}
|
7371
|
+
// Update selection range
|
7372
|
+
setTargetSelection({ start: targetStart, end: targetEnd });
|
7373
|
+
if (updateCurrentTarget) {
|
7374
|
+
// Only set the control, if the values are updated
|
7375
|
+
event.currentTarget.setSelectionRange(targetStart, targetEnd, direction);
|
7489
7376
|
}
|
7490
7377
|
}
|
7491
|
-
|
7492
|
-
|
7493
|
-
|
7494
|
-
|
7495
|
-
}
|
7496
|
-
|
7497
|
-
|
7498
|
-
|
7499
|
-
|
7500
|
-
|
7501
|
-
|
7502
|
-
.
|
7503
|
-
|
7504
|
-
|
7505
|
-
|
7506
|
-
|
7507
|
-
|
7508
|
-
|
7509
|
-
|
7510
|
-
|
7511
|
-
|
7512
|
-
|
7513
|
-
|
7514
|
-
|
7515
|
-
|
7516
|
-
|
7517
|
-
|
7518
|
-
|
7519
|
-
|
7520
|
-
|
7521
|
-
|
7522
|
-
|
7523
|
-
|
7524
|
-
|
7525
|
-
|
7526
|
-
|
7527
|
-
|
7528
|
-
|
7529
|
-
|
7530
|
-
|
7531
|
-
|
7532
|
-
|
7533
|
-
|
7378
|
+
}, [setTargetSelection, targetSelection, setShouldHandleOnMouseDownDuringSelect, interactionStartPoint, tagsValue]);
|
7379
|
+
const announcerText = React.useMemo(() => {
|
7380
|
+
if (activeSuggestionIndex === undefined) {
|
7381
|
+
return undefined;
|
7382
|
+
}
|
7383
|
+
const currentMention = mentionSuggestions[activeSuggestionIndex !== null && activeSuggestionIndex !== void 0 ? activeSuggestionIndex : 0];
|
7384
|
+
return (currentMention === null || currentMention === void 0 ? void 0 : currentMention.displayText.length) > 0
|
7385
|
+
? currentMention === null || currentMention === void 0 ? void 0 : currentMention.displayText
|
7386
|
+
: localeStrings.participantItem.displayNamePlaceholder;
|
7387
|
+
}, [activeSuggestionIndex, mentionSuggestions, localeStrings.participantItem.displayNamePlaceholder]);
|
7388
|
+
return (React__default['default'].createElement(React__default['default'].Fragment, null,
|
7389
|
+
mentionSuggestions.length > 0 && (React__default['default'].createElement(_MentionPopover, { suggestions: mentionSuggestions, activeSuggestionIndex: activeSuggestionIndex, target: inputBoxRef, targetPositionOffset: caretPosition, onRenderSuggestionItem: mentionLookupOptions === null || mentionLookupOptions === void 0 ? void 0 : mentionLookupOptions.onRenderSuggestionItem, onSuggestionSelected: onSuggestionSelected, onDismiss: () => {
|
7390
|
+
updateMentionSuggestions([]);
|
7391
|
+
} })),
|
7392
|
+
announcerText !== undefined && React__default['default'].createElement(Announcer$1, { announcementString: announcerText, ariaLive: 'polite' }),
|
7393
|
+
React__default['default'].createElement(react.TextField, Object.assign({}, textFieldProps, { "data-ui-id": dataUiId, value: inputTextValue, onChange: (e, newValue) => {
|
7394
|
+
// Remove when switching to react 17+, currently needed because of https://legacy.reactjs.org/docs/legacy-event-pooling.html
|
7395
|
+
// Prevents React from resetting event's properties
|
7396
|
+
e.persist();
|
7397
|
+
setInputTextValue(newValue !== null && newValue !== void 0 ? newValue : '');
|
7398
|
+
handleOnChange({
|
7399
|
+
event: e,
|
7400
|
+
tagsValue,
|
7401
|
+
htmlTextValue: textValue,
|
7402
|
+
inputTextValue,
|
7403
|
+
currentTriggerStartIndex,
|
7404
|
+
previousSelectionStart: nullToUndefined(selectionStartValue),
|
7405
|
+
previousSelectionEnd: nullToUndefined(selectionEndValue),
|
7406
|
+
currentSelectionStart: nullToUndefined(e.currentTarget.selectionStart),
|
7407
|
+
currentSelectionEnd: nullToUndefined(e.currentTarget.selectionEnd),
|
7408
|
+
updatedValue: newValue
|
7409
|
+
});
|
7410
|
+
}, onSelect: (e) => {
|
7411
|
+
handleOnSelect({
|
7412
|
+
event: e,
|
7413
|
+
inputTextValue,
|
7414
|
+
shouldHandleOnMouseDownDuringSelect,
|
7415
|
+
selectionEndValue,
|
7416
|
+
selectionStartValue,
|
7417
|
+
tags: tagsValue
|
7418
|
+
});
|
7419
|
+
}, onMouseDown: (e) => {
|
7420
|
+
setInteractionStartPoint({ x: e.clientX, y: e.clientY });
|
7421
|
+
// as events order is onMouseDown -> onMouseMove -> onMouseUp -> onSelect -> onClick
|
7422
|
+
// onClick and onMouseDown can't handle clicking on mention event because
|
7423
|
+
// onMouseDown doesn't have correct selectionRange yet and
|
7424
|
+
// onClick already has wrong range as it's called after onSelect that updates the selection range
|
7425
|
+
// so we need to handle onMouseDown to prevent onSelect default behavior
|
7426
|
+
setShouldHandleOnMouseDownDuringSelect(true);
|
7427
|
+
}, onMouseMove: handleOnMove, onMouseUp: () => {
|
7428
|
+
setInteractionStartPoint(undefined);
|
7429
|
+
}, onTouchStart: (e) => {
|
7430
|
+
setInteractionStartPoint({
|
7431
|
+
x: e.targetTouches.item(0).clientX,
|
7432
|
+
y: e.targetTouches.item(0).clientY
|
7433
|
+
});
|
7434
|
+
// see onMouseDown for more details
|
7435
|
+
setShouldHandleOnMouseDownDuringSelect(true);
|
7436
|
+
}, onTouchMove: handleOnMove, onTouchEnd: () => {
|
7437
|
+
setInteractionStartPoint(undefined);
|
7438
|
+
}, onBlur: () => {
|
7439
|
+
// setup all flags to default values when text field loses focus
|
7440
|
+
setShouldHandleOnMouseDownDuringSelect(false);
|
7441
|
+
setCaretIndex(undefined);
|
7442
|
+
setSelectionStartValue(undefined);
|
7443
|
+
setSelectionEndValue(undefined);
|
7444
|
+
}, onKeyDown: onTextFieldKeyDown, elementRef: inputBoxRef }))));
|
7534
7445
|
};
|
7535
|
-
|
7536
|
-
|
7537
|
-
|
7538
|
-
|
7539
|
-
|
7540
|
-
|
7541
|
-
|
7542
|
-
|
7543
|
-
|
7544
|
-
|
7545
|
-
|
7546
|
-
|
7547
|
-
|
7548
|
-
|
7549
|
-
|
7446
|
+
|
7447
|
+
// Copyright (c) Microsoft Corporation.
|
7448
|
+
/**
|
7449
|
+
* @private
|
7450
|
+
*/
|
7451
|
+
const InputBoxComponent = (props) => {
|
7452
|
+
const { styles, id, 'data-ui-id': dataUiId, textValue, onChange, textFieldRef, placeholderText, onKeyDown, onEnterKeyDown, supportNewline, inputClassName, errorMessage, disabled, children } = props;
|
7453
|
+
const mergedRootStyle = react.mergeStyles(inputBoxWrapperStyle, styles === null || styles === void 0 ? void 0 : styles.root);
|
7454
|
+
const mergedInputFieldStyle = react.mergeStyles(inputBoxStyle, inputClassName, props.inlineChildren ? {} : inputBoxNewLineSpaceAffordance);
|
7455
|
+
const mergedTextContainerStyle = react.mergeStyles(textContainerStyle, styles === null || styles === void 0 ? void 0 : styles.textFieldContainer);
|
7456
|
+
const mergedTextFieldStyle = react.concatStyleSets(textFieldStyle, {
|
7457
|
+
fieldGroup: styles === null || styles === void 0 ? void 0 : styles.textField,
|
7458
|
+
errorMessage: styles === null || styles === void 0 ? void 0 : styles.systemMessage,
|
7459
|
+
suffix: {
|
7460
|
+
backgroundColor: 'transparent',
|
7461
|
+
// Remove empty space in the suffix area when adding newline-style buttons
|
7462
|
+
display: props.inlineChildren ? 'flex' : 'contents',
|
7463
|
+
padding: '0 0.25rem'
|
7550
7464
|
}
|
7551
|
-
|
7552
|
-
|
7553
|
-
|
7465
|
+
});
|
7466
|
+
const mergedChildrenStyle = react.mergeStyles(props.inlineChildren ? {} : newLineButtonsContainerStyle);
|
7467
|
+
const onTextFieldKeyDown = React.useCallback((ev) => {
|
7468
|
+
if (isEnterKeyEventFromCompositionSession(ev)) {
|
7469
|
+
return;
|
7554
7470
|
}
|
7555
|
-
|
7556
|
-
|
7557
|
-
|
7558
|
-
tags.push(tag);
|
7559
|
-
}
|
7560
|
-
else {
|
7561
|
-
if (!parentTag.subTags) {
|
7562
|
-
parentTag.subTags = [tag];
|
7471
|
+
if (ev.key === 'Enter' && (ev.shiftKey === false || !supportNewline)) {
|
7472
|
+
ev.preventDefault();
|
7473
|
+
onEnterKeyDown && onEnterKeyDown();
|
7563
7474
|
}
|
7564
|
-
|
7565
|
-
|
7475
|
+
onKeyDown && onKeyDown(ev);
|
7476
|
+
}, [onEnterKeyDown, onKeyDown, supportNewline]);
|
7477
|
+
const onRenderChildren = () => {
|
7478
|
+
return (React__default['default'].createElement(react.Stack, { horizontal: true, className: mergedChildrenStyle }, children));
|
7479
|
+
};
|
7480
|
+
const renderTextField = () => {
|
7481
|
+
const textFieldProps = {
|
7482
|
+
autoFocus: props.autoFocus === 'sendBoxTextField',
|
7483
|
+
multiline: true,
|
7484
|
+
autoAdjustHeight: true,
|
7485
|
+
multiple: false,
|
7486
|
+
resizable: false,
|
7487
|
+
componentRef: textFieldRef,
|
7488
|
+
id,
|
7489
|
+
inputClassName: mergedInputFieldStyle,
|
7490
|
+
placeholder: placeholderText,
|
7491
|
+
autoComplete: 'off',
|
7492
|
+
styles: mergedTextFieldStyle,
|
7493
|
+
disabled,
|
7494
|
+
errorMessage,
|
7495
|
+
onRenderSuffix: onRenderChildren
|
7496
|
+
};
|
7497
|
+
/* @conditional-compile-remove(mention) */
|
7498
|
+
const textFieldWithMentionProps = {
|
7499
|
+
textFieldProps: textFieldProps,
|
7500
|
+
dataUiId: dataUiId,
|
7501
|
+
textValue: textValue,
|
7502
|
+
onChange: onChange,
|
7503
|
+
onKeyDown: onKeyDown,
|
7504
|
+
onEnterKeyDown: onEnterKeyDown,
|
7505
|
+
textFieldRef: textFieldRef,
|
7506
|
+
supportNewline: supportNewline,
|
7507
|
+
mentionLookupOptions: props.mentionLookupOptions
|
7508
|
+
};
|
7509
|
+
/* @conditional-compile-remove(mention) */
|
7510
|
+
if (props.mentionLookupOptions) {
|
7511
|
+
return React__default['default'].createElement(TextFieldWithMention, Object.assign({}, textFieldWithMentionProps));
|
7566
7512
|
}
|
7567
|
-
|
7513
|
+
return (React__default['default'].createElement(react.TextField, Object.assign({}, textFieldProps, { "data-ui-id": dataUiId, value: textValue, onChange: onChange, onKeyDown: onTextFieldKeyDown })));
|
7514
|
+
};
|
7515
|
+
return (React__default['default'].createElement(react.Stack, { className: mergedRootStyle },
|
7516
|
+
React__default['default'].createElement("div", { className: mergedTextContainerStyle }, renderTextField())));
|
7517
|
+
};
|
7518
|
+
/**
|
7519
|
+
* @private
|
7520
|
+
*/
|
7521
|
+
const InputBoxButton = (props) => {
|
7522
|
+
const { onRenderIcon, onClick, ariaLabel, className, id, tooltipContent } = props;
|
7523
|
+
const [isHover, setIsHover] = React.useState(false);
|
7524
|
+
const mergedButtonStyle = react.mergeStyles(inputButtonStyle, className);
|
7525
|
+
const theme = useTheme();
|
7526
|
+
const calloutStyle = { root: { padding: 0 }, calloutMain: { padding: '0.5rem' } };
|
7527
|
+
// Place callout with no gap between it and the button.
|
7528
|
+
const calloutProps = {
|
7529
|
+
gapSpace: 0,
|
7530
|
+
styles: calloutStyle,
|
7531
|
+
backgroundColor: isDarkThemed(theme) ? theme.palette.neutralLighter : ''
|
7532
|
+
};
|
7533
|
+
return (React__default['default'].createElement(react.TooltipHost, { hostClassName: inputButtonTooltipStyle, content: tooltipContent, calloutProps: Object.assign({}, calloutProps) },
|
7534
|
+
React__default['default'].createElement(react.IconButton, { className: mergedButtonStyle, ariaLabel: ariaLabel, onClick: onClick, id: id, onMouseEnter: () => {
|
7535
|
+
setIsHover(true);
|
7536
|
+
}, onMouseLeave: () => {
|
7537
|
+
setIsHover(false);
|
7538
|
+
},
|
7539
|
+
// VoiceOver fix: Avoid icon from stealing focus when IconButton is double-tapped to send message by wrapping with Stack with pointerEvents style to none
|
7540
|
+
onRenderIcon: () => React__default['default'].createElement(react.Stack, { className: iconWrapperStyle$1 }, onRenderIcon(isHover)) })));
|
7568
7541
|
};
|
7569
7542
|
|
7570
7543
|
// Copyright (c) Microsoft Corporation.
|
@@ -11101,9 +11074,9 @@ const DEFAULT_PERSONA_MIN_SIZE_PX = 32;
|
|
11101
11074
|
const DefaultPlaceholder = (props) => {
|
11102
11075
|
const { text, noVideoAvailableAriaLabel, coinSize, hidePersonaDetails } = props;
|
11103
11076
|
return (React__default['default'].createElement(react.Stack, { className: react.mergeStyles({ position: 'absolute', height: '100%', width: '100%' }) },
|
11104
|
-
React__default['default'].createElement(react.Stack, { styles: defaultPersonaStyles }, coinSize && (React__default['default'].createElement(react.Persona, { coinSize: coinSize, hidePersonaDetails: hidePersonaDetails, text: text !== null && text !== void 0 ? text : '', initialsTextColor: "white", "aria-label": noVideoAvailableAriaLabel !== null && noVideoAvailableAriaLabel !== void 0 ? noVideoAvailableAriaLabel : '', showOverflowTooltip: false })))));
|
11077
|
+
React__default['default'].createElement(react.Stack, { styles: defaultPersonaStyles$1 }, coinSize && (React__default['default'].createElement(react.Persona, { coinSize: coinSize, hidePersonaDetails: hidePersonaDetails, text: text !== null && text !== void 0 ? text : '', initialsTextColor: "white", "aria-label": noVideoAvailableAriaLabel !== null && noVideoAvailableAriaLabel !== void 0 ? noVideoAvailableAriaLabel : '', showOverflowTooltip: false })))));
|
11105
11078
|
};
|
11106
|
-
const defaultPersonaStyles = { root: { margin: 'auto', maxHeight: '100%' } };
|
11079
|
+
const defaultPersonaStyles$1 = { root: { margin: 'auto', maxHeight: '100%' } };
|
11107
11080
|
/* @conditional-compile-remove(pinned-participants) */
|
11108
11081
|
const videoTileMoreMenuIconProps = { iconName: undefined, style: { display: 'none' } };
|
11109
11082
|
/* @conditional-compile-remove(pinned-participants) */
|
@@ -11189,7 +11162,7 @@ const VideoTile = (props) => {
|
|
11189
11162
|
text: initialsName !== null && initialsName !== void 0 ? initialsName : displayName,
|
11190
11163
|
noVideoAvailableAriaLabel,
|
11191
11164
|
coinSize: personaSize,
|
11192
|
-
styles: defaultPersonaStyles,
|
11165
|
+
styles: defaultPersonaStyles$1,
|
11193
11166
|
hidePersonaDetails: true
|
11194
11167
|
};
|
11195
11168
|
const videoHintWithBorderRadius = react.mergeStyles(videoHint, { borderRadius: theme.effects.roundedCorner4 });
|
@@ -14850,11 +14823,11 @@ const _PictureInPictureInPicture = (props) => {
|
|
14850
14823
|
*/
|
14851
14824
|
const PictureInPictureInPictureContainer = (props) => {
|
14852
14825
|
const onKeyPress = (e) => props.onClick && submitWithKeyboard(e, props.onClick);
|
14853
|
-
return (React__default['default'].createElement("aside", { style: tileContainerStyles, onClick: props.onClick, onKeyPress: onKeyPress, "aria-label": props.ariaLabel, tabIndex: props.onClick ? 0 : -1, "data-ui-id": "picture-in-picture-in-picture-root" },
|
14826
|
+
return (React__default['default'].createElement("aside", { style: tileContainerStyles$1, onClick: props.onClick, onKeyPress: onKeyPress, "aria-label": props.ariaLabel, tabIndex: props.onClick ? 0 : -1, "data-ui-id": "picture-in-picture-in-picture-root" },
|
14854
14827
|
props.primaryView,
|
14855
14828
|
React__default['default'].createElement("div", { style: secondaryTileFloatingStyles }, props.secondaryView)));
|
14856
14829
|
};
|
14857
|
-
const tileContainerStyles = {
|
14830
|
+
const tileContainerStyles$1 = {
|
14858
14831
|
display: 'flex',
|
14859
14832
|
width: 'min-content',
|
14860
14833
|
position: 'relative',
|
@@ -18663,7 +18636,7 @@ const CallCompositeIcon = (props) => (React__default['default'].createElement(re
|
|
18663
18636
|
*/
|
18664
18637
|
const CallWithChatCompositeIcon = (props) => (React__default['default'].createElement(react.FontIcon, Object.assign({}, props)));
|
18665
18638
|
|
18666
|
-
var call$d={cameraLabel:"Camera",noCamerasLabel:"No cameras found",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",videoEffectsPaneTitle:"Effects",videoEffectsPaneBackgroundSelectionTitle:"Background",configurationPageVideoEffectsButtonLabel:"Effects",unableToStartVideoEffect:"Unable to apply video effect.",blurBackgroundEffectButtonLabel:"Blur",blurBackgroundTooltip:"Blur Background",removeBackgroundEffectButtonLabel:"None",removeBackgroundTooltip:"Remove Background",cameraOffBackgroundEffectWarningText:"Your camera is off. Turn on camera to see video effect.",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",noMicrophonesLabel:"No microphones found",noSpeakersLabel:"No speakers found",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number",outboundCallingNoticeString:"Calling...",participantJoinedNoticeString:"{displayName} joined",twoParticipantJoinedNoticeString:"{displayName1} and {displayName2} have joined",threeParticipantJoinedNoticeString:"{displayName1}, {displayName2} and {displayName3} have joined",participantLeftNoticeString:"{displayName} left",twoParticipantLeftNoticeString:"{displayName1} and {displayName2} have left",threeParticipantLeftNoticeString:"{displayName1}, {displayName2} and {displayName3} have left",unnamedParticipantString:"unnamed participant",manyUnnamedParticipantsJoined:"unnamed participant and {numOfParticipants} other participants joined",manyUnnamedParticipantsLeft:"unnamed participant and {numOfParticipants} other participants left",manyParticipantsJoined:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants joined",manyParticipantsLeft:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants left",liveCaptionsLabel:"Live captions",captionsSettingsLabel:"Caption settings",startCaptionsButtonOnLabel:"Turn on captions",startCaptionsButtonOffLabel:"Turn off captions",startCaptionsButtonTooltipOnContent:"Turn off captions",startCaptionsButtonTooltipOffContent:"Turn on captions",captionsSettingsModalTitle:"What language is being spoken?",captionsSettingsDropdownLabel:"Spoken language",captionsSettingsDropdownInfoText:"Language that everyone on this call is speaking.",captionsSettingsConfirmButtonLabel:"Confirm",captionsSettingsCancelButtonLabel:"Cancel",captionsSettingsModalAriaLabel:"Captions Setting Modal",captionsSettingsCloseModalButtonAriaLabel:"Close Captions Setting",captionsBannerMoreButtonCallingLabel:"More",captionsBannerMoreButtonTooltip:"More options",captionsAvailableLanguageStrings:{"ar-ae":"Arabic - U.A.E.","ar-sa":"Arabic - Saudi Arabia","da-dk":"Danish","de-de":"German - Germany","en-au":"English - Australia","en-ca":"English - Canada","en-gb":"English - United Kingdom","en-in":"English - India","en-nz":"English - New Zealand","en-us":"English - United States","es-es":"Spanish - Spain (Modern Sort)","es-mx":"Spanish - Mexico","fi-fi":"Finnish","fr-ca":"French - Canada","fr-fr":"French - France","hi-in":"Hindi","it-it":"Italian - Italy","ja-jp":"Japanese","ko-kr":"Korean","nb-no":"Norwegian (Bokmål)","nl-be":"Dutch - Belgium","nl-nl":"Dutch - Netherlands","pl-pl":"Polish","pt-br":"Portuguese - Brazil","ru-ru":"Russian","sv-se":"Swedish","zh-cn":"Chinese - People's Republic of China","zh-hk":"Chinese - Hong Kong SAR","cs-cz":"Czech","pt-pt":"Portuguese - Portugal","tr-tr":"Turkish","vi-vn":"Vietnamese","th-th":"Thai","he-il":"Hebrew","cy-gb":"Welsh","uk-ua":"Ukrainian","el-gr":"Greek","hu-hu":"Hungarian","ro-ro":"Romanian","sk-sk":"Slovak","zh-tw":"Chinese - Taiwan"},captionsBannerSpinnerText:"Starting captions..."};var chat$d={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$d={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",moreDrawerCaptionsMenuTitle:"Live captions",moreDrawerSpokenLanguageMenuTitle:"Spoken language",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number"};var en_US = {call:call$d,chat:chat$d,callWithChat:callWithChat$d};
|
18639
|
+
var call$d={cameraLabel:"Camera",noCamerasLabel:"No cameras found",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",videoEffectsPaneTitle:"Effects",videoEffectsPaneBackgroundSelectionTitle:"Background",configurationPageVideoEffectsButtonLabel:"Effects",unableToStartVideoEffect:"Unable to apply video effect.",blurBackgroundEffectButtonLabel:"Blur",blurBackgroundTooltip:"Blur Background",removeBackgroundEffectButtonLabel:"None",removeBackgroundTooltip:"Remove Background",cameraOffBackgroundEffectWarningText:"Your camera is off. Turn on camera to see video effect.",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",noMicrophonesLabel:"No microphones found",noSpeakersLabel:"No speakers found",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number",outboundCallingNoticeString:"Calling...",participantJoinedNoticeString:"{displayName} joined",twoParticipantJoinedNoticeString:"{displayName1} and {displayName2} have joined",threeParticipantJoinedNoticeString:"{displayName1}, {displayName2} and {displayName3} have joined",participantLeftNoticeString:"{displayName} left",twoParticipantLeftNoticeString:"{displayName1} and {displayName2} have left",threeParticipantLeftNoticeString:"{displayName1}, {displayName2} and {displayName3} have left",unnamedParticipantString:"unnamed participant",manyUnnamedParticipantsJoined:"unnamed participant and {numOfParticipants} other participants joined",manyUnnamedParticipantsLeft:"unnamed participant and {numOfParticipants} other participants left",manyParticipantsJoined:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants joined",manyParticipantsLeft:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants left",liveCaptionsLabel:"Live captions",captionsSettingsLabel:"Caption settings",startCaptionsButtonOnLabel:"Turn on captions",startCaptionsButtonOffLabel:"Turn off captions",startCaptionsButtonTooltipOnContent:"Turn off captions",startCaptionsButtonTooltipOffContent:"Turn on captions",captionsSettingsModalTitle:"What language is being spoken?",captionsSettingsDropdownLabel:"Spoken language",captionsSettingsDropdownInfoText:"Language that everyone on this call is speaking.",captionsSettingsConfirmButtonLabel:"Confirm",captionsSettingsCancelButtonLabel:"Cancel",captionsSettingsModalAriaLabel:"Captions Setting Modal",captionsSettingsCloseModalButtonAriaLabel:"Close Captions Setting",captionsBannerMoreButtonCallingLabel:"More",captionsBannerMoreButtonTooltip:"More options",captionsAvailableLanguageStrings:{"ar-ae":"Arabic - U.A.E.","ar-sa":"Arabic - Saudi Arabia","da-dk":"Danish","de-de":"German - Germany","en-au":"English - Australia","en-ca":"English - Canada","en-gb":"English - United Kingdom","en-in":"English - India","en-nz":"English - New Zealand","en-us":"English - United States","es-es":"Spanish - Spain (Modern Sort)","es-mx":"Spanish - Mexico","fi-fi":"Finnish","fr-ca":"French - Canada","fr-fr":"French - France","hi-in":"Hindi","it-it":"Italian - Italy","ja-jp":"Japanese","ko-kr":"Korean","nb-no":"Norwegian (Bokmål)","nl-be":"Dutch - Belgium","nl-nl":"Dutch - Netherlands","pl-pl":"Polish","pt-br":"Portuguese - Brazil","ru-ru":"Russian","sv-se":"Swedish","zh-cn":"Chinese - People's Republic of China","zh-hk":"Chinese - Hong Kong SAR","cs-cz":"Czech","pt-pt":"Portuguese - Portugal","tr-tr":"Turkish","vi-vn":"Vietnamese","th-th":"Thai","he-il":"Hebrew","cy-gb":"Welsh","uk-ua":"Ukrainian","el-gr":"Greek","hu-hu":"Hungarian","ro-ro":"Romanian","sk-sk":"Slovak","zh-tw":"Chinese - Taiwan"},captionsBannerSpinnerText:"Starting captions...",transferPageTransferorText:"Transferring...",transferPageTransferTargetText:"Connecting...",transferPageUnknownTransferorDisplayName:"Unknown",transferPageUnknownTransferTargetDisplayName:"Unknown"};var chat$d={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$d={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",moreDrawerCaptionsMenuTitle:"Live captions",moreDrawerSpokenLanguageMenuTitle:"Spoken language",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number"};var en_US = {call:call$d,chat:chat$d,callWithChat:callWithChat$d};
|
18667
18640
|
|
18668
18641
|
var call$c={cameraLabel:"Camera",noCamerasLabel:"No cameras found",cameraPermissionDenied:"Your browser is blocking access to your camera",cameraTurnedOff:"Your camera is turned off",chatButtonLabel:"Chat",close:"Close",complianceBannerNowOnlyRecording:"You are now only recording this meeting.",complianceBannerNowOnlyTranscription:"You are now only transcribing this meeting.",complianceBannerRecordingAndTranscriptionSaved:"Recording and transcription are being saved.",complianceBannerRecordingAndTranscriptionStarted:"Recording and transcription have started.",complianceBannerRecordingAndTranscriptionStopped:"Recording and transcription have stopped.",complianceBannerRecordingSaving:"Recording is being saved.",complianceBannerRecordingStarted:"Recording has started.",complianceBannerRecordingStopped:"Recording has stopped.",complianceBannerTranscriptionStarted:"Transcription has started.",complianceBannerTranscriptionConsent:"By joining, you are giving consent for this meeting to be transcribed.",complianceBannerTranscriptionSaving:"Transcription is being saved.",complianceBannerTranscriptionStopped:"Transcription has stopped.",configurationPageTitle:"Start a call",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",defaultPlaceHolder:"Select an option",dismissSidePaneButtonLabel:"Close",videoEffectsPaneTitle:"Effects",videoEffectsPaneBackgroundSelectionTitle:"Background",configurationPageVideoEffectsButtonLabel:"Effects",unableToStartVideoEffect:"Unable to apply video effect.",blurBackgroundEffectButtonLabel:"Blur",blurBackgroundTooltip:"Blur Background",removeBackgroundEffectButtonLabel:"None",removeBackgroundTooltip:"Remove Background",cameraOffBackgroundEffectWarningText:"Your camera is off. Turn on camera to see video effect.",failedToJoinCallDueToNoNetworkMoreDetails:"Call was disconnected due to a network issue. Check your connection and join again.",failedToJoinCallDueToNoNetworkTitle:"Call disconnected",failedToJoinTeamsMeetingReasonAccessDeniedMoreDetails:"You were not granted entry in the call. If this was a mistake, re-join the call.",failedToJoinTeamsMeetingReasonAccessDeniedTitle:"Dismissed from lobby",learnMore:"Learn more",leftCallMoreDetails:"If this was a mistake, re-join the call.",leftCallTitle:"You left the call",lobbyScreenConnectingToCallTitle:"Joining call",lobbyScreenWaitingToBeAdmittedTitle:"Waiting to be admitted",microphonePermissionDenied:"Your browser is blocking access to your microphone",microphoneToggleInLobbyNotAllowed:"Cannot mute or unmute while in lobby.",mutedMessage:"You're muted",networkReconnectMoreDetails:"Looks like something went wrong. We're trying to get back into the call.",networkReconnectTitle:"Hold on",deniedPermissionToRoomDetails:"You do not have permission to join this room.",deniedPermissionToRoomTitle:"Permission denied to room",peopleButtonLabel:"People",peoplePaneTitle:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",privacyPolicy:"Privacy policy",rejoinCallButtonLabel:"Re-join call",removedFromCallMoreDetails:"Another participant removed you from the call.",removedFromCallTitle:"You were removed",removeMenuLabel:"Remove",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",roomNotFoundDetails:"Room ID provided is not valid.",roomNotFoundTitle:"Room not found",soundLabel:"Sound",noMicrophonesLabel:"No microphones found",noSpeakersLabel:"No speakers found",startCallButtonLabel:"Start call",openDialpadButtonLabel:"Dial phone number",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",moreButtonCallingLabel:"More",resumeCallButtonLabel:"Resume",resumingCallButtonLabel:"Resuming...",resumeCallButtonAriaLabel:"Resume call",resumingCallButtonAriaLabel:"Resume call",holdScreenLabel:"You're on hold",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number",outboundCallingNoticeString:"Calling...",participantJoinedNoticeString:"{displayName} joined",twoParticipantJoinedNoticeString:"{displayName1} and {displayName2} have joined",threeParticipantJoinedNoticeString:"{displayName1}, {displayName2} and {displayName3} have joined",participantLeftNoticeString:"{displayName} left",twoParticipantLeftNoticeString:"{displayName1} and {displayName2} have left",threeParticipantLeftNoticeString:"{displayName1}, {displayName2} and {displayName3} have left",unnamedParticipantString:"unnamed participant",manyUnnamedParticipantsJoined:"unnamed participant and {numOfParticipants} other participants joined",manyUnnamedParticipantsLeft:"unnamed participant and {numOfParticipants} other participants left",manyParticipantsJoined:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants joined",manyParticipantsLeft:"{displayName1}, {displayName2}, {displayName3} and {numOfParticipants} other participants left",liveCaptionsLabel:"Live captions",captionsSettingsLabel:"Caption settings",startCaptionsButtonOnLabel:"Turn on captions",startCaptionsButtonOffLabel:"Turn off captions",startCaptionsButtonTooltipOnContent:"Turn off captions",startCaptionsButtonTooltipOffContent:"Turn on captions",captionsSettingsModalTitle:"What language is being spoken?",captionsSettingsDropdownLabel:"Spoken language",captionsSettingsDropdownInfoText:"Language that everyone on this call is speaking.",captionsSettingsConfirmButtonLabel:"Confirm",captionsSettingsCancelButtonLabel:"Cancel",captionsSettingsModalAriaLabel:"Captions Setting Modal",captionsSettingsCloseModalButtonAriaLabel:"Close Captions Setting",captionsBannerMoreButtonCallingLabel:"More",captionsBannerMoreButtonTooltip:"More options",captionsAvailableLanguageStrings:{"ar-ae":"Arabic - U.A.E.","ar-sa":"Arabic - Saudi Arabia","da-dk":"Danish","de-de":"German - Germany","en-au":"English - Australia","en-ca":"English - Canada","en-gb":"English - United Kingdom","en-in":"English - India","en-nz":"English - New Zealand","en-us":"English - United States","es-es":"Spanish - Spain (Modern Sort)","es-mx":"Spanish - Mexico","fi-fi":"Finnish","fr-ca":"French - Canada","fr-fr":"French - France","hi-in":"Hindi","it-it":"Italian - Italy","ja-jp":"Japanese","ko-kr":"Korean","nb-no":"Norwegian (Bokmål)","nl-be":"Dutch - Belgium","nl-nl":"Dutch - Netherlands","pl-pl":"Polish","pt-br":"Portuguese - Brazil","ru-ru":"Russian","sv-se":"Swedish","zh-cn":"Chinese - People's Republic of China","zh-hk":"Chinese - Hong Kong SAR","cs-cz":"Czech","pt-pt":"Portuguese - Portugal","tr-tr":"Turkish","vi-vn":"Vietnamese","th-th":"Thai","he-il":"Hebrew","cy-gb":"Welsh","uk-ua":"Ukrainian","el-gr":"Greek","hu-hu":"Hungarian","ro-ro":"Romanian","sk-sk":"Slovak","zh-tw":"Chinese - Taiwan"},captionsBannerSpinnerText:"Starting captions..."};var chat$c={chatListHeader:"In this chat",uploadFile:"Upload File"};var callWithChat$c={chatButtonLabel:"Chat",chatButtonNewMessageNotificationLabel:"New Message",chatButtonTooltipClosedWithMessageCount:"Show chat ({unreadMessagesCount} unread)",chatButtonTooltipClose:"Hide chat",chatButtonTooltipOpen:"Show chat",chatPaneTitle:"Chat",copyInviteLinkButtonLabel:"Copy invite link",copyInviteLinkActionedAriaLabel:"Invite link copied",dismissSidePaneButtonLabel:"Close",moreDrawerAudioDeviceMenuTitle:"Audio Device",moreDrawerButtonLabel:"More options",moreDrawerButtonTooltip:"More options",moreDrawerMicrophoneMenuTitle:"Microphone",moreDrawerSpeakerMenuTitle:"Speaker",moreDrawerCaptionsMenuTitle:"Live captions",moreDrawerSpokenLanguageMenuTitle:"Spoken language",peopleButtonLabel:"People",peopleButtonTooltipOpen:"Show participants",peopleButtonTooltipClose:"Hide participants",peoplePaneSubTitle:"In this call",peoplePaneTitle:"People",pictureInPictureTileAriaLabel:"Video Feeds. Click to return to call screen.",removeMenuLabel:"Remove",openDialpadButtonLabel:"Dial phone number",returnToCallButtonAriaDescription:"Return to Call",returnToCallButtonAriaLabel:"Back",peoplePaneAddPeopleButtonLabel:"Add People",dialpadStartCallButtonLabel:"Call",dialpadModalTitle:"Dial Phone Number",dialpadModalAriaLabel:"Dialpad",dialpadCloseModalButtonAriaLabel:"Close dialpad",openDtmfDialpadLabel:"Show dialpad",dtmfDialpadPlaceholderText:"Enter number"};var en_GB = {call:call$c,chat:chat$c,callWithChat:callWithChat$c};
|
18669
18642
|
|
@@ -19190,11 +19163,15 @@ const getCallEndReason = (call) => {
|
|
19190
19163
|
*
|
19191
19164
|
* @private
|
19192
19165
|
*/
|
19193
|
-
const getCallCompositePage = (call, previousCall, unsupportedBrowserInfo) => {
|
19166
|
+
const getCallCompositePage = (call, previousCall, unsupportedBrowserInfo, transferCall) => {
|
19194
19167
|
/* @conditional-compile-remove(unsupported-browser) */
|
19195
19168
|
if (isUnsupportedEnvironment(unsupportedBrowserInfo.environmentInfo, unsupportedBrowserInfo.unsupportedBrowserVersionOptedIn)) {
|
19196
19169
|
return 'unsupportedEnvironment';
|
19197
19170
|
}
|
19171
|
+
/* @conditional-compile-remove(call-transfer) */
|
19172
|
+
if (transferCall !== undefined) {
|
19173
|
+
return 'transferring';
|
19174
|
+
}
|
19198
19175
|
if (call) {
|
19199
19176
|
// Must check for ongoing call *before* looking at any previous calls.
|
19200
19177
|
// If the composite completes one call and joins another, the previous calls
|
@@ -20469,7 +20446,7 @@ const participantListMobileStyle = {
|
|
20469
20446
|
/**
|
20470
20447
|
* @private
|
20471
20448
|
*/
|
20472
|
-
const displayNameStyles = {
|
20449
|
+
const displayNameStyles$1 = {
|
20473
20450
|
root: {
|
20474
20451
|
padding: '0.5rem',
|
20475
20452
|
textOverflow: 'ellipsis',
|
@@ -20505,7 +20482,7 @@ const ParticipantListWithHeading = (props) => {
|
|
20505
20482
|
React__default['default'].createElement(react.FocusZone, { className: participantListContainerStyle, shouldFocusOnMount: true },
|
20506
20483
|
React__default['default'].createElement(ParticipantList, Object.assign({}, participantListProps, { styles: props.isMobile ? participantListMobileStyle : participantListStyle, onRenderAvatar: (userId, options) => (React__default['default'].createElement(React__default['default'].Fragment, null,
|
20507
20484
|
React__default['default'].createElement(AvatarPersona, Object.assign({ "data-ui-id": "chat-composite-participant-custom-avatar", userId: userId }, options, { hidePersonaDetails: !!(options === null || options === void 0 ? void 0 : options.text) }, { dataProvider: onFetchAvatarPersonaData })),
|
20508
|
-
(options === null || options === void 0 ? void 0 : options.text) && (React__default['default'].createElement(react.Text, { nowrap: true, styles: displayNameStyles }, options === null || options === void 0 ? void 0 : options.text)))), onFetchParticipantMenuItems: onFetchParticipantMenuItems, showParticipantOverflowTooltip: !props.isMobile })))));
|
20485
|
+
(options === null || options === void 0 ? void 0 : options.text) && (React__default['default'].createElement(react.Text, { nowrap: true, styles: displayNameStyles$1 }, options === null || options === void 0 ? void 0 : options.text)))), onFetchParticipantMenuItems: onFetchParticipantMenuItems, showParticipantOverflowTooltip: !props.isMobile })))));
|
20509
20486
|
};
|
20510
20487
|
|
20511
20488
|
// Copyright (c) Microsoft Corporation.
|
@@ -21340,6 +21317,11 @@ const getRole = (state) => { var _a; return (_a = state.call) === null || _a ===
|
|
21340
21317
|
* @private
|
21341
21318
|
*/
|
21342
21319
|
const getPage = (state) => state.page;
|
21320
|
+
/* @conditional-compile-remove(call-transfer) */
|
21321
|
+
/**
|
21322
|
+
* @private
|
21323
|
+
*/
|
21324
|
+
const getTransferCall = (state) => state.acceptedTransferCallState;
|
21343
21325
|
/**
|
21344
21326
|
* @private
|
21345
21327
|
*/
|
@@ -24374,14 +24356,14 @@ const MediaGallery = (props) => {
|
|
24374
24356
|
? 'VerticalRight'
|
24375
24357
|
: 'HorizontalBottom', [containerWidth, containerHeight]);
|
24376
24358
|
const VideoGalleryMemoized = React.useMemo(() => {
|
24377
|
-
var _a;
|
24378
|
-
return (React__default['default'].createElement(VideoGallery, Object.assign({}, videoGalleryProps, { localVideoViewOptions: localVideoViewOptions$2, remoteVideoViewOptions: remoteVideoViewOptions, styles: VideoGalleryStyles, layout: layoutBasedOnTilePosition, showCameraSwitcherInLocalPreview: props.isMobile, localVideoCameraCycleButtonProps: cameraSwitcherProps, onRenderAvatar: onRenderAvatar,
|
24359
|
+
var _a, _b;
|
24360
|
+
return (React__default['default'].createElement(VideoGallery, Object.assign({}, videoGalleryProps, { localVideoViewOptions: localVideoViewOptions$2, remoteVideoViewOptions: remoteVideoViewOptions, styles: VideoGalleryStyles, layout: layoutBasedOnTilePosition, showCameraSwitcherInLocalPreview: props.isMobile, localVideoCameraCycleButtonProps: cameraSwitcherProps, onRenderAvatar: (_a = props.onRenderAvatar) !== null && _a !== void 0 ? _a : onRenderAvatar,
|
24379
24361
|
/* @conditional-compile-remove(pinned-participants) */
|
24380
24362
|
remoteVideoTileMenuOptions: remoteVideoTileMenuOptions,
|
24381
24363
|
/* @conditional-compile-remove(vertical-gallery) */
|
24382
24364
|
overflowGalleryPosition: overflowGalleryPosition,
|
24383
24365
|
/* @conditional-compile-remove(click-to-call) */
|
24384
|
-
localVideoTileSize: ((
|
24366
|
+
localVideoTileSize: ((_b = props.localVideoTileOptions) === null || _b === void 0 ? void 0 : _b.position) === 'hidden'
|
24385
24367
|
? 'hidden'
|
24386
24368
|
: props.isMobile
|
24387
24369
|
? 'followDeviceOrientation'
|
@@ -24389,6 +24371,7 @@ const MediaGallery = (props) => {
|
|
24389
24371
|
}, [
|
24390
24372
|
videoGalleryProps,
|
24391
24373
|
props.isMobile,
|
24374
|
+
props.onRenderAvatar,
|
24392
24375
|
onRenderAvatar,
|
24393
24376
|
cameraSwitcherProps,
|
24394
24377
|
/* @conditional-compile-remove(pinned-participants) */ remoteVideoTileMenuOptions,
|
@@ -25796,6 +25779,139 @@ const outboundCallStringsTrampoline = (strings) => {
|
|
25796
25779
|
return strings.outboundCallingNoticeString;
|
25797
25780
|
};
|
25798
25781
|
|
25782
|
+
// Copyright (c) Microsoft Corporation.
|
25783
|
+
// Licensed under the MIT license.
|
25784
|
+
/**
|
25785
|
+
* @private
|
25786
|
+
*/
|
25787
|
+
const tileContainerStyles = {
|
25788
|
+
position: 'absolute',
|
25789
|
+
top: '0',
|
25790
|
+
left: '0',
|
25791
|
+
width: '100%',
|
25792
|
+
height: '100%',
|
25793
|
+
minWidth: '100%',
|
25794
|
+
minHeight: '100%',
|
25795
|
+
objectPosition: 'center',
|
25796
|
+
objectFit: 'cover',
|
25797
|
+
zIndex: 0
|
25798
|
+
};
|
25799
|
+
/**
|
25800
|
+
* @private
|
25801
|
+
*/
|
25802
|
+
const tileContentStyles = {
|
25803
|
+
width: '100%',
|
25804
|
+
position: 'absolute',
|
25805
|
+
top: '50%',
|
25806
|
+
transform: 'translate(0, -50%)',
|
25807
|
+
display: 'flex',
|
25808
|
+
justifyContent: 'center'
|
25809
|
+
};
|
25810
|
+
/**
|
25811
|
+
* @private
|
25812
|
+
*/
|
25813
|
+
const defaultPersonaStyles = {
|
25814
|
+
root: { margin: 'auto' }
|
25815
|
+
};
|
25816
|
+
/**
|
25817
|
+
* @private
|
25818
|
+
*/
|
25819
|
+
const displayNameStyles = { textAlign: 'center', fontSize: '1.5rem', fontWeight: 400 };
|
25820
|
+
/**
|
25821
|
+
* @private
|
25822
|
+
*/
|
25823
|
+
const spinnerStyles = { circle: { borderWidth: '0.125rem' } };
|
25824
|
+
/**
|
25825
|
+
* @private
|
25826
|
+
*/
|
25827
|
+
const statusTextStyles = { textAlign: 'center', fontSize: '1rem' };
|
25828
|
+
|
25829
|
+
// Copyright (c) Microsoft Corporation.
|
25830
|
+
/**
|
25831
|
+
* @private
|
25832
|
+
*/
|
25833
|
+
const TransferPage = (props) => {
|
25834
|
+
var _a, _b, _c, _d, _e;
|
25835
|
+
const errorBarProps = usePropsFor$1(ErrorBar);
|
25836
|
+
const strings = useLocale().strings.call;
|
25837
|
+
const remoteParticipants = useSelector$1(getRemoteParticipants);
|
25838
|
+
/* @conditional-compile-remove(call-transfer) */
|
25839
|
+
const transferCall = useSelector$1(getTransferCall);
|
25840
|
+
// Reduce the controls shown when mobile view is enabled.
|
25841
|
+
const callControlOptions = props.mobileView
|
25842
|
+
? reduceCallControlsForMobile((_a = props.options) === null || _a === void 0 ? void 0 : _a.callControls)
|
25843
|
+
: (_b = props.options) === null || _b === void 0 ? void 0 : _b.callControls;
|
25844
|
+
/* @conditional-compile-remove(call-transfer) */
|
25845
|
+
// page subject is which should be participant shown in the transfer page depending on the transfer call state
|
25846
|
+
const pageSubject = React.useMemo(() => {
|
25847
|
+
if (transferCall && ['Ringing', 'Connected'].includes(transferCall.state)) {
|
25848
|
+
return 'transferTarget';
|
25849
|
+
}
|
25850
|
+
return 'transferor';
|
25851
|
+
}, [transferCall]);
|
25852
|
+
const transferor = React.useMemo(() => { var _a; return (remoteParticipants ? (_a = Object.values(remoteParticipants)) === null || _a === void 0 ? void 0 : _a[0] : undefined); }, [remoteParticipants]);
|
25853
|
+
/* @conditional-compile-remove(call-transfer) */
|
25854
|
+
const transferTarget = React.useMemo(() => { var _a; return ((transferCall === null || transferCall === void 0 ? void 0 : transferCall.remoteParticipants) ? (_a = Object.values(transferCall.remoteParticipants)) === null || _a === void 0 ? void 0 : _a[0] : undefined); }, [transferCall]);
|
25855
|
+
let transferTileParticipant = transferor;
|
25856
|
+
/* @conditional-compile-remove(call-transfer) */
|
25857
|
+
if (pageSubject === 'transferTarget') {
|
25858
|
+
transferTileParticipant = transferTarget;
|
25859
|
+
}
|
25860
|
+
let transferParticipantDisplayName = (_c = transferor === null || transferor === void 0 ? void 0 : transferor.displayName) !== null && _c !== void 0 ? _c :
|
25861
|
+
/* @conditional-compile-remove(call-transfer) */ strings.transferPageUnknownTransferorDisplayName;
|
25862
|
+
/* @conditional-compile-remove(call-transfer) */
|
25863
|
+
if (pageSubject === 'transferTarget') {
|
25864
|
+
transferParticipantDisplayName =
|
25865
|
+
(_d = transferTarget === null || transferTarget === void 0 ? void 0 : transferTarget.displayName) !== null && _d !== void 0 ? _d : strings.transferPageUnknownTransferTargetDisplayName;
|
25866
|
+
}
|
25867
|
+
return (React__default['default'].createElement(CallArrangement, { complianceBannerProps: { strings },
|
25868
|
+
// Ignore errors from before current call. This avoids old errors from showing up when a user re-joins a call.
|
25869
|
+
errorBarProps: ((_e = props.options) === null || _e === void 0 ? void 0 : _e.errorBar) !== false && Object.assign(Object.assign({}, errorBarProps), { ignorePremountErrors: true }), callControlProps: {
|
25870
|
+
options: callControlOptions,
|
25871
|
+
increaseFlyoutItemSize: props.mobileView
|
25872
|
+
}, mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, onRenderGalleryContent: () => (React__default['default'].createElement(TransferTile, { userId: transferTileParticipant ? toFlatCommunicationIdentifier(transferTileParticipant === null || transferTileParticipant === void 0 ? void 0 : transferTileParticipant.identifier) : undefined, displayName: transferParticipantDisplayName, initialsName: transferParticipantDisplayName,
|
25873
|
+
/* @conditional-compile-remove(call-transfer) */
|
25874
|
+
statusText: pageSubject === 'transferTarget'
|
25875
|
+
? strings.transferPageTransferTargetText
|
25876
|
+
: strings.transferPageTransferorText, onRenderAvatar: props.onRenderAvatar, onFetchAvatarPersonaData: props.onFetchAvatarPersonaData })), dataUiId: 'transfer-page', updateSidePaneRenderer: props.updateSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader }));
|
25877
|
+
};
|
25878
|
+
const TransferTile = (props) => {
|
25879
|
+
const { displayName, initialsName, userId, onRenderAvatar, onFetchAvatarPersonaData, statusText } = props;
|
25880
|
+
const [personaSize, setPersonaSize] = React.useState();
|
25881
|
+
const tileRef = React.useRef(null);
|
25882
|
+
const observer = React.useRef(new ResizeObserver((entries) => {
|
25883
|
+
const { width, height } = entries[0].contentRect;
|
25884
|
+
const personaSize = Math.min(width, height) / 2;
|
25885
|
+
setPersonaSize(Math.max(Math.min(personaSize, 150), 32));
|
25886
|
+
}));
|
25887
|
+
React.useLayoutEffect(() => {
|
25888
|
+
if (tileRef.current) {
|
25889
|
+
observer.current.observe(tileRef.current);
|
25890
|
+
}
|
25891
|
+
const currentObserver = observer.current;
|
25892
|
+
return () => currentObserver.disconnect();
|
25893
|
+
}, [observer, tileRef]);
|
25894
|
+
const placeholderOptions = React.useMemo(() => ({
|
25895
|
+
userId,
|
25896
|
+
text: initialsName !== null && initialsName !== void 0 ? initialsName : displayName,
|
25897
|
+
coinSize: personaSize,
|
25898
|
+
styles: defaultPersonaStyles,
|
25899
|
+
hidePersonaDetails: true
|
25900
|
+
}), [userId, initialsName, displayName, personaSize]);
|
25901
|
+
const defaultOnRenderAvatar = React.useCallback(() => {
|
25902
|
+
return personaSize ? React__default['default'].createElement(AvatarPersona, Object.assign({}, placeholderOptions, { dataProvider: onFetchAvatarPersonaData })) : React__default['default'].createElement(React__default['default'].Fragment, null);
|
25903
|
+
}, [placeholderOptions, onFetchAvatarPersonaData, personaSize]);
|
25904
|
+
const defaultAvatar = React.useMemo(() => defaultOnRenderAvatar(), [defaultOnRenderAvatar]);
|
25905
|
+
return (React__default['default'].createElement("div", { ref: tileRef, className: react.mergeStyles(tileContainerStyles), "data-is-focusable": true },
|
25906
|
+
React__default['default'].createElement(react.Stack, { className: react.mergeStyles(tileContentStyles), tokens: { childrenGap: '1rem' } },
|
25907
|
+
React__default['default'].createElement(react.Stack, { horizontalAlign: "center", tokens: { childrenGap: '0.5rem' } },
|
25908
|
+
onRenderAvatar ? onRenderAvatar(userId !== null && userId !== void 0 ? userId : '', placeholderOptions, defaultOnRenderAvatar) : defaultAvatar,
|
25909
|
+
React__default['default'].createElement(react.Text, { className: react.mergeStyles(displayNameStyles) }, displayName)),
|
25910
|
+
React__default['default'].createElement(react.Stack, { horizontal: true, horizontalAlign: "center", verticalAlign: "center", tokens: { childrenGap: '0.5rem' } },
|
25911
|
+
React__default['default'].createElement(react.Spinner, { size: react.SpinnerSize.large, className: react.mergeStyles(spinnerStyles) }),
|
25912
|
+
React__default['default'].createElement(react.Text, { className: react.mergeStyles(statusTextStyles) }, statusText)))));
|
25913
|
+
};
|
25914
|
+
|
25799
25915
|
// Copyright (c) Microsoft Corporation.
|
25800
25916
|
/**
|
25801
25917
|
* styles for hold pane resume button
|
@@ -26101,6 +26217,10 @@ const MainScreen = (props) => {
|
|
26101
26217
|
case 'lobby':
|
26102
26218
|
pageElement = (React__default['default'].createElement(LobbyPage, { mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, options: props.options, updateSidePaneRenderer: setSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader }));
|
26103
26219
|
break;
|
26220
|
+
/* @conditional-compile-remove(call-transfer) */
|
26221
|
+
case 'transferring':
|
26222
|
+
pageElement = (React__default['default'].createElement(TransferPage, { mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, options: props.options, updateSidePaneRenderer: setSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader, onRenderAvatar: onRenderAvatar, onFetchAvatarPersonaData: onFetchAvatarPersonaData }));
|
26223
|
+
break;
|
26104
26224
|
case 'call':
|
26105
26225
|
pageElement = (React__default['default'].createElement(CallPage, { onRenderAvatar: onRenderAvatar, callInvitationURL: callInvitationUrl, onFetchAvatarPersonaData: onFetchAvatarPersonaData, onFetchParticipantMenuItems: onFetchParticipantMenuItems, mobileView: props.mobileView, modalLayerHostId: props.modalLayerHostId, options: props.options, updateSidePaneRenderer: setSidePaneRenderer, mobileChatTabHeader: props.mobileChatTabHeader }));
|
26106
26226
|
break;
|
@@ -26403,8 +26523,15 @@ class CallContext {
|
|
26403
26523
|
environmentInfo: this.state.environmentInfo,
|
26404
26524
|
unsupportedBrowserVersionOptedIn: this.state.unsupportedBrowserVersionsAllowed
|
26405
26525
|
};
|
26526
|
+
/* @conditional-compile-remove(call-transfer) */
|
26527
|
+
const latestAcceptedTransfer = (call === null || call === void 0 ? void 0 : call.transferFeature.acceptedTransfers)
|
26528
|
+
? findLatestAcceptedTransfer(call.transferFeature.acceptedTransfers)
|
26529
|
+
: undefined;
|
26530
|
+
/* @conditional-compile-remove(call-transfer) */
|
26531
|
+
const transferCall = latestAcceptedTransfer ? clientState.calls[latestAcceptedTransfer.callId] : undefined;
|
26406
26532
|
const newPage = getCallCompositePage(call, latestEndedCall,
|
26407
|
-
/* @conditional-compile-remove(unsupported-browser) */ environmentInfo
|
26533
|
+
/* @conditional-compile-remove(unsupported-browser) */ environmentInfo,
|
26534
|
+
/* @conditional-compile-remove(call-transfer) */ transferCall);
|
26408
26535
|
if (!IsCallEndedPage(oldPage) && IsCallEndedPage(newPage)) {
|
26409
26536
|
this.emitter.emit('callEnded', { callId: this.callId });
|
26410
26537
|
// Reset the callId to undefined as the call has ended.
|
@@ -26412,12 +26539,6 @@ class CallContext {
|
|
26412
26539
|
// Make sure that the call is set to undefined in the state.
|
26413
26540
|
call = undefined;
|
26414
26541
|
}
|
26415
|
-
/* @conditional-compile-remove(call-transfer) */
|
26416
|
-
const latestAcceptedTransfer = (call === null || call === void 0 ? void 0 : call.transferFeature.acceptedTransfers)
|
26417
|
-
? findLatestAcceptedTransfer(call.transferFeature.acceptedTransfers)
|
26418
|
-
: undefined;
|
26419
|
-
/* @conditional-compile-remove(call-transfer) */
|
26420
|
-
const transferCall = latestAcceptedTransfer ? clientState.calls[latestAcceptedTransfer.callId] : undefined;
|
26421
26542
|
if (this.state.page) {
|
26422
26543
|
this.setState(Object.assign(Object.assign({}, this.state), { userId: clientState.userId, displayName: (_a = clientState.callAgent) === null || _a === void 0 ? void 0 : _a.displayName, call, page: newPage, endedCall: latestEndedCall, devices: clientState.deviceManager, latestErrors: clientState.latestErrors, cameraStatus: (call === null || call === void 0 ? void 0 : call.localVideoStreams.find((s) => s.mediaStreamType === 'Video')) ||
|
26423
26544
|
clientState.deviceManager.unparentedViews.find((s) => s.mediaStreamType === 'Video')
|