@capillarytech/blaze-ui 6.1.6-beta.1 → 6.1.6-beta.3
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/CapEmojiPicker/Picker/index.d.ts +6 -0
- package/CapEmojiPicker/Picker/index.d.ts.map +1 -0
- package/CapEmojiPicker/Picker/index.js +114 -0
- package/CapEmojiPicker/Picker/messages.d.ts +21 -0
- package/CapEmojiPicker/Picker/messages.d.ts.map +1 -0
- package/CapEmojiPicker/Picker/messages.js +24 -0
- package/CapEmojiPicker/TriggerButton/_triggerButton.scss +45 -0
- package/CapEmojiPicker/TriggerButton/index.d.ts +9 -0
- package/CapEmojiPicker/TriggerButton/index.d.ts.map +1 -0
- package/CapEmojiPicker/TriggerButton/index.js +35 -0
- package/CapEmojiPicker/Wrapper/index.d.ts +4 -0
- package/CapEmojiPicker/Wrapper/index.d.ts.map +1 -0
- package/CapEmojiPicker/Wrapper/index.js +166 -0
- package/CapEmojiPicker/Wrapper/messages.d.ts +13 -0
- package/CapEmojiPicker/Wrapper/messages.d.ts.map +1 -0
- package/CapEmojiPicker/Wrapper/messages.js +16 -0
- package/CapEmojiPicker/Wrapper/useEmojiTriggerPosition.d.ts +18 -0
- package/CapEmojiPicker/Wrapper/useEmojiTriggerPosition.d.ts.map +1 -0
- package/CapEmojiPicker/Wrapper/useEmojiTriggerPosition.js +108 -0
- package/CapEmojiPicker/_capEmojiPicker.css +231 -0
- package/CapEmojiPicker/_capEmojiPicker.scss +281 -0
- package/CapEmojiPicker/_config.scss +7 -0
- package/CapEmojiPicker/assets/sentiment-satsified.svg +3 -0
- package/CapEmojiPicker/assets/sentiment-satsified.svg.js +4 -0
- package/CapEmojiPicker/constants.d.ts +34 -0
- package/CapEmojiPicker/constants.d.ts.map +1 -0
- package/CapEmojiPicker/constants.js +18 -0
- package/CapEmojiPicker/index.d.ts +4 -0
- package/CapEmojiPicker/index.d.ts.map +1 -0
- package/CapEmojiPicker/index.js +11 -0
- package/CapEmojiPicker/utils.d.ts +20 -0
- package/CapEmojiPicker/utils.d.ts.map +1 -0
- package/CapEmojiPicker/utils.js +24 -0
- package/CapNavigationSPA/CapNavigationSPASidebar/index.d.ts.map +1 -1
- package/CapNavigationSPA/CapNavigationSPASidebar/index.js +476 -246
- package/CapNavigationSPA/CapNavigationSPASidebar/styles.css +34 -2
- package/CapNavigationSPA/CapNavigationSPASidebar/styles.module.scss.js +3 -0
- package/CapNavigationSPA/CapNavigationSPASidebar/styles.scss +43 -6
- package/CapNavigationSPA/CapNavigationSPATopBar/index.d.ts +3 -2
- package/CapNavigationSPA/CapNavigationSPATopBar/index.d.ts.map +1 -1
- package/CapNavigationSPA/CapNavigationSPATopBar/index.js +72 -96
- package/CapNavigationSPA/CapNavigationSPATopBar/styles.css +75 -69
- package/CapNavigationSPA/CapNavigationSPATopBar/styles.module.scss.js +6 -7
- package/CapNavigationSPA/CapNavigationSPATopBar/styles.scss +102 -92
- package/CapNavigationSPA/CapNavigationSPATopBar/types.d.ts +6 -10
- package/CapNavigationSPA/CapNavigationSPATopBar/types.d.ts.map +1 -1
- package/CapNavigationSPA/index.d.ts.map +1 -1
- package/CapNavigationSPA/index.js +5 -5
- package/CapNavigationSPA/styles.css +5 -16
- package/CapNavigationSPA/styles.module.scss.js +1 -2
- package/CapNavigationSPA/styles.scss +8 -19
- package/assets/icons/blocks.svg +9 -0
- package/assets/icons/closed-lock.svg +1 -0
- package/assets/icons/csv.svg +21 -0
- package/assets/icons/databricks.svg +7 -0
- package/assets/icons/four-join.svg +19 -0
- package/assets/icons/http.svg +18 -0
- package/assets/icons/kafka.svg +9 -0
- package/assets/icons/open-lock.svg +1 -0
- package/assets/icons/s3.svg +3 -0
- package/assets/icons/sftp.svg +32 -0
- package/assets/icons/split-json.svg +9 -0
- package/assets/icons/three-join.svg +17 -0
- package/assets/icons/two-join.svg +15 -0
- package/assets/icons/xml.svg +12 -0
- package/package.json +2 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../_capEmojiPicker.scss';
|
|
3
|
+
export declare const importEmojiPicker: () => Promise<any>;
|
|
4
|
+
declare const _default: React.ComponentType<Omit<import("react-intl").WrappedComponentProps, "intl">>;
|
|
5
|
+
export default _default;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/Picker/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAKjF,OAAO,yBAAyB,CAAC;AAMjC,eAAO,MAAM,iBAAiB,oBAAqC,CAAC;;AAuJpE,wBAAkC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useState, useRef, useCallback, useEffect, useMemo } from "react";
|
|
5
|
+
import { intlShape, injectIntl } from "react-intl";
|
|
6
|
+
import CapButton from "../../CapButton/index.js";
|
|
7
|
+
import CapLabelWithStatic from "../../CapLabel/index.js";
|
|
8
|
+
import '../_capEmojiPicker.css';/* empty css */
|
|
9
|
+
import { CLS_PREFIX, PICKER_HEIGHT, PICKER_WIDTH } from "../constants.js";
|
|
10
|
+
import messages from "./messages.js";
|
|
11
|
+
const importEmojiPicker = () => import("emoji-picker-react");
|
|
12
|
+
const Picker = ({
|
|
13
|
+
intl: { formatMessage },
|
|
14
|
+
onEmojiSelect,
|
|
15
|
+
className = "",
|
|
16
|
+
importFunction = importEmojiPicker
|
|
17
|
+
}) => {
|
|
18
|
+
const [EmojiPickerComponent, setEmojiPickerComponent] = useState(null);
|
|
19
|
+
const [EmojiPickerEnums, setEmojiPickerEnums] = useState(null);
|
|
20
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
21
|
+
const [hasError, setHasError] = useState(false);
|
|
22
|
+
const isMountedRef = useRef(true);
|
|
23
|
+
const loadEmojiPicker = useCallback(() => {
|
|
24
|
+
importFunction().then((module) => {
|
|
25
|
+
if (isMountedRef.current) {
|
|
26
|
+
const { Theme, EmojiStyle, SuggestionMode, SkinTonePickerLocation } = module;
|
|
27
|
+
setEmojiPickerComponent(() => module.default);
|
|
28
|
+
setEmojiPickerEnums({
|
|
29
|
+
Theme,
|
|
30
|
+
EmojiStyle,
|
|
31
|
+
SuggestionMode,
|
|
32
|
+
SkinTonePickerLocation
|
|
33
|
+
});
|
|
34
|
+
setIsLoading(false);
|
|
35
|
+
setHasError(false);
|
|
36
|
+
}
|
|
37
|
+
}).catch((error) => {
|
|
38
|
+
console.error("Failed to load emoji-picker-react:", error);
|
|
39
|
+
if (isMountedRef.current) {
|
|
40
|
+
setIsLoading(false);
|
|
41
|
+
setHasError(true);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}, [importFunction]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
isMountedRef.current = true;
|
|
47
|
+
loadEmojiPicker();
|
|
48
|
+
return () => {
|
|
49
|
+
isMountedRef.current = false;
|
|
50
|
+
};
|
|
51
|
+
}, [loadEmojiPicker]);
|
|
52
|
+
const handleRetry = useCallback(() => {
|
|
53
|
+
setHasError(false);
|
|
54
|
+
setIsLoading(true);
|
|
55
|
+
loadEmojiPicker();
|
|
56
|
+
}, [loadEmojiPicker]);
|
|
57
|
+
const handleEmojiClick = useCallback(
|
|
58
|
+
({
|
|
59
|
+
emoji,
|
|
60
|
+
names,
|
|
61
|
+
originalUnified
|
|
62
|
+
}) => {
|
|
63
|
+
const mappedData = {
|
|
64
|
+
emoji,
|
|
65
|
+
label: (names == null ? void 0 : names[0]) || originalUnified || ""
|
|
66
|
+
};
|
|
67
|
+
onEmojiSelect(mappedData);
|
|
68
|
+
},
|
|
69
|
+
[onEmojiSelect]
|
|
70
|
+
);
|
|
71
|
+
const previewConfig = useMemo(
|
|
72
|
+
() => ({
|
|
73
|
+
showPreview: true,
|
|
74
|
+
defaultCaption: formatMessage(messages.defaultCaption)
|
|
75
|
+
}),
|
|
76
|
+
[formatMessage]
|
|
77
|
+
);
|
|
78
|
+
if (hasError) {
|
|
79
|
+
return /* @__PURE__ */ jsx("div", { className: classNames(`${CLS_PREFIX}-panel`, className), children: /* @__PURE__ */ jsxs("div", { className: `${CLS_PREFIX}-error-container`, children: [
|
|
80
|
+
/* @__PURE__ */ jsx(CapLabelWithStatic, { className: `${CLS_PREFIX}-error-message`, children: formatMessage(messages.errorMessage) }),
|
|
81
|
+
/* @__PURE__ */ jsx(CapButton, { onClick: handleRetry, className: `${CLS_PREFIX}-retry-button`, children: formatMessage(messages.retryButton) })
|
|
82
|
+
] }) });
|
|
83
|
+
}
|
|
84
|
+
if (isLoading || !EmojiPickerComponent || !EmojiPickerEnums) {
|
|
85
|
+
return /* @__PURE__ */ jsx("div", { className: classNames(`${CLS_PREFIX}-panel`, className), children: /* @__PURE__ */ jsx("div", { className: `${CLS_PREFIX}-loading-container`, children: /* @__PURE__ */ jsx(CapLabelWithStatic, { children: formatMessage(messages.loadingMessage) }) }) });
|
|
86
|
+
}
|
|
87
|
+
return /* @__PURE__ */ jsx("div", { className: classNames(`${CLS_PREFIX}-panel`, className), children: /* @__PURE__ */ jsx(
|
|
88
|
+
EmojiPickerComponent,
|
|
89
|
+
{
|
|
90
|
+
onEmojiClick: handleEmojiClick,
|
|
91
|
+
width: PICKER_WIDTH,
|
|
92
|
+
height: PICKER_HEIGHT,
|
|
93
|
+
theme: EmojiPickerEnums.Theme.LIGHT,
|
|
94
|
+
emojiStyle: EmojiPickerEnums.EmojiStyle.NATIVE,
|
|
95
|
+
suggestedEmojisMode: EmojiPickerEnums.SuggestionMode.RECENT,
|
|
96
|
+
skinTonePickerLocation: EmojiPickerEnums.SkinTonePickerLocation.SEARCH,
|
|
97
|
+
skinTonesDisabled: false,
|
|
98
|
+
searchDisabled: false,
|
|
99
|
+
previewConfig,
|
|
100
|
+
lazyLoadEmojis: true
|
|
101
|
+
}
|
|
102
|
+
) });
|
|
103
|
+
};
|
|
104
|
+
Picker.propTypes = {
|
|
105
|
+
intl: intlShape.isRequired,
|
|
106
|
+
onEmojiSelect: PropTypes.func.isRequired,
|
|
107
|
+
className: PropTypes.string,
|
|
108
|
+
importFunction: PropTypes.func
|
|
109
|
+
};
|
|
110
|
+
const Picker$1 = injectIntl(Picker);
|
|
111
|
+
export {
|
|
112
|
+
Picker$1 as default,
|
|
113
|
+
importEmojiPicker
|
|
114
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const scope = "app.commonUtils.capUiLibrary.CapEmojiPicker.Picker";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
defaultCaption: {
|
|
4
|
+
id: string;
|
|
5
|
+
defaultMessage: string;
|
|
6
|
+
};
|
|
7
|
+
errorMessage: {
|
|
8
|
+
id: string;
|
|
9
|
+
defaultMessage: string;
|
|
10
|
+
};
|
|
11
|
+
retryButton: {
|
|
12
|
+
id: string;
|
|
13
|
+
defaultMessage: string;
|
|
14
|
+
};
|
|
15
|
+
loadingMessage: {
|
|
16
|
+
id: string;
|
|
17
|
+
defaultMessage: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export default _default;
|
|
21
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/Picker/messages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK,uDAAuD,CAAC;;;;;;;;;;;;;;;;;;;AAE1E,wBAiBG"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineMessages } from "react-intl";
|
|
2
|
+
const scope = "app.commonUtils.capUiLibrary.CapEmojiPicker.Picker";
|
|
3
|
+
const messages = defineMessages({
|
|
4
|
+
defaultCaption: {
|
|
5
|
+
id: `${scope}.defaultCaption`,
|
|
6
|
+
defaultMessage: "Choose an emoji"
|
|
7
|
+
},
|
|
8
|
+
errorMessage: {
|
|
9
|
+
id: `${scope}.errorMessage`,
|
|
10
|
+
defaultMessage: "Failed to load emoji picker"
|
|
11
|
+
},
|
|
12
|
+
retryButton: {
|
|
13
|
+
id: `${scope}.retryButton`,
|
|
14
|
+
defaultMessage: "Retry"
|
|
15
|
+
},
|
|
16
|
+
loadingMessage: {
|
|
17
|
+
id: `${scope}.loadingMessage`,
|
|
18
|
+
defaultMessage: "Loading emoji picker..."
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export {
|
|
22
|
+
messages as default,
|
|
23
|
+
scope
|
|
24
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@import '../../styles/_variables.scss';
|
|
2
|
+
@import '../_config.scss';
|
|
3
|
+
|
|
4
|
+
.#{$clsPrefix}-trigger-button {
|
|
5
|
+
position: absolute;
|
|
6
|
+
bottom: $CAP_SPACE_02;
|
|
7
|
+
right: $CAP_SPACE_02;
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
width: $CAP_SPACE_28;
|
|
12
|
+
height: $CAP_SPACE_28;
|
|
13
|
+
padding: 0;
|
|
14
|
+
border: none;
|
|
15
|
+
background: transparent;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
border-radius: 50%;
|
|
18
|
+
transition:
|
|
19
|
+
background-color 0.2s ease,
|
|
20
|
+
transform 0.2s ease;
|
|
21
|
+
z-index: 10;
|
|
22
|
+
|
|
23
|
+
&:hover {
|
|
24
|
+
background-color: rgba($FONT_COLOR_02, 0.1); // Light background on hover (rounded)
|
|
25
|
+
transform: scale(1.05);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:active {
|
|
29
|
+
background-color: rgba($FONT_COLOR_02, 0.15);
|
|
30
|
+
transform: scale(0.95);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:focus {
|
|
34
|
+
outline: $CAP_SPACE_02 solid $FONT_COLOR_05;
|
|
35
|
+
outline-offset: $CAP_SPACE_02;
|
|
36
|
+
background-color: rgba($FONT_COLOR_02, 0.1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.#{$clsPrefix}-trigger-button-icon {
|
|
40
|
+
width: 1rem;
|
|
41
|
+
height: 1rem;
|
|
42
|
+
display: block;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
declare const TriggerButton: React.ForwardRefExoticComponent<{
|
|
3
|
+
onClick?: () => void;
|
|
4
|
+
className?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
ariaLabel?: string;
|
|
7
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
8
|
+
export default TriggerButton;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/TriggerButton/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,QAAA,MAAM,aAAa;cAGL,MAAM,IAAI;gBACR,MAAM;eACP,OAAO;gBACN,MAAM;2CAapB,CAAC;AAkBH,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import React from "react";
|
|
5
|
+
import emojiIcon from "../assets/sentiment-satsified.svg.js";
|
|
6
|
+
import { CLS_PREFIX } from "../constants.js";
|
|
7
|
+
const TriggerButton = React.forwardRef(({ onClick, className, disabled, ariaLabel }, ref) => /* @__PURE__ */ jsx(
|
|
8
|
+
"button",
|
|
9
|
+
{
|
|
10
|
+
type: "button",
|
|
11
|
+
className: classNames(`${CLS_PREFIX}-trigger`, className),
|
|
12
|
+
onClick,
|
|
13
|
+
disabled,
|
|
14
|
+
"aria-label": ariaLabel,
|
|
15
|
+
ref,
|
|
16
|
+
children: /* @__PURE__ */ jsx("img", { src: emojiIcon, alt: "emoji picker" })
|
|
17
|
+
}
|
|
18
|
+
));
|
|
19
|
+
TriggerButton.displayName = "CapEmojiPickerTriggerButton";
|
|
20
|
+
TriggerButton.propTypes = {
|
|
21
|
+
onClick: PropTypes.func,
|
|
22
|
+
className: PropTypes.string,
|
|
23
|
+
disabled: PropTypes.bool,
|
|
24
|
+
ariaLabel: PropTypes.string
|
|
25
|
+
};
|
|
26
|
+
TriggerButton.defaultProps = {
|
|
27
|
+
onClick: () => {
|
|
28
|
+
},
|
|
29
|
+
className: "",
|
|
30
|
+
disabled: false,
|
|
31
|
+
ariaLabel: "Insert emoji"
|
|
32
|
+
};
|
|
33
|
+
export {
|
|
34
|
+
TriggerButton as default
|
|
35
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/Wrapper/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4E,MAAM,OAAO,CAAC;;AAsOjG,wBAAmC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { lazy, useState, useRef, useEffect, useCallback, useMemo, Suspense } from "react";
|
|
5
|
+
import { intlShape, injectIntl } from "react-intl";
|
|
6
|
+
import CapLabelWithStatic from "../../CapLabel/index.js";
|
|
7
|
+
import CapPopover from "../../CapPopover/index.js";
|
|
8
|
+
import { INPUT_TEXTAREA_SELECTOR, LOADING_FALLBACK_COLOR, PICKER_HEIGHT, PICKER_WIDTH, CLS_PREFIX, DEFAULT_POPOVER_PLACEMENT } from "../constants.js";
|
|
9
|
+
import TriggerButton from "../TriggerButton/index.js";
|
|
10
|
+
import { resolveInputElement } from "../utils.js";
|
|
11
|
+
import messages from "./messages.js";
|
|
12
|
+
import useEmojiTriggerPosition from "./useEmojiTriggerPosition.js";
|
|
13
|
+
const Picker = lazy(() => import("../Picker/index.js"));
|
|
14
|
+
const Wrapper = ({
|
|
15
|
+
intl: { formatMessage },
|
|
16
|
+
children,
|
|
17
|
+
value,
|
|
18
|
+
onChange,
|
|
19
|
+
textAreaRef,
|
|
20
|
+
// Deprecated: kept for backward compatibility
|
|
21
|
+
inputRef,
|
|
22
|
+
// New preferred prop name
|
|
23
|
+
popoverPlacement,
|
|
24
|
+
disabled,
|
|
25
|
+
onEmojiSelect,
|
|
26
|
+
triggerAriaLabel,
|
|
27
|
+
className,
|
|
28
|
+
popoverClassName,
|
|
29
|
+
pickerClassName
|
|
30
|
+
}) => {
|
|
31
|
+
const [visible, setVisible] = useState(false);
|
|
32
|
+
const wrapperRef = useRef(null);
|
|
33
|
+
const extractedInputRef = useRef(null);
|
|
34
|
+
const inputElementRef = inputRef || textAreaRef;
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!wrapperRef.current) return;
|
|
37
|
+
const rafId = requestAnimationFrame(() => {
|
|
38
|
+
const inputElement = wrapperRef.current.querySelector(INPUT_TEXTAREA_SELECTOR);
|
|
39
|
+
if (inputElement) {
|
|
40
|
+
extractedInputRef.current = inputElement;
|
|
41
|
+
if (inputElementRef) {
|
|
42
|
+
if (typeof inputElementRef === "object" && "current" in inputElementRef) {
|
|
43
|
+
inputElementRef.current = inputElement;
|
|
44
|
+
} else if (typeof inputElementRef === "function") {
|
|
45
|
+
inputElementRef(
|
|
46
|
+
inputElement
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return () => {
|
|
53
|
+
cancelAnimationFrame(rafId);
|
|
54
|
+
if (inputElementRef && typeof inputElementRef === "function") {
|
|
55
|
+
inputElementRef(null);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}, [inputElementRef]);
|
|
59
|
+
const { triggerPositionClass } = useEmojiTriggerPosition(
|
|
60
|
+
wrapperRef,
|
|
61
|
+
inputElementRef,
|
|
62
|
+
value,
|
|
63
|
+
extractedInputRef
|
|
64
|
+
);
|
|
65
|
+
const handleEmojiSelect = useCallback(
|
|
66
|
+
(emojiData) => {
|
|
67
|
+
const emoji = (emojiData == null ? void 0 : emojiData.emoji) || "";
|
|
68
|
+
const target = extractedInputRef.current || resolveInputElement(inputElementRef);
|
|
69
|
+
const currentValue = value || "";
|
|
70
|
+
let nextValue = `${currentValue}${emoji}`;
|
|
71
|
+
if (target && typeof target.selectionStart === "number" && typeof target.selectionEnd === "number") {
|
|
72
|
+
const { selectionStart, selectionEnd } = target;
|
|
73
|
+
nextValue = currentValue.slice(0, selectionStart) + emoji + currentValue.slice(selectionEnd);
|
|
74
|
+
requestAnimationFrame(() => {
|
|
75
|
+
const caret = selectionStart + emoji.length;
|
|
76
|
+
target.focus();
|
|
77
|
+
target.setSelectionRange(caret, caret);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
onChange(nextValue);
|
|
81
|
+
if (onEmojiSelect) {
|
|
82
|
+
onEmojiSelect(emojiData);
|
|
83
|
+
}
|
|
84
|
+
setVisible(false);
|
|
85
|
+
},
|
|
86
|
+
[onChange, onEmojiSelect, inputElementRef, value]
|
|
87
|
+
);
|
|
88
|
+
const content = useMemo(
|
|
89
|
+
() => /* @__PURE__ */ jsx(
|
|
90
|
+
Suspense,
|
|
91
|
+
{
|
|
92
|
+
fallback: /* @__PURE__ */ jsx("div", { className: classNames(`${CLS_PREFIX}-panel`, pickerClassName), children: /* @__PURE__ */ jsx(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
style: {
|
|
96
|
+
width: PICKER_WIDTH,
|
|
97
|
+
height: PICKER_HEIGHT,
|
|
98
|
+
display: "flex",
|
|
99
|
+
alignItems: "center",
|
|
100
|
+
justifyContent: "center",
|
|
101
|
+
color: LOADING_FALLBACK_COLOR
|
|
102
|
+
},
|
|
103
|
+
children: /* @__PURE__ */ jsx(CapLabelWithStatic, { children: formatMessage(messages.loadingMessage) })
|
|
104
|
+
}
|
|
105
|
+
) }),
|
|
106
|
+
children: /* @__PURE__ */ jsx(Picker, { onEmojiSelect: handleEmojiSelect, className: pickerClassName })
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
[handleEmojiSelect, pickerClassName, formatMessage]
|
|
110
|
+
);
|
|
111
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: classNames(`${CLS_PREFIX}-wrapper`, className), children: [
|
|
112
|
+
children,
|
|
113
|
+
!disabled && /* @__PURE__ */ jsx("div", { className: classNames(`${CLS_PREFIX}-trigger-container`, triggerPositionClass), children: /* @__PURE__ */ jsx(
|
|
114
|
+
CapPopover,
|
|
115
|
+
{
|
|
116
|
+
content,
|
|
117
|
+
trigger: "click",
|
|
118
|
+
placement: popoverPlacement,
|
|
119
|
+
overlayClassName: classNames(`${CLS_PREFIX}-popover`, popoverClassName),
|
|
120
|
+
visible,
|
|
121
|
+
onVisibleChange: (nextVisible) => setVisible(nextVisible),
|
|
122
|
+
children: /* @__PURE__ */ jsx(
|
|
123
|
+
TriggerButton,
|
|
124
|
+
{
|
|
125
|
+
ariaLabel: triggerAriaLabel || formatMessage(messages.defaultTriggerAriaLabel)
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
) })
|
|
130
|
+
] });
|
|
131
|
+
};
|
|
132
|
+
Wrapper.propTypes = {
|
|
133
|
+
intl: intlShape.isRequired,
|
|
134
|
+
children: PropTypes.node.isRequired,
|
|
135
|
+
value: PropTypes.string,
|
|
136
|
+
onChange: PropTypes.func.isRequired,
|
|
137
|
+
textAreaRef: PropTypes.oneOfType([PropTypes.shape({ current: PropTypes.any }), PropTypes.any]),
|
|
138
|
+
// Deprecated: use inputRef instead
|
|
139
|
+
inputRef: PropTypes.oneOfType([PropTypes.shape({ current: PropTypes.any }), PropTypes.any]),
|
|
140
|
+
// Ref to the input/textarea element for inserting emoji at cursor position
|
|
141
|
+
popoverPlacement: PropTypes.string,
|
|
142
|
+
disabled: PropTypes.bool,
|
|
143
|
+
onEmojiSelect: PropTypes.func,
|
|
144
|
+
triggerAriaLabel: PropTypes.string,
|
|
145
|
+
className: PropTypes.string,
|
|
146
|
+
popoverClassName: PropTypes.string,
|
|
147
|
+
pickerClassName: PropTypes.string
|
|
148
|
+
};
|
|
149
|
+
Wrapper.defaultProps = {
|
|
150
|
+
value: "",
|
|
151
|
+
textAreaRef: null,
|
|
152
|
+
// Deprecated
|
|
153
|
+
inputRef: null,
|
|
154
|
+
popoverPlacement: DEFAULT_POPOVER_PLACEMENT,
|
|
155
|
+
disabled: false,
|
|
156
|
+
onEmojiSelect: null,
|
|
157
|
+
triggerAriaLabel: null,
|
|
158
|
+
// Will use translated default if not provided
|
|
159
|
+
className: "",
|
|
160
|
+
popoverClassName: "",
|
|
161
|
+
pickerClassName: ""
|
|
162
|
+
};
|
|
163
|
+
const Wrapper$1 = injectIntl(Wrapper);
|
|
164
|
+
export {
|
|
165
|
+
Wrapper$1 as default
|
|
166
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const scope = "app.commonUtils.capUiLibrary.CapEmojiPicker.Wrapper";
|
|
2
|
+
declare const _default: {
|
|
3
|
+
loadingMessage: {
|
|
4
|
+
id: string;
|
|
5
|
+
defaultMessage: string;
|
|
6
|
+
};
|
|
7
|
+
defaultTriggerAriaLabel: {
|
|
8
|
+
id: string;
|
|
9
|
+
defaultMessage: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export default _default;
|
|
13
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/Wrapper/messages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,KAAK,wDAAwD,CAAC;;;;;;;;;;;AAE3E,wBASG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineMessages } from "react-intl";
|
|
2
|
+
const scope = "app.commonUtils.capUiLibrary.CapEmojiPicker.Wrapper";
|
|
3
|
+
const messages = defineMessages({
|
|
4
|
+
loadingMessage: {
|
|
5
|
+
id: `${scope}.loadingMessage`,
|
|
6
|
+
defaultMessage: "Loading emoji picker..."
|
|
7
|
+
},
|
|
8
|
+
defaultTriggerAriaLabel: {
|
|
9
|
+
id: `${scope}.defaultTriggerAriaLabel`,
|
|
10
|
+
defaultMessage: "Insert emoji"
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export {
|
|
14
|
+
messages as default,
|
|
15
|
+
scope
|
|
16
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
type InputElementRef = React.RefObject<HTMLInputElement | HTMLTextAreaElement | null> | ((el: HTMLInputElement | HTMLTextAreaElement | null) => void) | null;
|
|
3
|
+
/**
|
|
4
|
+
* Custom hook to calculate and apply emoji trigger positioning
|
|
5
|
+
* Optimizes DOM queries and style mutations while maintaining backward compatibility
|
|
6
|
+
*
|
|
7
|
+
* @param {React.RefObject} wrapperRef - Ref to the wrapper container
|
|
8
|
+
* @param {React.RefObject|Function} inputElementRef - Ref to the input element (for backward compat)
|
|
9
|
+
* @param {string} value - Current input value
|
|
10
|
+
* @param {React.RefObject} extractedInputRef - Ref to the extracted input element from DOM
|
|
11
|
+
* @returns {Object} { triggerPositionClass, triggerContainerRef } - Position class and ref to container
|
|
12
|
+
*/
|
|
13
|
+
declare const useEmojiTriggerPosition: (wrapperRef: React.RefObject<HTMLDivElement | null>, inputElementRef: InputElementRef, value: string, extractedInputRef: React.RefObject<HTMLInputElement | HTMLTextAreaElement | null>) => {
|
|
14
|
+
triggerPositionClass: string;
|
|
15
|
+
triggerContainerRef: React.MutableRefObject<HTMLDivElement>;
|
|
16
|
+
};
|
|
17
|
+
export default useEmojiTriggerPosition;
|
|
18
|
+
//# sourceMappingURL=useEmojiTriggerPosition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEmojiTriggerPosition.d.ts","sourceRoot":"","sources":["../../../components/CapEmojiPicker/Wrapper/useEmojiTriggerPosition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAK3D,KAAK,eAAe,GAChB,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,CAAC,GAC9D,CAAC,CAAC,EAAE,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,KAAK,IAAI,CAAC,GAC7D,IAAI,CAAC;AAET;;;;;;;;;GASG;AACH,QAAA,MAAM,uBAAuB,GAC3B,YAAY,KAAK,CAAC,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,EAClD,iBAAiB,eAAe,EAChC,OAAO,MAAM,EACb,mBAAmB,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,CAAC;;;CAkKlF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from "react";
|
|
2
|
+
import { CLS_PREFIX, TEXTAREA_TAG, INPUT_TAG } from "../constants.js";
|
|
3
|
+
import { resolveInputElement } from "../utils.js";
|
|
4
|
+
const useEmojiTriggerPosition = (wrapperRef, inputElementRef, value, extractedInputRef) => {
|
|
5
|
+
const [triggerPositionClass, setTriggerPositionClass] = useState("");
|
|
6
|
+
const triggerContainerRef = useRef(null);
|
|
7
|
+
const resizeObserverRef = useRef(null);
|
|
8
|
+
const rafIdRef = useRef(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!wrapperRef.current) {
|
|
11
|
+
setTriggerPositionClass("");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const updatePosition = () => {
|
|
15
|
+
if (rafIdRef.current) {
|
|
16
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
17
|
+
}
|
|
18
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
19
|
+
const target = extractedInputRef.current || resolveInputElement(inputElementRef);
|
|
20
|
+
if (!target || !wrapperRef.current) {
|
|
21
|
+
setTriggerPositionClass("");
|
|
22
|
+
if (triggerContainerRef.current) {
|
|
23
|
+
triggerContainerRef.current.style.setProperty("--emoji-trigger-bottom", "");
|
|
24
|
+
}
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!triggerContainerRef.current) {
|
|
28
|
+
triggerContainerRef.current = wrapperRef.current.querySelector(
|
|
29
|
+
`.${CLS_PREFIX}-trigger-container`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
const tagName = target.tagName;
|
|
33
|
+
const hasValue = (value == null ? void 0 : value.trim().length) > 0;
|
|
34
|
+
const componentWithLabel = wrapperRef.current.querySelector(".component-with-label");
|
|
35
|
+
const inputWrapper = target.closest(".component-with-label-wrapper") || target.closest(".ant-input-affix-wrapper") || target.parentElement;
|
|
36
|
+
const errorMessage = componentWithLabel == null ? void 0 : componentWithLabel.querySelector(".error-message");
|
|
37
|
+
let bottomOffset = null;
|
|
38
|
+
if (errorMessage && inputWrapper && triggerContainerRef.current) {
|
|
39
|
+
const inputWrapperRect = inputWrapper.getBoundingClientRect();
|
|
40
|
+
const wrapperRect = wrapperRef.current.getBoundingClientRect();
|
|
41
|
+
const inputWrapperBottomFromWrapperTop = inputWrapperRect.bottom - wrapperRect.top;
|
|
42
|
+
const distanceFromWrapperBottomToInputWrapperBottom = wrapperRect.height - inputWrapperBottomFromWrapperTop;
|
|
43
|
+
bottomOffset = tagName === TEXTAREA_TAG ? `${distanceFromWrapperBottomToInputWrapperBottom + 4}px` : `${distanceFromWrapperBottomToInputWrapperBottom + 2}px`;
|
|
44
|
+
}
|
|
45
|
+
if (triggerContainerRef.current) {
|
|
46
|
+
if (bottomOffset !== null) {
|
|
47
|
+
triggerContainerRef.current.style.setProperty("--emoji-trigger-bottom", bottomOffset);
|
|
48
|
+
} else {
|
|
49
|
+
triggerContainerRef.current.style.setProperty("--emoji-trigger-bottom", "");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (tagName === TEXTAREA_TAG) {
|
|
53
|
+
setTriggerPositionClass(`${CLS_PREFIX}-trigger-textarea`);
|
|
54
|
+
} else if (tagName === INPUT_TAG) {
|
|
55
|
+
let isSearch = false;
|
|
56
|
+
let hasClearIcon = false;
|
|
57
|
+
const parentElement = target.parentElement;
|
|
58
|
+
const prefixArea = parentElement == null ? void 0 : parentElement.querySelector(".ant-input-prefix");
|
|
59
|
+
const suffixArea = parentElement == null ? void 0 : parentElement.querySelector(".ant-input-suffix");
|
|
60
|
+
if (prefixArea) {
|
|
61
|
+
const hasSearchIcon = prefixArea.querySelector('[class*="search"], [class*="Search"]');
|
|
62
|
+
isSearch = hasSearchIcon !== null;
|
|
63
|
+
}
|
|
64
|
+
if (suffixArea) {
|
|
65
|
+
hasClearIcon = suffixArea.querySelector('.anticon-close, [class*="close"], [class*="Close"]') !== null;
|
|
66
|
+
}
|
|
67
|
+
if (isSearch && hasValue && hasClearIcon) {
|
|
68
|
+
setTriggerPositionClass(`${CLS_PREFIX}-trigger-search-with-value`);
|
|
69
|
+
} else {
|
|
70
|
+
setTriggerPositionClass(`${CLS_PREFIX}-trigger-input`);
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
setTriggerPositionClass("");
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
updatePosition();
|
|
78
|
+
let observeInputTimeout = null;
|
|
79
|
+
if (window.ResizeObserver && wrapperRef.current) {
|
|
80
|
+
resizeObserverRef.current = new ResizeObserver(() => {
|
|
81
|
+
updatePosition();
|
|
82
|
+
});
|
|
83
|
+
resizeObserverRef.current.observe(wrapperRef.current);
|
|
84
|
+
observeInputTimeout = setTimeout(() => {
|
|
85
|
+
const target = extractedInputRef.current || resolveInputElement(inputElementRef);
|
|
86
|
+
if (target && resizeObserverRef.current) {
|
|
87
|
+
resizeObserverRef.current.observe(target);
|
|
88
|
+
}
|
|
89
|
+
}, 0);
|
|
90
|
+
}
|
|
91
|
+
return () => {
|
|
92
|
+
if (rafIdRef.current) {
|
|
93
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
94
|
+
}
|
|
95
|
+
if (resizeObserverRef.current) {
|
|
96
|
+
resizeObserverRef.current.disconnect();
|
|
97
|
+
}
|
|
98
|
+
if (observeInputTimeout) {
|
|
99
|
+
clearTimeout(observeInputTimeout);
|
|
100
|
+
}
|
|
101
|
+
triggerContainerRef.current = null;
|
|
102
|
+
};
|
|
103
|
+
}, [value]);
|
|
104
|
+
return { triggerPositionClass, triggerContainerRef };
|
|
105
|
+
};
|
|
106
|
+
export {
|
|
107
|
+
useEmojiTriggerPosition as default
|
|
108
|
+
};
|