@alifd/chat 0.3.31 → 0.3.32-beta.2

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.
@@ -1,4 +1,5 @@
1
1
  import { HTMLRendererProps } from './types';
2
+ import '../balloon/style';
2
3
  export * from './types';
3
4
  declare const _default: import("@alifd/next/types/config-provider/types").ConfiguredComponentClass<HTMLRendererProps & import("@alifd/next/types/config-provider/types").ComponentCommonProps, unknown, {}>;
4
5
  export default _default;
@@ -15,12 +15,15 @@ import { ConfigProvider } from '@alifd/next';
15
15
  import { PREFIX_DEFAULT, assignSubComponent } from '../utils';
16
16
  import copy from 'copy-to-clipboard';
17
17
  import { Message } from '@alifd/next';
18
+ import Balloon from '../balloon';
19
+ import '../balloon/style';
18
20
  const IMAGE_MAX_HEIGHT = 222;
19
21
  const IMAGE_MAX_WIDTH = 372;
20
22
  const sanitizeHtmlOptions = {
21
23
  allowedTags: sanitizeHtml.defaults.allowedTags.concat([
22
24
  'acronym', 'audio', 'big', 'center', 'del', 'dir', 'font',
23
25
  'img', 'ins', 'source', 'strike', 'track', 'tt', 'video',
26
+ 'link-reference',
24
27
  ]),
25
28
  allowedAttributes: {
26
29
  '*': ['data-*', 'title', 'align', 'bgcolor', 'class', 'style'],
@@ -100,13 +103,36 @@ const HTMLRenderer = memo(function HTMLRenderer({ className, children, imagePrev
100
103
  const parserOptions = {
101
104
  // @ts-ignore
102
105
  replace: domNode => {
103
- var _a;
106
+ var _a, _b, _c, _d, _e, _f;
104
107
  // 处理文本节点
105
108
  if ((domNode.type === 'text' || domNode.nodeType === 3) && typewriterEffect) {
106
109
  return processTextNode(domNode);
107
110
  }
108
111
  if (domNode instanceof Element && domNode.attribs) {
109
112
  const { name } = domNode;
113
+ if (name === 'link-reference') {
114
+ const element = (domToReact([domNode]));
115
+ // link-reference 的子元素一定是 a 标签
116
+ const aElement = (_a = element.props) === null || _a === void 0 ? void 0 : _a.children;
117
+ // a 标签的子元素一定是 span 节点
118
+ const spanElement = (_b = aElement === null || aElement === void 0 ? void 0 : aElement.props) === null || _b === void 0 ? void 0 : _b.children;
119
+ const handleUrlClick = () => {
120
+ var _a;
121
+ if (!((_a = aElement === null || aElement === void 0 ? void 0 : aElement.props) === null || _a === void 0 ? void 0 : _a.href)) {
122
+ return;
123
+ }
124
+ if (handleOpenLink) {
125
+ handleOpenLink === null || handleOpenLink === void 0 ? void 0 : handleOpenLink(aElement.props.href);
126
+ }
127
+ else {
128
+ defaultOpenLink(aElement.props.href);
129
+ }
130
+ };
131
+ return (React.createElement(Balloon, { v2: true, align: "b", className: "link-reference-balloon", closable: false, offset: [0, -8], triggerType: ['hover'], trigger: React.createElement("span", { className: "link-reference-index", onClick: handleUrlClick }, (_c = spanElement === null || spanElement === void 0 ? void 0 : spanElement.props) === null || _c === void 0 ? void 0 : _c.children) },
132
+ React.createElement("div", { className: "link-reference-content" },
133
+ React.createElement("img", { className: "link-reference-source-icon", src: ((_d = element.props) === null || _d === void 0 ? void 0 : _d['data-source-icon']) || '' }),
134
+ React.createElement("a", { className: "link-reference-title", onClick: handleUrlClick }, ((_e = element.props) === null || _e === void 0 ? void 0 : _e['data-title']) || ''))));
135
+ }
110
136
  if (name === 'a') {
111
137
  const element = (domToReact([domNode]));
112
138
  const { props } = element;
@@ -159,7 +185,7 @@ const HTMLRenderer = memo(function HTMLRenderer({ className, children, imagePrev
159
185
  return renderImage(element.props);
160
186
  }
161
187
  // 换成统一的图片渲染
162
- return React.createElement(Img, Object.assign({}, element.props, { imageClassName: (_a = element.props) === null || _a === void 0 ? void 0 : _a.className, enablePreview: imagePreview, onImageClick: () => {
188
+ return React.createElement(Img, Object.assign({}, element.props, { imageClassName: (_f = element.props) === null || _f === void 0 ? void 0 : _f.className, enablePreview: imagePreview, onImageClick: () => {
163
189
  handleImageClick === null || handleImageClick === void 0 ? void 0 : handleImageClick(element.props.src);
164
190
  } }));
165
191
  }
@@ -256,4 +256,86 @@
256
256
  opacity: 1;
257
257
  }
258
258
  }
259
+ .link-reference-index {
260
+ display: inline-block;
261
+ font-size: 10px;
262
+ height: 16px;
263
+ vertical-align: text-bottom;
264
+ border-radius: 4px;
265
+ color: $color-text1-3;
266
+ background-color: $color-fill1-2;
267
+ margin: 0 4px;
268
+ padding: 0 4px;
269
+ cursor: pointer;
270
+ user-select: none;
271
+ --web-kit-user-select: none;
272
+ transition: color 0.3s, background-color 0.3s;
273
+
274
+ @media (hover: hover) {
275
+ &:hover {
276
+ background-color: $color-brand1-6;
277
+ color: $color-bg-1;
278
+ }
279
+ }
280
+
281
+ // 移动端触摸反馈
282
+ &:active {
283
+ background-color: $color-brand1-6;
284
+ color: $color-bg-1;
285
+ }
286
+ }
287
+ }
288
+
289
+ .link-reference-balloon {
290
+ max-width: 168px !important;
291
+ background-color: $color-bg-1 !important;
292
+ border-radius: 6px !important;
293
+ padding: 8px !important;
294
+
295
+ .link-reference-source-icon {
296
+ flex: none;
297
+ width: 28px;
298
+ height: 16px;
299
+ position: relative;
300
+ transition: all 0.3s ease;
301
+
302
+ &::before {
303
+ content: "";
304
+ position: absolute;
305
+ top: 0;
306
+ left: 0;
307
+ width: 100%;
308
+ height: 100%;
309
+ border-radius: 4px;
310
+ display: none;
311
+ }
312
+ }
313
+
314
+ .link-reference-content {
315
+ display: flex;
316
+ align-items: center;
317
+ gap: 4px;
318
+ .link-reference-title {
319
+ overflow: hidden;
320
+ text-overflow: ellipsis;
321
+ white-space: nowrap;
322
+ }
323
+ }
324
+
325
+ .next-balloon-arrow {
326
+ display: none !important;
327
+ }
328
+ a {
329
+ cursor: pointer;
330
+ color: $color-link-1;
331
+ text-decoration: none;
332
+ &:hover {
333
+ color: $color-link-2;
334
+ text-decoration: none;
335
+ }
336
+ &:focus, &:visited {
337
+ color: $color-link-3;
338
+ text-decoration: none;
339
+ }
340
+ }
259
341
  }
package/es/index.js CHANGED
@@ -31,4 +31,4 @@ export { default as RadioGroup } from './radio-group';
31
31
  export { default as CheckboxGroup } from './checkbox-group';
32
32
  export { default as Select } from './select';
33
33
  export { default as Flip } from './flip';
34
- export const version = '0.3.31';
34
+ export const version = '0.3.32-beta.2';
@@ -1,4 +1,5 @@
1
1
  import { HTMLRendererProps } from './types';
2
+ import '../balloon/style';
2
3
  export * from './types';
3
4
  declare const _default: import("@alifd/next/types/config-provider/types").ConfiguredComponentClass<HTMLRendererProps & import("@alifd/next/types/config-provider/types").ComponentCommonProps, unknown, {}>;
4
5
  export default _default;
@@ -18,12 +18,15 @@ const next_1 = require("@alifd/next");
18
18
  const utils_1 = require("../utils");
19
19
  const copy_to_clipboard_1 = tslib_1.__importDefault(require("copy-to-clipboard"));
20
20
  const next_2 = require("@alifd/next");
21
+ const balloon_1 = tslib_1.__importDefault(require("../balloon"));
22
+ require("../balloon/style");
21
23
  const IMAGE_MAX_HEIGHT = 222;
22
24
  const IMAGE_MAX_WIDTH = 372;
23
25
  const sanitizeHtmlOptions = {
24
26
  allowedTags: sanitize_html_1.default.defaults.allowedTags.concat([
25
27
  'acronym', 'audio', 'big', 'center', 'del', 'dir', 'font',
26
28
  'img', 'ins', 'source', 'strike', 'track', 'tt', 'video',
29
+ 'link-reference',
27
30
  ]),
28
31
  allowedAttributes: {
29
32
  '*': ['data-*', 'title', 'align', 'bgcolor', 'class', 'style'],
@@ -103,13 +106,36 @@ const HTMLRenderer = (0, react_1.memo)(function HTMLRenderer({ className, childr
103
106
  const parserOptions = {
104
107
  // @ts-ignore
105
108
  replace: domNode => {
106
- var _a;
109
+ var _a, _b, _c, _d, _e, _f;
107
110
  // 处理文本节点
108
111
  if ((domNode.type === 'text' || domNode.nodeType === 3) && typewriterEffect) {
109
112
  return processTextNode(domNode);
110
113
  }
111
114
  if (domNode instanceof html_react_parser_1.Element && domNode.attribs) {
112
115
  const { name } = domNode;
116
+ if (name === 'link-reference') {
117
+ const element = ((0, html_react_parser_1.domToReact)([domNode]));
118
+ // link-reference 的子元素一定是 a 标签
119
+ const aElement = (_a = element.props) === null || _a === void 0 ? void 0 : _a.children;
120
+ // a 标签的子元素一定是 span 节点
121
+ const spanElement = (_b = aElement === null || aElement === void 0 ? void 0 : aElement.props) === null || _b === void 0 ? void 0 : _b.children;
122
+ const handleUrlClick = () => {
123
+ var _a;
124
+ if (!((_a = aElement === null || aElement === void 0 ? void 0 : aElement.props) === null || _a === void 0 ? void 0 : _a.href)) {
125
+ return;
126
+ }
127
+ if (handleOpenLink) {
128
+ handleOpenLink === null || handleOpenLink === void 0 ? void 0 : handleOpenLink(aElement.props.href);
129
+ }
130
+ else {
131
+ defaultOpenLink(aElement.props.href);
132
+ }
133
+ };
134
+ return (react_1.default.createElement(balloon_1.default, { v2: true, align: "b", className: "link-reference-balloon", closable: false, offset: [0, -8], triggerType: ['hover'], trigger: react_1.default.createElement("span", { className: "link-reference-index", onClick: handleUrlClick }, (_c = spanElement === null || spanElement === void 0 ? void 0 : spanElement.props) === null || _c === void 0 ? void 0 : _c.children) },
135
+ react_1.default.createElement("div", { className: "link-reference-content" },
136
+ react_1.default.createElement("img", { className: "link-reference-source-icon", src: ((_d = element.props) === null || _d === void 0 ? void 0 : _d['data-source-icon']) || '' }),
137
+ react_1.default.createElement("a", { className: "link-reference-title", onClick: handleUrlClick }, ((_e = element.props) === null || _e === void 0 ? void 0 : _e['data-title']) || ''))));
138
+ }
113
139
  if (name === 'a') {
114
140
  const element = ((0, html_react_parser_1.domToReact)([domNode]));
115
141
  const { props } = element;
@@ -162,7 +188,7 @@ const HTMLRenderer = (0, react_1.memo)(function HTMLRenderer({ className, childr
162
188
  return renderImage(element.props);
163
189
  }
164
190
  // 换成统一的图片渲染
165
- return react_1.default.createElement(img_1.default, Object.assign({}, element.props, { imageClassName: (_a = element.props) === null || _a === void 0 ? void 0 : _a.className, enablePreview: imagePreview, onImageClick: () => {
191
+ return react_1.default.createElement(img_1.default, Object.assign({}, element.props, { imageClassName: (_f = element.props) === null || _f === void 0 ? void 0 : _f.className, enablePreview: imagePreview, onImageClick: () => {
166
192
  handleImageClick === null || handleImageClick === void 0 ? void 0 : handleImageClick(element.props.src);
167
193
  } }));
168
194
  }
@@ -256,4 +256,86 @@
256
256
  opacity: 1;
257
257
  }
258
258
  }
259
+ .link-reference-index {
260
+ display: inline-block;
261
+ font-size: 10px;
262
+ height: 16px;
263
+ vertical-align: text-bottom;
264
+ border-radius: 4px;
265
+ color: $color-text1-3;
266
+ background-color: $color-fill1-2;
267
+ margin: 0 4px;
268
+ padding: 0 4px;
269
+ cursor: pointer;
270
+ user-select: none;
271
+ --web-kit-user-select: none;
272
+ transition: color 0.3s, background-color 0.3s;
273
+
274
+ @media (hover: hover) {
275
+ &:hover {
276
+ background-color: $color-brand1-6;
277
+ color: $color-bg-1;
278
+ }
279
+ }
280
+
281
+ // 移动端触摸反馈
282
+ &:active {
283
+ background-color: $color-brand1-6;
284
+ color: $color-bg-1;
285
+ }
286
+ }
287
+ }
288
+
289
+ .link-reference-balloon {
290
+ max-width: 168px !important;
291
+ background-color: $color-bg-1 !important;
292
+ border-radius: 6px !important;
293
+ padding: 8px !important;
294
+
295
+ .link-reference-source-icon {
296
+ flex: none;
297
+ width: 28px;
298
+ height: 16px;
299
+ position: relative;
300
+ transition: all 0.3s ease;
301
+
302
+ &::before {
303
+ content: "";
304
+ position: absolute;
305
+ top: 0;
306
+ left: 0;
307
+ width: 100%;
308
+ height: 100%;
309
+ border-radius: 4px;
310
+ display: none;
311
+ }
312
+ }
313
+
314
+ .link-reference-content {
315
+ display: flex;
316
+ align-items: center;
317
+ gap: 4px;
318
+ .link-reference-title {
319
+ overflow: hidden;
320
+ text-overflow: ellipsis;
321
+ white-space: nowrap;
322
+ }
323
+ }
324
+
325
+ .next-balloon-arrow {
326
+ display: none !important;
327
+ }
328
+ a {
329
+ cursor: pointer;
330
+ color: $color-link-1;
331
+ text-decoration: none;
332
+ &:hover {
333
+ color: $color-link-2;
334
+ text-decoration: none;
335
+ }
336
+ &:focus, &:visited {
337
+ color: $color-link-3;
338
+ text-decoration: none;
339
+ }
340
+ }
259
341
  }
package/lib/index.js CHANGED
@@ -68,4 +68,4 @@ var select_1 = require("./select");
68
68
  Object.defineProperty(exports, "Select", { enumerable: true, get: function () { return tslib_1.__importDefault(select_1).default; } });
69
69
  var flip_1 = require("./flip");
70
70
  Object.defineProperty(exports, "Flip", { enumerable: true, get: function () { return tslib_1.__importDefault(flip_1).default; } });
71
- exports.version = '0.3.31';
71
+ exports.version = '0.3.32-beta.2';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alifd/chat",
3
- "version": "0.3.31",
3
+ "version": "0.3.32-beta.2",
4
4
  "description": "A configurable component library for chat built on React.",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",