@lark-apaas/client-toolkit 1.2.52-alpha.0 → 1.2.52-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,5 +8,8 @@ export interface UniversalLinkProps extends Omit<React.AnchorHTMLAttributes<HTML
8
8
  * - 内部路由(/dashboard)→ react-router Link
9
9
  * - Hash 锚点(#section)→ <a>
10
10
  * - 外链(https://...)→ <a target="_blank">
11
+ *
12
+ * 预览态(iframe 内)时,通过 postMessage 通知父页面处理链接跳转,
13
+ * 避免浏览器安全策略限制导致链接无法正常打开。
11
14
  */
12
15
  export declare const UniversalLink: React.ForwardRefExoticComponent<UniversalLinkProps & React.RefAttributes<HTMLAnchorElement>>;
@@ -1,23 +1,62 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import react from "react";
3
3
  import { Link } from "react-router-dom";
4
+ import { isPreview } from "../../utils/utils.js";
5
+ import { getParentOriginFromParams, submitPostMessage } from "../../utils/postMessage.js";
4
6
  function isInternalRoute(to) {
5
7
  return !to.startsWith('#') && !to.startsWith('http://') && !to.startsWith('https://') && !to.startsWith('//');
6
8
  }
7
9
  function isExternalLink(to) {
8
10
  return to.startsWith('http://') || to.startsWith('https://') || to.startsWith('//');
9
11
  }
10
- const UniversalLink_UniversalLink = /*#__PURE__*/ react.forwardRef(function({ to, ...props }, ref) {
12
+ function isIframeUnderMainHost() {
13
+ if ('undefined' == typeof window) return false;
14
+ if (window.parent === window) return false;
15
+ if (getParentOriginFromParams()) return true;
16
+ const envOrigin = process.env.FORCE_FRAMEWORK_DOMAIN_MAIN;
17
+ if (!envOrigin || !document.referrer) return false;
18
+ try {
19
+ return new URL(document.referrer).origin === envOrigin;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ const UniversalLink_UniversalLink = /*#__PURE__*/ react.forwardRef(function({ to, onClick, ...props }, ref) {
25
+ const isExternal = isExternalLink(to);
26
+ const preview = (isPreview() || isIframeUnderMainHost()) && isExternal;
27
+ if (preview) {
28
+ const handlePreviewClick = (e)=>{
29
+ e.preventDefault();
30
+ onClick?.(e);
31
+ submitPostMessage({
32
+ type: 'OpenIframeLink',
33
+ data: {
34
+ href: to,
35
+ external: true
36
+ }
37
+ });
38
+ };
39
+ return /*#__PURE__*/ jsx("a", {
40
+ href: to,
41
+ ref: ref,
42
+ ...props,
43
+ onClick: handlePreviewClick,
44
+ target: props.target ?? '_blank',
45
+ rel: props.rel ?? 'noopener noreferrer'
46
+ });
47
+ }
11
48
  if (isInternalRoute(to)) return /*#__PURE__*/ jsx(Link, {
12
49
  to: to,
13
50
  ref: ref,
14
- ...props
51
+ ...props,
52
+ onClick: onClick
15
53
  });
16
54
  return /*#__PURE__*/ jsx("a", {
17
55
  href: to,
18
56
  ref: ref,
19
57
  ...props,
20
- ...isExternalLink(to) && {
58
+ onClick: onClick,
59
+ ...isExternal && {
21
60
  target: props.target ?? '_blank',
22
61
  rel: props.rel ?? 'noopener noreferrer'
23
62
  }
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ /**
3
+ * 打开「投诉与举报」页:scene/entity_type 固定,entity_id 取当前妙搭 appId(getAppId →
4
+ * window.appId,水印仅豆包应用展示,此时必有 appId),域名按环境选,params 整体 encode。
5
+ */
6
+ export declare const openDoubaoReport: () => void;
7
+ export declare const FeedbackIcon: React.FC;
8
+ export declare const CloseIcon: React.FC<{
9
+ size: number;
10
+ }>;
11
+ export declare const Avatar: React.FC<{
12
+ size: number;
13
+ }>;
14
+ export declare const Pill: React.FC<{
15
+ variant: 'desktop' | 'mobile';
16
+ onClose?: () => void;
17
+ showClose?: boolean;
18
+ }>;
19
+ export declare const MenuRow: React.FC<{
20
+ icon: 'feedback' | 'close';
21
+ label: string;
22
+ fontSize: number;
23
+ onClick?: () => void;
24
+ }>;
25
+ type MenuItem = {
26
+ icon: 'feedback' | 'close';
27
+ label: string;
28
+ onClick?: () => void;
29
+ };
30
+ export declare const MenuCard: React.FC<{
31
+ items: MenuItem[];
32
+ fontSize: number;
33
+ footerFontSize: number;
34
+ minWidth: number;
35
+ style?: React.CSSProperties;
36
+ }>;
37
+ /**
38
+ * 豆包水印:仅当应用来源为豆包时,在视口右下角展示收起态药丸(头像 +「豆包AI」)。
39
+ *
40
+ * 设计稿:Figma 1582:41560(桌面)/ 1582:41777(移动)。
41
+ * - 药丸 / 卡片本体用代码画(投影走 CSS box-shadow、图标用无滤镜小 SVG),高分屏清晰。
42
+ * - 桌面端点关闭叉 → 隐藏整个水印;hover 徽标 → 上方弹白色卡片(投诉与举报 + 由飞书妙搭提供支持)。
43
+ * - 移动端 tap 徽标 → 上方弹卡片(投诉与举报 / 不再展示 / 由飞书妙搭提供支持)。
44
+ * - 「投诉与举报」点击跳飞书风控举报中心(tns,域名随环境);后端链接未就绪时由 REPORT_ENABLED 整体隐藏。
45
+ * - 不加 NODE_ENV 判断——预览态与运行态都要展示。
46
+ */
47
+ declare const Watermark: React.FC;
48
+ export default Watermark;
@@ -0,0 +1,352 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState } from "react";
3
+ import { Content, Portal, Root, Trigger } from "@radix-ui/react-popover";
4
+ import { DOUBAO_LOGO_SRC, DOUBAO_PILL_MOBILE_PNG } from "./doubao-watermark-asset.js";
5
+ import { getAppId } from "../../utils/getAppId.js";
6
+ import { useIsMobile } from "../../hooks/index.js";
7
+ const REPORT_ENABLED = true;
8
+ const BRAND_TEXT = '豆包 AI 生成';
9
+ const POWERED_BY_TEXT = '由飞书妙搭提供支持';
10
+ const FONT_FAMILY = "'PingFang SC', -apple-system, BlinkMacSystemFont, sans-serif";
11
+ const PILL_SHADOW = '0px 8px 32px rgba(0,0,0,0.08), 0px 4px 16px rgba(0,0,0,0.04), 0px 2px 4px rgba(0,0,0,0.02)';
12
+ const CARD_SHADOW = '0px 4px 16px rgba(0,0,0,0.03), 0px 4px 10px rgba(0,0,0,0.03), 0px 2px 4px rgba(0,0,0,0.02)';
13
+ const reportDomainByEnv = (env)=>{
14
+ if ('boe' === env) return 'tns.feishu-boe.cn';
15
+ if ('pre' === env) return 'tns.feishu-pre.cn';
16
+ return 'tns.feishu.cn';
17
+ };
18
+ const openDoubaoReport = ()=>{
19
+ const params = JSON.stringify({
20
+ scene: 'miaoda_app_report',
21
+ entity_id: getAppId() ?? '',
22
+ entity_type: 'miaoda_app',
23
+ extra: ''
24
+ });
25
+ const domain = reportDomainByEnv(process.env.FORCE_FRAMEWORK_ENVIRONMENT);
26
+ const url = `https://${domain}/cust/lark_report/?type=common&params=${encodeURIComponent(params)}&lang=zh-CN`;
27
+ window.open(url, '_blank', 'noopener,noreferrer');
28
+ };
29
+ const FeedbackIcon = ()=>/*#__PURE__*/ jsxs("svg", {
30
+ width: 16,
31
+ height: 16,
32
+ viewBox: "0 0 16 16",
33
+ fill: "none",
34
+ xmlns: "http://www.w3.org/2000/svg",
35
+ style: {
36
+ display: 'block',
37
+ flexShrink: 0
38
+ },
39
+ children: [
40
+ /*#__PURE__*/ jsx("path", {
41
+ d: "M12.6667 2H3.33333V14H6.66667V15.3334H3.33333C2.59695 15.3334 2 14.7364 2 14V2C2 1.26364 2.59695 0.666687 3.33333 0.666687H12.6667C13.403 0.666687 14 1.26364 14 2V7.33335H12.6667V2Z",
42
+ fill: "currentColor"
43
+ }),
44
+ /*#__PURE__*/ jsx("path", {
45
+ d: "M5.33333 4.66669C4.96514 4.66669 4.66667 4.96516 4.66667 5.33335C4.66667 5.70154 4.96514 6 5.33333 6H10.6667C11.0349 6 11.3333 5.70154 11.3333 5.33335C11.3333 4.96516 11.0349 4.66669 10.6667 4.66669H5.33333Z",
46
+ fill: "currentColor"
47
+ }),
48
+ /*#__PURE__*/ jsx("path", {
49
+ d: "M4.66667 8.33335C4.66667 7.96516 4.96514 7.66669 5.33333 7.66669H8C8.36819 7.66669 8.66667 7.96516 8.66667 8.33335C8.66667 8.70154 8.36819 9 8 9H5.33333C4.96514 9 4.66667 8.70154 4.66667 8.33335Z",
50
+ fill: "currentColor"
51
+ }),
52
+ /*#__PURE__*/ jsx("path", {
53
+ d: "M13.5523 8.70017C13.9428 8.30964 14.576 8.30964 14.9665 8.70017C15.357 9.09069 15.357 9.72386 14.9665 10.1144L14.2594 10.8215L12.8452 9.40728L13.5523 8.70017Z",
54
+ fill: "currentColor"
55
+ }),
56
+ /*#__PURE__*/ jsx("path", {
57
+ d: "M12.1381 10.1144L13.5523 11.5286L10.2309 14.85C10.0916 14.9892 9.91229 15.0815 9.71798 15.1138L8.45737 15.3234C8.42136 15.3294 8.38467 15.3177 8.35885 15.2918C8.33271 15.2657 8.32099 15.2284 8.32749 15.192L8.55128 13.9374C8.58465 13.7502 8.6746 13.5779 8.80901 13.4435L12.1381 10.1144Z",
58
+ fill: "currentColor"
59
+ })
60
+ ]
61
+ });
62
+ const CloseIcon = ({ size })=>/*#__PURE__*/ jsx("svg", {
63
+ width: size,
64
+ height: size,
65
+ viewBox: "0 0 10 10",
66
+ fill: "none",
67
+ xmlns: "http://www.w3.org/2000/svg",
68
+ style: {
69
+ display: 'block',
70
+ flexShrink: 0
71
+ },
72
+ children: /*#__PURE__*/ jsx("path", {
73
+ d: "M8.08312 8.08298C8.2384 7.92769 8.23953 7.67705 8.08424 7.52176L5.3625 4.80002L8.08422 2.07829C8.23951 1.92301 8.23839 1.67236 8.0831 1.51708C7.92781 1.36179 7.67717 1.36066 7.52188 1.51595C7.36659 1.67124 4.80016 4.23767 4.80016 4.23767L2.07841 1.51593C1.92313 1.36064 1.67248 1.36177 1.5172 1.51705C1.36191 1.67234 1.36078 1.92298 1.51607 2.07827L4.23782 4.80002L1.51605 7.52178C1.36076 7.67707 1.36189 7.92771 1.51718 8.083C1.67246 8.23829 1.92311 8.23941 2.07839 8.08412L4.80016 5.36236L7.5219 8.0841C7.67719 8.23939 7.92783 8.23826 8.08312 8.08298Z",
74
+ fill: "currentColor"
75
+ })
76
+ });
77
+ const Avatar = ({ size })=>/*#__PURE__*/ jsx("img", {
78
+ src: DOUBAO_LOGO_SRC,
79
+ width: size,
80
+ height: size,
81
+ alt: "",
82
+ style: {
83
+ width: size,
84
+ height: size,
85
+ maxWidth: 'none',
86
+ maxHeight: 'none',
87
+ borderRadius: 100,
88
+ flexShrink: 0,
89
+ display: 'block'
90
+ }
91
+ });
92
+ const Pill = ({ variant, onClose, showClose = false })=>{
93
+ const isDesktop = 'desktop' === variant;
94
+ return /*#__PURE__*/ jsxs("div", {
95
+ style: {
96
+ boxSizing: 'border-box',
97
+ display: 'inline-flex',
98
+ alignItems: 'center',
99
+ gap: isDesktop ? 4 : 6,
100
+ padding: isDesktop ? '6px 12px 6px 8px' : '4px 12px 4px 8px',
101
+ background: '#363636',
102
+ border: '0.5px solid rgba(255,255,255,0.1)',
103
+ borderRadius: 100,
104
+ boxShadow: PILL_SHADOW,
105
+ cursor: 'pointer'
106
+ },
107
+ children: [
108
+ /*#__PURE__*/ jsx(Avatar, {
109
+ size: isDesktop ? 16 : 18
110
+ }),
111
+ /*#__PURE__*/ jsx("span", {
112
+ style: {
113
+ fontFamily: FONT_FAMILY,
114
+ fontSize: isDesktop ? 12 : 14,
115
+ lineHeight: isDesktop ? '18px' : '22px',
116
+ color: 'rgba(255,255,255,0.85)',
117
+ whiteSpace: 'nowrap'
118
+ },
119
+ children: BRAND_TEXT
120
+ }),
121
+ isDesktop && onClose && showClose && /*#__PURE__*/ jsx("span", {
122
+ role: "button",
123
+ "aria-label": "关闭",
124
+ onClick: (e)=>{
125
+ e.stopPropagation();
126
+ onClose();
127
+ },
128
+ style: {
129
+ display: 'inline-flex',
130
+ alignItems: 'center',
131
+ cursor: 'pointer',
132
+ flexShrink: 0,
133
+ color: 'rgba(255,255,255,0.5)'
134
+ },
135
+ children: /*#__PURE__*/ jsx(CloseIcon, {
136
+ size: 10
137
+ })
138
+ })
139
+ ]
140
+ });
141
+ };
142
+ const MenuRow = ({ icon, label, fontSize, onClick })=>{
143
+ const [hover, setHover] = useState(false);
144
+ return /*#__PURE__*/ jsxs("div", {
145
+ role: "menuitem",
146
+ "data-label": label,
147
+ onClick: onClick,
148
+ onMouseEnter: ()=>setHover(true),
149
+ onMouseLeave: ()=>setHover(false),
150
+ style: {
151
+ boxSizing: 'border-box',
152
+ display: 'flex',
153
+ alignItems: 'center',
154
+ gap: 8,
155
+ padding: '4px 10px',
156
+ borderRadius: 6,
157
+ cursor: 'pointer',
158
+ color: '#000000',
159
+ background: hover ? 'rgba(0,0,0,0.04)' : 'transparent'
160
+ },
161
+ children: [
162
+ /*#__PURE__*/ jsx("span", {
163
+ style: {
164
+ display: 'inline-flex',
165
+ width: 16,
166
+ height: 16,
167
+ flexShrink: 0,
168
+ color: '#000000'
169
+ },
170
+ children: 'feedback' === icon ? /*#__PURE__*/ jsx(FeedbackIcon, {}) : /*#__PURE__*/ jsx(CloseIcon, {
171
+ size: 16
172
+ })
173
+ }),
174
+ /*#__PURE__*/ jsx("span", {
175
+ style: {
176
+ fontFamily: FONT_FAMILY,
177
+ fontSize,
178
+ lineHeight: `${fontSize + 8}px`,
179
+ color: '#000000',
180
+ whiteSpace: 'nowrap'
181
+ },
182
+ children: label
183
+ })
184
+ ]
185
+ });
186
+ };
187
+ const MenuCard = ({ items, fontSize, footerFontSize, minWidth, style })=>/*#__PURE__*/ jsxs("div", {
188
+ style: {
189
+ boxSizing: 'border-box',
190
+ display: 'flex',
191
+ flexDirection: 'column',
192
+ minWidth,
193
+ background: '#ffffff',
194
+ border: '0.5px solid rgba(0,0,0,0.1)',
195
+ borderRadius: 10,
196
+ boxShadow: CARD_SHADOW,
197
+ overflow: 'hidden',
198
+ outline: 'none',
199
+ ...style
200
+ },
201
+ children: [
202
+ items.length > 0 && /*#__PURE__*/ jsx("div", {
203
+ style: {
204
+ boxSizing: 'border-box',
205
+ padding: 4
206
+ },
207
+ children: items.map((it)=>/*#__PURE__*/ jsx(MenuRow, {
208
+ icon: it.icon,
209
+ label: it.label,
210
+ fontSize: fontSize,
211
+ onClick: it.onClick
212
+ }, it.label))
213
+ }),
214
+ /*#__PURE__*/ jsx("div", {
215
+ style: {
216
+ boxSizing: 'border-box',
217
+ background: '#f9f9f9',
218
+ padding: '8px 14px',
219
+ fontFamily: FONT_FAMILY,
220
+ fontSize: footerFontSize,
221
+ lineHeight: `${footerFontSize + 8}px`,
222
+ color: 'rgba(0,0,0,0.35)',
223
+ whiteSpace: 'nowrap'
224
+ },
225
+ children: POWERED_BY_TEXT
226
+ })
227
+ ]
228
+ });
229
+ const MobileWatermark = ({ onDontShow })=>{
230
+ const [open, setOpen] = useState(false);
231
+ const items = [];
232
+ if (REPORT_ENABLED) items.push({
233
+ icon: 'feedback',
234
+ label: '投诉与举报',
235
+ onClick: openDoubaoReport
236
+ });
237
+ items.push({
238
+ icon: 'close',
239
+ label: '不再展示',
240
+ onClick: ()=>{
241
+ setOpen(false);
242
+ onDontShow();
243
+ }
244
+ });
245
+ return /*#__PURE__*/ jsxs(Root, {
246
+ open: open,
247
+ onOpenChange: setOpen,
248
+ children: [
249
+ /*#__PURE__*/ jsx(Trigger, {
250
+ asChild: true,
251
+ children: /*#__PURE__*/ jsx("div", {
252
+ "data-custom-element": "doubao-watermark-mobile",
253
+ style: {
254
+ position: 'fixed',
255
+ right: 12,
256
+ bottom: 12,
257
+ width: 122,
258
+ height: 30,
259
+ zIndex: 9999,
260
+ cursor: 'pointer'
261
+ },
262
+ children: /*#__PURE__*/ jsx("img", {
263
+ src: DOUBAO_PILL_MOBILE_PNG,
264
+ width: 166,
265
+ height: 94,
266
+ alt: "豆包 AI 生成",
267
+ style: {
268
+ position: 'absolute',
269
+ right: -12,
270
+ bottom: -40,
271
+ width: 166,
272
+ height: 94,
273
+ maxWidth: 'none',
274
+ maxHeight: 'none',
275
+ display: 'block',
276
+ pointerEvents: 'none'
277
+ }
278
+ })
279
+ })
280
+ }),
281
+ /*#__PURE__*/ jsx(Portal, {
282
+ children: /*#__PURE__*/ jsx(Content, {
283
+ side: "top",
284
+ align: "end",
285
+ sideOffset: 8,
286
+ style: {
287
+ outline: 'none'
288
+ },
289
+ children: /*#__PURE__*/ jsx(MenuCard, {
290
+ items: items,
291
+ fontSize: 16,
292
+ footerFontSize: 14,
293
+ minWidth: 160
294
+ })
295
+ })
296
+ })
297
+ ]
298
+ });
299
+ };
300
+ const Watermark_Watermark = ()=>{
301
+ const [closed, setClosed] = useState(false);
302
+ const [open, setOpen] = useState(false);
303
+ const timer = useRef(null);
304
+ const isMobile = useIsMobile();
305
+ if (closed) return null;
306
+ if (isMobile) return /*#__PURE__*/ jsx(MobileWatermark, {
307
+ onDontShow: ()=>setClosed(true)
308
+ });
309
+ const enter = ()=>{
310
+ if (timer.current) clearTimeout(timer.current);
311
+ setOpen(true);
312
+ };
313
+ const leave = ()=>{
314
+ timer.current = setTimeout(()=>setOpen(false), 100);
315
+ };
316
+ const desktopItems = [];
317
+ if (REPORT_ENABLED) desktopItems.push({
318
+ icon: 'feedback',
319
+ label: '投诉与举报',
320
+ onClick: openDoubaoReport
321
+ });
322
+ return /*#__PURE__*/ jsxs("div", {
323
+ "data-custom-element": "doubao-watermark",
324
+ onMouseEnter: enter,
325
+ onMouseLeave: leave,
326
+ style: {
327
+ position: 'fixed',
328
+ right: 12,
329
+ bottom: 12,
330
+ zIndex: 9999,
331
+ display: 'flex',
332
+ flexDirection: 'column',
333
+ alignItems: 'flex-end',
334
+ gap: 8
335
+ },
336
+ children: [
337
+ open && /*#__PURE__*/ jsx(MenuCard, {
338
+ items: desktopItems,
339
+ fontSize: 14,
340
+ footerFontSize: 12,
341
+ minWidth: 144
342
+ }),
343
+ /*#__PURE__*/ jsx(Pill, {
344
+ variant: "desktop",
345
+ onClose: ()=>setClosed(true),
346
+ showClose: open
347
+ })
348
+ ]
349
+ });
350
+ };
351
+ const Watermark = Watermark_Watermark;
352
+ export { Avatar, CloseIcon, FeedbackIcon, MenuCard, MenuRow, Pill, Watermark as default, openDoubaoReport };
@@ -0,0 +1,113 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import react from "react";
3
+ import { renderToStaticMarkup } from "react-dom/server";
4
+ import Watermark, { Avatar, CloseIcon, FeedbackIcon, MenuCard, Pill, openDoubaoReport } from "../Watermark.js";
5
+ import { DOUBAO_LOGO_SRC, DOUBAO_PILL_MOBILE_PNG } from "../doubao-watermark-asset.js";
6
+ const html = ()=>renderToStaticMarkup(/*#__PURE__*/ react.createElement(Watermark));
7
+ const setViewportWidth = (w)=>Object.defineProperty(window, 'innerWidth', {
8
+ value: w,
9
+ configurable: true
10
+ });
11
+ afterEach(()=>{
12
+ vi.unstubAllEnvs();
13
+ vi.restoreAllMocks();
14
+ setViewportWidth(1024);
15
+ });
16
+ describe('Watermark(豆包来源水印)', ()=>{
17
+ it('豆包来源(MIAODA_APP_SOURCE=5)时展示收起态药丸(头像 + 豆包 AI 生成)', ()=>{
18
+ vi.stubEnv('MIAODA_APP_SOURCE', '5');
19
+ const out = html();
20
+ expect(out).toContain('data-custom-element="doubao-watermark"');
21
+ expect(out).toContain('豆包 AI 生成');
22
+ expect(out).toContain(DOUBAO_LOGO_SRC);
23
+ expect(out).not.toContain('aria-label="关闭"');
24
+ expect(out).not.toContain('投诉与举报');
25
+ expect(out).not.toContain('由飞书妙搭提供支持');
26
+ });
27
+ it('移动端视口(<768)时展示移动端药丸(doubao-watermark-mobile)而非桌面药丸', ()=>{
28
+ vi.stubEnv('MIAODA_APP_SOURCE', '5');
29
+ setViewportWidth(375);
30
+ const out = html();
31
+ expect(out).toContain('data-custom-element="doubao-watermark-mobile"');
32
+ expect(out).toContain(DOUBAO_PILL_MOBILE_PNG);
33
+ expect(out).toContain('豆包 AI 生成');
34
+ expect(out).not.toContain('aria-label="关闭"');
35
+ });
36
+ it('非豆包来源(其它 enum)时不渲染', ()=>{
37
+ vi.stubEnv('MIAODA_APP_SOURCE', '3');
38
+ expect(html()).toBe('');
39
+ });
40
+ it('来源未注入时不渲染(String(undefined) !== "5")', ()=>{
41
+ expect(html()).toBe('');
42
+ });
43
+ describe('展开态展示组件(SSR 覆盖)', ()=>{
44
+ it('Pill 桌面态:头像 + 豆包 AI 生成;关闭叉仅 showClose 时显示', ()=>{
45
+ const out = renderToStaticMarkup(/*#__PURE__*/ react.createElement(Pill, {
46
+ variant: 'desktop',
47
+ onClose: ()=>{}
48
+ }));
49
+ expect(out).toContain('豆包 AI 生成');
50
+ expect(out).toContain(DOUBAO_LOGO_SRC);
51
+ expect(out).not.toContain('aria-label="关闭"');
52
+ const hovered = renderToStaticMarkup(/*#__PURE__*/ react.createElement(Pill, {
53
+ variant: 'desktop',
54
+ onClose: ()=>{},
55
+ showClose: true
56
+ }));
57
+ expect(hovered).toContain('aria-label="关闭"');
58
+ });
59
+ it('Pill 移动态:头像 + 豆包 AI 生成,无关闭叉', ()=>{
60
+ const out = renderToStaticMarkup(/*#__PURE__*/ react.createElement(Pill, {
61
+ variant: 'mobile'
62
+ }));
63
+ expect(out).toContain('豆包 AI 生成');
64
+ expect(out).not.toContain('aria-label="关闭"');
65
+ });
66
+ it('MenuCard:投诉与举报 + 不再展示 行 + 由飞书妙搭提供支持 页脚', ()=>{
67
+ const out = renderToStaticMarkup(/*#__PURE__*/ react.createElement(MenuCard, {
68
+ items: [
69
+ {
70
+ icon: 'feedback',
71
+ label: '投诉与举报',
72
+ onClick: ()=>{}
73
+ },
74
+ {
75
+ icon: 'close',
76
+ label: '不再展示',
77
+ onClick: ()=>{}
78
+ }
79
+ ],
80
+ fontSize: 16,
81
+ footerFontSize: 14,
82
+ minWidth: 160
83
+ }));
84
+ expect(out).toContain('data-label="投诉与举报"');
85
+ expect(out).toContain('data-label="不再展示"');
86
+ expect(out).toContain('由飞书妙搭提供支持');
87
+ });
88
+ it('图标:FeedbackIcon / CloseIcon / Avatar 渲染', ()=>{
89
+ expect(renderToStaticMarkup(/*#__PURE__*/ react.createElement(FeedbackIcon))).toContain('<svg');
90
+ expect(renderToStaticMarkup(/*#__PURE__*/ react.createElement(CloseIcon, {
91
+ size: 16
92
+ }))).toContain('<svg');
93
+ expect(renderToStaticMarkup(/*#__PURE__*/ react.createElement(Avatar, {
94
+ size: 18
95
+ }))).toContain(DOUBAO_LOGO_SRC);
96
+ });
97
+ });
98
+ describe('openDoubaoReport(举报跳转,后端就绪后启用)', ()=>{
99
+ it('按当前环境拼出飞书风控举报中心(tns) URL 并以新窗口打开', ()=>{
100
+ const openSpy = vi.spyOn(window, 'open').mockReturnValue(null);
101
+ window.appId = 'app_abc';
102
+ vi.stubEnv('FORCE_FRAMEWORK_ENVIRONMENT', 'boe');
103
+ openDoubaoReport();
104
+ expect(openSpy).toHaveBeenCalledTimes(1);
105
+ const [url, target, features] = openSpy.mock.calls[0];
106
+ expect(String(url)).toContain('tns.feishu-boe.cn/cust/lark_report/');
107
+ expect(String(url)).toContain(encodeURIComponent('miaoda_app_report'));
108
+ expect(String(url)).toContain('app_abc');
109
+ expect(target).toBe('_blank');
110
+ expect(features).toBe('noopener,noreferrer');
111
+ });
112
+ });
113
+ });
@@ -0,0 +1,2 @@
1
+ export declare const DOUBAO_LOGO_SRC = "https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/miaoda-ui/setting_voice.svg";
2
+ export declare const DOUBAO_PILL_MOBILE_PNG = "https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/miaoda-ui/Frame%202147223991%20(3).png";
@@ -0,0 +1,4 @@
1
+ const CDN = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/miaoda-ui';
2
+ const DOUBAO_LOGO_SRC = `${CDN}/setting_voice.svg`;
3
+ const DOUBAO_PILL_MOBILE_PNG = `${CDN}/Frame%202147223991%20(3).png`;
4
+ export { DOUBAO_LOGO_SRC, DOUBAO_PILL_MOBILE_PNG };
@@ -1,5 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import react, { Suspense, useEffect, useMemo, useState } from "react";
2
+ import { useEffect, useMemo, useState } from "react";
3
3
  import { ConfigProvider } from "antd";
4
4
  import { MiaodaInspector } from "@lark-apaas/miaoda-inspector";
5
5
  import zh_CN from "antd/locale/zh_CN";
@@ -7,7 +7,6 @@ import IframeBridge from "./IframeBridge.js";
7
7
  import { Toaster } from "./sonner.js";
8
8
  import { PageHoc } from "./PageHoc.js";
9
9
  import { reportTeaEvent } from "./utils/tea.js";
10
- import { SafetyErrorBoundary } from "./safety-error-boundary.js";
11
10
  import { useAppInfo } from "../../hooks/index.js";
12
11
  import { TrackKey } from "../../types/tea.js";
13
12
  import { slardar } from "@lark-apaas/internal-slardar";
@@ -15,8 +14,8 @@ import { getAppId } from "../../utils/getAppId.js";
15
14
  import { isNewPathEnabled } from "../../utils/apiPath.js";
16
15
  import QueryProvider from "../QueryProvider/index.js";
17
16
  import { AuthProvider } from "@lark-apaas/auth-sdk";
17
+ import Watermark from "./Watermark.js";
18
18
  import "../../runtime/index.js";
19
- const Safety = /*#__PURE__*/ react.lazy(()=>import("./safety.js"));
20
19
  const isMiaodaPreview = window.IS_MIAODA_PREVIEW;
21
20
  const readAllCssVarColors = ()=>{
22
21
  try {
@@ -197,12 +196,7 @@ const AppContainer_AppContainer = (props)=>{
197
196
  };
198
197
  return /*#__PURE__*/ jsxs(Fragment, {
199
198
  children: [
200
- /*#__PURE__*/ jsx(SafetyErrorBoundary, {
201
- children: /*#__PURE__*/ jsx(Suspense, {
202
- fallback: null,
203
- children: /*#__PURE__*/ jsx(Safety, {})
204
- })
205
- }),
199
+ /*#__PURE__*/ jsx(Watermark, {}),
206
200
  /*#__PURE__*/ jsx(QueryProvider, {
207
201
  children: /*#__PURE__*/ jsx(ConfigProvider, {
208
202
  locale: zh_CN,
@@ -2,12 +2,32 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover.js";
4
4
  import { getAppId } from "../../utils/getAppId.js";
5
+ import { getEnv } from "../../utils/getParentOrigin.js";
5
6
  import { getCsrfToken } from "../../utils/getCsrfToken.js";
6
7
  import { isNewPathEnabled } from "../../utils/apiPath.js";
7
8
  import { useIsMobile } from "../../hooks/index.js";
8
9
  import { X } from "lucide-react";
9
10
  import { Sheet, SheetContent, SheetTrigger } from "../ui/drawer.js";
10
11
  import { t } from "../../locales/index.js";
12
+ const ICON_FEEDBACK_URL = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/miaoda-ui/icon_feedback_outlined.png';
13
+ const REPORT_DOMAIN = {
14
+ BOE: 'tns.feishu-boe.cn',
15
+ PRE: 'tns.feishu-pre.cn',
16
+ ONLINE: 'tns.feishu.cn'
17
+ };
18
+ const openReport = ()=>{
19
+ const appId = getAppId();
20
+ if (!appId) return;
21
+ const params = JSON.stringify({
22
+ scene: 'miaoda_app_report',
23
+ entity_id: appId,
24
+ entity_type: 'miaoda_app',
25
+ extra: ''
26
+ });
27
+ const domain = REPORT_DOMAIN[getEnv()] ?? REPORT_DOMAIN.ONLINE;
28
+ const url = `https://${domain}/cust/lark_report/?type=common&params=${encodeURIComponent(params)}&lang=zh-CN`;
29
+ window.open(url, '_blank', 'noopener,noreferrer');
30
+ };
11
31
  const Component = ()=>{
12
32
  const HasClosedKey = `miaoda-creatByMiaoda-has-closed-${getAppId()}`;
13
33
  const [visible, setVisible] = useState(!window.localStorage?.getItem(HasClosedKey));
@@ -129,6 +149,21 @@ const Component = ()=>{
129
149
  children: t('safety.ai.disclaimer')
130
150
  })
131
151
  ]
152
+ }),
153
+ /*#__PURE__*/ jsxs("div", {
154
+ className: "self-stretch shrink-0 flex items-center gap-x-[6px] cursor-pointer",
155
+ "data-custom-element": "safety-report",
156
+ onClick: openReport,
157
+ children: [
158
+ /*#__PURE__*/ jsx("img", {
159
+ src: ICON_FEEDBACK_URL,
160
+ className: "shrink-0 w-[14px] h-[14px]"
161
+ }),
162
+ /*#__PURE__*/ jsx("p", {
163
+ className: "shrink-0 m-0! text-[#646A73] text-sm underline underline-offset-2",
164
+ children: t('safety.report')
165
+ })
166
+ ]
132
167
  })
133
168
  ]
134
169
  }),
@@ -248,6 +283,21 @@ const Component = ()=>{
248
283
  children: t('safety.ai.disclaimer')
249
284
  })
250
285
  ]
286
+ }),
287
+ /*#__PURE__*/ jsxs("div", {
288
+ className: "self-stretch shrink-0 flex items-center gap-x-[6px] cursor-pointer",
289
+ "data-custom-element": "safety-report",
290
+ onClick: openReport,
291
+ children: [
292
+ /*#__PURE__*/ jsx("img", {
293
+ src: ICON_FEEDBACK_URL,
294
+ className: "shrink-0 w-[12px] h-[12px]"
295
+ }),
296
+ /*#__PURE__*/ jsx("p", {
297
+ className: "shrink-0 m-0! text-[#a6a6a6] underline underline-offset-2",
298
+ children: t('safety.report')
299
+ })
300
+ ]
251
301
  })
252
302
  ]
253
303
  }),
@@ -1,10 +1,11 @@
1
1
  import { IUserProfile } from '../apis/udt-types';
2
2
  /**
3
3
  * useCurrentUserProfile 的返回类型。
4
- * client-toolkit-lite 完全一致:所有字段保证非 undefined(未加载时为空字符串),
5
- * 使用 `if (!userInfo.user_id)` 判断是否已加载完成。
4
+ * 初始状态为空对象 `{}`(所有字段均为 undefined),异步获取用户信息后字段才会被填充。
5
+ * 使用时必须通过可选链或空值合并进行安全访问,如 `userInfo?.user_id`。
6
+ * 判断是否已加载完成应使用 `if (!userInfo?.user_id)` 而非 `if (!userInfo)`(因为空对象是 truthy)。
6
7
  */
7
- export interface ICompatibilityUserProfile extends IUserProfile {
8
+ export type ICompatibilityUserProfile = Partial<IUserProfile & {
8
9
  /**
9
10
  * @deprecated please use `name`
10
11
  */
@@ -13,5 +14,14 @@ export interface ICompatibilityUserProfile extends IUserProfile {
13
14
  * @deprecated please use `avatar`
14
15
  */
15
16
  userAvatar: string;
16
- }
17
- export declare const useCurrentUserProfile: () => ICompatibilityUserProfile;
17
+ }>;
18
+ export declare const useCurrentUserProfile: () => Partial<IUserProfile & {
19
+ /**
20
+ * @deprecated please use `name`
21
+ */
22
+ userName: string;
23
+ /**
24
+ * @deprecated please use `avatar`
25
+ */
26
+ userAvatar: string;
27
+ }>;
@@ -25,14 +25,9 @@ function fetchLarkUserId() {
25
25
  function getCompatibilityUserProfile() {
26
26
  const userInfo = getCurrentUserProfile();
27
27
  return {
28
- user_id: userInfo.user_id ?? '',
29
- email: userInfo.email ?? '',
30
- name: userInfo.name ?? '',
31
- avatar: userInfo.avatar ?? '',
32
- status: userInfo.status,
33
- lark_user_id: userInfo.lark_user_id,
34
- userName: userInfo.name ?? '',
35
- userAvatar: userInfo.avatar ?? ''
28
+ ...userInfo,
29
+ userName: userInfo.name,
30
+ userAvatar: userInfo.avatar
36
31
  };
37
32
  }
38
33
  const useCurrentUserProfile = ()=>{
@@ -43,15 +38,14 @@ const useCurrentUserProfile = ()=>{
43
38
  const result = await authClient.session.getUserInfo();
44
39
  if (cancelled) return;
45
40
  const info = result?.data?.user_info;
46
- const userName = getNameFromArray(info?.name) ?? '';
47
- const avatar = info?.avatar?.image?.large ?? '';
41
+ const userName = getNameFromArray(info?.name);
48
42
  const newUserInfo = {
49
- user_id: info?.user_id?.toString() ?? '',
50
- email: info?.email ?? '',
43
+ user_id: info?.user_id?.toString(),
44
+ email: info?.email,
51
45
  name: userName,
52
- avatar,
53
- userName,
54
- userAvatar: avatar
46
+ avatar: info?.avatar?.image?.large,
47
+ userName: userName,
48
+ userAvatar: info?.avatar?.image?.large
55
49
  };
56
50
  const larkUserId = await fetchLarkUserId();
57
51
  if (larkUserId) newUserInfo.lark_user_id = larkUserId;
package/lib/index.d.ts CHANGED
@@ -1,46 +1,6 @@
1
- import { getAppId } from './utils/getAppId';
2
- import { logger } from './logger';
3
1
  export declare const capabilityClient: import("@lark-apaas/client-capability").CapabilityClient;
4
2
  export { showConfirm } from './components/ui/confirm';
5
3
  export type { ConfirmOptions } from './components/ui/confirm';
6
- export { default as AppContainer } from './components/AppContainer';
7
- export { default as QueryProvider } from './components/QueryProvider';
8
- export { default as PagePlaceholder } from './components/PagePlaceholder';
9
- export { default as Welcome } from './components/PagePlaceholder';
10
- export { default as ErrorRender } from './components/ErrorRender';
11
- export { ActiveLink } from './apis/components/ActiveLink';
12
- export { NavLink } from './apis/components/NavLink';
13
- export { UniversalLink } from './apis/components/UniversalLink';
14
- export { useAppInfo } from './hooks/useAppInfo';
15
- export { useCurrentUserProfile } from './hooks/useCurrentUserProfile';
16
- export { useIsMobile } from './hooks/useIsMobile';
17
- export { useLogout } from './hooks/useLogout';
18
- export { clsxWithTw, isPreview, normalizeBasePath, getWsPath } from './utils/utils';
19
- export { getCsrfToken } from './utils/getCsrfToken';
20
- export { scopedStorage } from './utils/scopedStorage';
21
- export { copyToClipboard } from './utils/copyToClipboard';
22
- export { isIpad, isMobile, isIOS } from './utils/deviceType';
23
- export { resolveAppUrl } from './utils/resolveAppUrl';
24
- export { getEnvPath } from './utils/getEnvPath';
25
- export { safeStringify } from './utils/safeStringify';
26
- export { getAxiosForBackend, axiosForBackend } from './utils/getAxiosForBackend';
27
- export { initAxiosConfig } from './utils/axiosConfig';
28
- export { getAppId };
29
- export { getAppInfo } from './integrations/getAppInfo';
30
- export { getCurrentUserProfile } from './integrations/getCurrentUserProfile';
31
- export { getDataloom } from './integrations/dataloom';
32
- export { logger };
33
- export type { LogLevel, LogWithMeta } from './logger/log-types';
34
- export { trace } from './trace';
35
- export { initObservable } from './runtime/observable';
36
- export type { AppInfoPayload } from './types/common';
37
- export type { IUserProfile, IJson, IFileAttachment } from './apis/udt-types';
38
- export type { TrackParams } from './types/tea';
39
- export { TrackKey } from './types/tea';
40
- export { reportTeaEvent } from './components/AppContainer/utils/tea';
41
- export * as avatarImages from './apis/constants/img-resources/avatar';
42
- export * as bannerImages from './apis/constants/img-resources/banner';
43
- export * as coverImages from './apis/constants/img-resources/cover';
44
4
  declare const _default: {
45
5
  version: string;
46
6
  };
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createClient } from "@lark-apaas/client-capability";
2
- import { clsxWithTw, getWsPath, isPreview, normalizeBasePath } from "./utils/utils.js";
2
+ import { normalizeBasePath } from "./utils/utils.js";
3
3
  import { getAppId } from "./utils/getAppId.js";
4
4
  import { isNewPathEnabled } from "./utils/apiPath.js";
5
5
  import { logger } from "./logger/index.js";
@@ -7,36 +7,6 @@ import { showToast } from "./components/ui/toast.js";
7
7
  import { t } from "./locales/index.js";
8
8
  import { version } from "../package.json";
9
9
  import { showConfirm } from "./components/ui/confirm.js";
10
- import AppContainer from "./components/AppContainer/index.js";
11
- import QueryProvider from "./components/QueryProvider/index.js";
12
- import PagePlaceholder from "./components/PagePlaceholder/index.js";
13
- import ErrorRender from "./components/ErrorRender/index.js";
14
- import { ActiveLink } from "./apis/components/ActiveLink.js";
15
- import { NavLink } from "./apis/components/NavLink.js";
16
- import { UniversalLink } from "./apis/components/UniversalLink.js";
17
- import { useAppInfo } from "./hooks/useAppInfo.js";
18
- import { useCurrentUserProfile } from "./hooks/useCurrentUserProfile.js";
19
- import { useIsMobile } from "./hooks/useIsMobile.js";
20
- import { useLogout } from "./hooks/useLogout.js";
21
- import { getCsrfToken } from "./utils/getCsrfToken.js";
22
- import { scopedStorage } from "./utils/scopedStorage.js";
23
- import { copyToClipboard } from "./utils/copyToClipboard.js";
24
- import { isIOS, isIpad, isMobile } from "./utils/deviceType.js";
25
- import { resolveAppUrl } from "./utils/resolveAppUrl.js";
26
- import { getEnvPath } from "./utils/getEnvPath.js";
27
- import { safeStringify } from "./utils/safeStringify.js";
28
- import { axiosForBackend, getAxiosForBackend } from "./utils/getAxiosForBackend.js";
29
- import { initAxiosConfig } from "./utils/axiosConfig.js";
30
- import { getAppInfo } from "./integrations/getAppInfo.js";
31
- import { getCurrentUserProfile } from "./integrations/getCurrentUserProfile.js";
32
- import { getDataloom } from "./integrations/dataloom.js";
33
- import { trace } from "./trace/index.js";
34
- import { initObservable } from "./runtime/observable.js";
35
- import { TrackKey } from "./types/tea.js";
36
- import { reportTeaEvent } from "./components/AppContainer/utils/tea.js";
37
- import * as __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_avatar_js_2c154035__ from "./apis/constants/img-resources/avatar.js";
38
- import * as __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_banner_js_72c990bf__ from "./apis/constants/img-resources/banner.js";
39
- import * as __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_cover_js_90a812c2__ from "./apis/constants/img-resources/cover.js";
40
10
  const _appId = getAppId();
41
11
  const _acquireUploadUrl = isNewPathEnabled() ? `/app/${_appId}/__runtime__/api/v1/studio/plugins/tmp_files/acquire_upload_url` : "/af/api/v1/studio/plugins/tmp_files/acquire_upload_url";
42
12
  const _acquireDownloadUrl = isNewPathEnabled() ? `/app/${_appId}/__runtime__/api/v1/studio/plugins/tmp_files/acquire_download_url` : "/af/api/v1/studio/plugins/tmp_files/acquire_download_url";
@@ -57,4 +27,4 @@ const capabilityClient = createClient({
57
27
  const src = {
58
28
  version: version
59
29
  };
60
- export { ActiveLink, AppContainer, ErrorRender, NavLink, PagePlaceholder, QueryProvider, TrackKey, UniversalLink, PagePlaceholder as Welcome, __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_avatar_js_2c154035__ as avatarImages, axiosForBackend, __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_banner_js_72c990bf__ as bannerImages, capabilityClient, clsxWithTw, copyToClipboard, __WEBPACK_EXTERNAL_MODULE__apis_constants_img_resources_cover_js_90a812c2__ as coverImages, src as default, getAppId, getAppInfo, getAxiosForBackend, getCsrfToken, getCurrentUserProfile, getDataloom, getEnvPath, getWsPath, initAxiosConfig, initObservable, isIOS, isIpad, isMobile, isPreview, logger, normalizeBasePath, reportTeaEvent, resolveAppUrl, safeStringify, scopedStorage, showConfirm, trace, useAppInfo, useCurrentUserProfile, useIsMobile, useLogout };
30
+ export { capabilityClient, src as default, showConfirm };
@@ -1,10 +1,11 @@
1
1
  import { IUserProfile } from '../apis/udt-types';
2
2
  /**
3
3
  * 获取当前用户信息。
4
- * client-toolkit-lite 一致返回 IUserProfile(非 Partial);
5
- * 调用方需自行处理 window._userInfo 未就绪时空对象的情况。
4
+ * 返回 Partial<IUserProfile>,因为初始值来自 window._userInfo,
5
+ * 该值在运行时始终为空对象 {},所有字段均为 undefined。
6
+ * 异步获取用户信息后才会被填充为完整的 IUserProfile。
6
7
  */
7
- export declare function getCurrentUserProfile(): IUserProfile;
8
+ export declare function getCurrentUserProfile(): Partial<IUserProfile>;
8
9
  /**
9
10
  * @deprecated 请使用 getCurrentUserProfile 代替
10
11
  */
@@ -23,6 +23,10 @@ const messages_messages = {
23
23
  zh: '了解更多',
24
24
  en: 'Learn more'
25
25
  },
26
+ 'safety.report': {
27
+ zh: '投诉与举报',
28
+ en: 'Report'
29
+ },
26
30
  'safety.cover.pc': {
27
31
  zh: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/logo/miaodacover.png',
28
32
  en: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/LMfspH/ljhwZthlaukjlkulzlp/logo/miaodacover-weben.png'
@@ -46,7 +46,18 @@ export interface DevServerMessage extends IframeMessage<{
46
46
  }> {
47
47
  type: 'DevServerMessage';
48
48
  }
49
- export type OutgoingMessage = PreviewReadyMessage | HmrMessage | ConsoleMessage | ChildLocationChangeMessage | CreatePageMessage | RenderErrorMessage | RenderErrorRepairMessage | PageScreenshotMessage | DevServerMessage | UpdateRoutesMessage;
49
+ /**
50
+ * 预览态下链接点击通知父页面处理。
51
+ * iframe 内直接跳转可能被浏览器安全策略拦截,
52
+ * 通过 postMessage 让父页面在新标签页或外壳中打开链接。
53
+ */
54
+ export interface OpenIframeLinkMessage extends IframeMessage<{
55
+ href: string;
56
+ external: boolean;
57
+ }> {
58
+ type: 'OpenIframeLink';
59
+ }
60
+ export type OutgoingMessage = PreviewReadyMessage | HmrMessage | ConsoleMessage | ChildLocationChangeMessage | CreatePageMessage | RenderErrorMessage | RenderErrorRepairMessage | PageScreenshotMessage | DevServerMessage | UpdateRoutesMessage | OpenIframeLinkMessage;
50
61
  export interface GetRoutesMessage extends IframeMessage<Record<string, never>> {
51
62
  type: 'GetRoutes';
52
63
  }
@@ -1,4 +1,5 @@
1
1
  import type { IncomingMessage, OutgoingMessage } from '../types/iframe-events';
2
+ export declare function getParentOriginFromParams(): string | undefined;
2
3
  export declare function resolveParentOrigin(): string;
3
4
  export declare function submitPostMessage<T extends OutgoingMessage>(message: T, targetOrigin?: string): void;
4
5
  export declare function isOutgoingMessage<T extends OutgoingMessage['type']>(msg: OutgoingMessage, type: T): msg is Extract<OutgoingMessage, {
@@ -50,4 +50,4 @@ function isOutgoingMessage(msg, type) {
50
50
  function isIncomingMessage(msg, type) {
51
51
  return msg.type === type;
52
52
  }
53
- export { isIncomingMessage, isOutgoingMessage, resolveParentOrigin, submitPostMessage };
53
+ export { getParentOriginFromParams, isIncomingMessage, isOutgoingMessage, resolveParentOrigin, submitPostMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/client-toolkit",
3
- "version": "1.2.52-alpha.0",
3
+ "version": "1.2.52-alpha.1",
4
4
  "types": "./lib/index.d.ts",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -26,7 +26,6 @@
26
26
  "types": "./lib/antd-table.d.ts"
27
27
  },
28
28
  "./lib/index.css": "./lib/index.css",
29
- "./styles.css": "./lib/index.css",
30
29
  "./dataloom": {
31
30
  "import": "./lib/apis/dataloom.js",
32
31
  "require": "./lib/apis/dataloom.js",