@blocklet/aigne-hub 0.2.7

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.
Files changed (128) hide show
  1. package/README.md +29 -0
  2. package/lib/cjs/api/ai-kit.js +60 -0
  3. package/lib/cjs/api/api.js +17 -0
  4. package/lib/cjs/api/app.js +57 -0
  5. package/lib/cjs/api/call/api.js +51 -0
  6. package/lib/cjs/api/call/app.js +74 -0
  7. package/lib/cjs/api/call/index.js +19 -0
  8. package/lib/cjs/api/call/proxy.js +64 -0
  9. package/lib/cjs/api/call/v1.js +166 -0
  10. package/lib/cjs/api/call/v2.js +101 -0
  11. package/lib/cjs/api/config.js +46 -0
  12. package/lib/cjs/api/constants.js +4 -0
  13. package/lib/cjs/api/error.js +42 -0
  14. package/lib/cjs/api/index.js +19 -0
  15. package/lib/cjs/api/types/audio.js +2 -0
  16. package/lib/cjs/api/types/chat.js +14 -0
  17. package/lib/cjs/api/types/embedding.js +2 -0
  18. package/lib/cjs/api/types/image.js +2 -0
  19. package/lib/cjs/api/types/index.js +19 -0
  20. package/lib/cjs/api/types/status.js +2 -0
  21. package/lib/cjs/api/utils/auth.js +90 -0
  22. package/lib/cjs/api/utils/event-stream.js +59 -0
  23. package/lib/cjs/components/conversation/conversation.js +71 -0
  24. package/lib/cjs/components/conversation/index.js +25 -0
  25. package/lib/cjs/components/conversation/message.js +120 -0
  26. package/lib/cjs/components/conversation/prompt.js +43 -0
  27. package/lib/cjs/components/conversation/use-conversation.js +100 -0
  28. package/lib/cjs/components/credit/alert.js +40 -0
  29. package/lib/cjs/components/credit/balance.js +95 -0
  30. package/lib/cjs/components/credit/button.js +69 -0
  31. package/lib/cjs/components/credit/index.js +12 -0
  32. package/lib/cjs/components/form-label.js +27 -0
  33. package/lib/cjs/components/image-preview.js +116 -0
  34. package/lib/cjs/components/index.js +45 -0
  35. package/lib/cjs/components/loading-image.js +37 -0
  36. package/lib/cjs/components/subscribe/alert.js +53 -0
  37. package/lib/cjs/components/subscribe/button.js +92 -0
  38. package/lib/cjs/components/subscribe/state.js +42 -0
  39. package/lib/cjs/components/switch-button.js +48 -0
  40. package/lib/cjs/components/table.js +203 -0
  41. package/lib/cjs/index.js +2 -0
  42. package/lib/cjs/libs/logger.js +8 -0
  43. package/lib/cjs/utils/withLocaleProvider.js +11 -0
  44. package/lib/esm/api/ai-kit.js +54 -0
  45. package/lib/esm/api/api.js +11 -0
  46. package/lib/esm/api/app.js +42 -0
  47. package/lib/esm/api/call/api.js +24 -0
  48. package/lib/esm/api/call/app.js +68 -0
  49. package/lib/esm/api/call/index.js +3 -0
  50. package/lib/esm/api/call/proxy.js +58 -0
  51. package/lib/esm/api/call/v1.js +155 -0
  52. package/lib/esm/api/call/v2.js +93 -0
  53. package/lib/esm/api/config.js +41 -0
  54. package/lib/esm/api/constants.js +1 -0
  55. package/lib/esm/api/error.js +37 -0
  56. package/lib/esm/api/index.js +3 -0
  57. package/lib/esm/api/types/audio.js +1 -0
  58. package/lib/esm/api/types/chat.js +9 -0
  59. package/lib/esm/api/types/embedding.js +1 -0
  60. package/lib/esm/api/types/image.js +1 -0
  61. package/lib/esm/api/types/index.js +3 -0
  62. package/lib/esm/api/types/status.js +1 -0
  63. package/lib/esm/api/utils/auth.js +79 -0
  64. package/lib/esm/api/utils/event-stream.js +50 -0
  65. package/lib/esm/components/conversation/conversation.js +65 -0
  66. package/lib/esm/components/conversation/index.js +4 -0
  67. package/lib/esm/components/conversation/message.js +114 -0
  68. package/lib/esm/components/conversation/prompt.js +40 -0
  69. package/lib/esm/components/conversation/use-conversation.js +97 -0
  70. package/lib/esm/components/credit/alert.js +35 -0
  71. package/lib/esm/components/credit/balance.js +90 -0
  72. package/lib/esm/components/credit/button.js +64 -0
  73. package/lib/esm/components/credit/index.js +3 -0
  74. package/lib/esm/components/form-label.js +24 -0
  75. package/lib/esm/components/image-preview.js +110 -0
  76. package/lib/esm/components/index.js +14 -0
  77. package/lib/esm/components/loading-image.js +35 -0
  78. package/lib/esm/components/subscribe/alert.js +48 -0
  79. package/lib/esm/components/subscribe/button.js +87 -0
  80. package/lib/esm/components/subscribe/state.js +39 -0
  81. package/lib/esm/components/switch-button.js +46 -0
  82. package/lib/esm/components/table.js +198 -0
  83. package/lib/esm/index.js +1 -0
  84. package/lib/esm/libs/logger.js +3 -0
  85. package/lib/esm/utils/withLocaleProvider.js +8 -0
  86. package/lib/types/api/ai-kit.d.ts +70 -0
  87. package/lib/types/api/api.d.ts +4 -0
  88. package/lib/types/api/app.d.ts +113 -0
  89. package/lib/types/api/call/api.d.ts +2 -0
  90. package/lib/types/api/call/app.d.ts +50 -0
  91. package/lib/types/api/call/index.d.ts +3 -0
  92. package/lib/types/api/call/proxy.d.ts +6 -0
  93. package/lib/types/api/call/v1.d.ts +51 -0
  94. package/lib/types/api/call/v2.d.ts +30 -0
  95. package/lib/types/api/config.d.ts +14 -0
  96. package/lib/types/api/constants.d.ts +1 -0
  97. package/lib/types/api/error.d.ts +18 -0
  98. package/lib/types/api/index.d.ts +3 -0
  99. package/lib/types/api/types/audio.d.ts +18 -0
  100. package/lib/types/api/types/chat.d.ts +97 -0
  101. package/lib/types/api/types/embedding.d.ts +9 -0
  102. package/lib/types/api/types/image.d.ts +23 -0
  103. package/lib/types/api/types/index.d.ts +3 -0
  104. package/lib/types/api/types/status.d.ts +3 -0
  105. package/lib/types/api/utils/auth.d.ts +33 -0
  106. package/lib/types/api/utils/event-stream.d.ts +7 -0
  107. package/lib/types/components/conversation/conversation.d.ts +30 -0
  108. package/lib/types/components/conversation/index.d.ts +4 -0
  109. package/lib/types/components/conversation/message.d.ts +10 -0
  110. package/lib/types/components/conversation/prompt.d.ts +10 -0
  111. package/lib/types/components/conversation/use-conversation.d.ts +44 -0
  112. package/lib/types/components/credit/alert.d.ts +10 -0
  113. package/lib/types/components/credit/balance.d.ts +7 -0
  114. package/lib/types/components/credit/button.d.ts +11 -0
  115. package/lib/types/components/credit/index.d.ts +3 -0
  116. package/lib/types/components/form-label.d.ts +7 -0
  117. package/lib/types/components/image-preview.d.ts +17 -0
  118. package/lib/types/components/index.d.ts +12 -0
  119. package/lib/types/components/loading-image.d.ts +6 -0
  120. package/lib/types/components/subscribe/alert.d.ts +5 -0
  121. package/lib/types/components/subscribe/button.d.ts +5 -0
  122. package/lib/types/components/subscribe/state.d.ts +14 -0
  123. package/lib/types/components/switch-button.d.ts +7 -0
  124. package/lib/types/components/table.d.ts +3 -0
  125. package/lib/types/index.d.ts +1 -0
  126. package/lib/types/libs/logger.d.ts +2 -0
  127. package/lib/types/utils/withLocaleProvider.d.ts +9 -0
  128. package/package.json +158 -0
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cx } from '@emotion/css';
3
+ import styled from '@emotion/styled';
4
+ import { CopyAll } from '@mui/icons-material';
5
+ import { Box, Button, Tooltip } from '@mui/material';
6
+ import { useMemo, useState } from 'react';
7
+ import ReactMarkdown from 'react-markdown';
8
+ export default function Message({ avatar = undefined, message = undefined, children = undefined, loading = false, actions = undefined, ...props }) {
9
+ const text = useMemo(() => (typeof message === 'string' ? message : message === null || message === void 0 ? void 0 : message.map((i) => `${i.role}: ${i.content}`).join('\n\n')), [message]);
10
+ return (_jsxs(Root, { ...props, display: "flex", children: [_jsx(Box, { className: "avatar", sx: {
11
+ mr: 1,
12
+ }, children: avatar }), _jsxs(Box, { className: cx('content'), children: [_jsx(Box, { component: ReactMarkdown, className: cx('message', loading && 'cursor'), children: text }), children, _jsxs(Box, { className: "actions", children: [actions, text && _jsx(CopyButton, { message: text }, "copy")] })] })] }));
13
+ }
14
+ function CopyButton({ message }) {
15
+ const [copied, setCopied] = useState(false);
16
+ return (_jsx(Tooltip, { title: copied === 'copied' ? 'Copied!' : 'Copy', placement: "top", open: Boolean(copied), children: _jsx(Button, { size: "small", className: cx('copy', copied && 'active'), onMouseEnter: () => setCopied(true), onMouseLeave: () => setCopied(false), onClick: () => {
17
+ navigator.clipboard.writeText(message);
18
+ setCopied('copied');
19
+ setTimeout(() => setCopied(false), 1500);
20
+ }, children: _jsx(CopyAll, { fontSize: "small" }) }) }));
21
+ }
22
+ const Root = styled(Box) `
23
+ > .avatar {
24
+ padding-top: 5px;
25
+
26
+ > .MuiAvatar-root {
27
+ width: 30px;
28
+ height: 30px;
29
+ }
30
+ }
31
+
32
+ > .content {
33
+ min-height: 40px;
34
+ flex: 1;
35
+ overflow: hidden;
36
+ word-break: break-word;
37
+ padding: 8px;
38
+ border-radius: 4px;
39
+ position: relative;
40
+
41
+ > .message {
42
+ > *:first-of-type {
43
+ margin-top: 0;
44
+ }
45
+ > *:last-child {
46
+ margin-bottom: 0;
47
+ }
48
+
49
+ pre {
50
+ line-height: 1.2;
51
+ background-color: #f6f8fa;
52
+ overflow: auto;
53
+ padding: 16px;
54
+ border-radius: 3px;
55
+ }
56
+
57
+ &.cursor {
58
+ > *:last-child {
59
+ &:after {
60
+ content: '';
61
+ display: inline-block;
62
+ vertical-align: middle;
63
+ height: 1em;
64
+ margin-top: -0.15em;
65
+ margin-left: 0.15em;
66
+ border-right: 0.15em solid orange;
67
+ animation: blink-caret 0.75s step-end infinite;
68
+
69
+ @keyframes blink-caret {
70
+ from,
71
+ to {
72
+ border-color: transparent;
73
+ }
74
+ 50% {
75
+ border-color: orange;
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ > .actions {
84
+ position: absolute;
85
+ right: 2px;
86
+ top: 2px;
87
+ border-radius: 4px;
88
+ opacity: 0;
89
+
90
+ &.active {
91
+ display: flex;
92
+ }
93
+
94
+ button {
95
+ min-width: 0;
96
+ padding: 0;
97
+ height: 24px;
98
+ width: 22px;
99
+ color: rgba(0, 0, 0, 0.4);
100
+ }
101
+ }
102
+ }
103
+
104
+ &:hover {
105
+ > .content {
106
+ background-color: rgba(0, 0, 0, 0.05);
107
+
108
+ > .actions {
109
+ opacity: 1;
110
+ background-color: rgba(240, 240, 240, 0.9);
111
+ }
112
+ }
113
+ }
114
+ `;
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Send } from '@mui/icons-material';
3
+ import { Box, IconButton, Input, InputAdornment } from '@mui/material';
4
+ import { useHistoryTravel } from 'ahooks';
5
+ import { useState } from 'react';
6
+ export default function Prompt({ startAdornment = undefined, endAdornment = undefined, onSubmit, slotProps = {}, sx = {}, ...props }) {
7
+ const [prompt, setPrompt] = useState('');
8
+ const { value: historyPrompt, setValue: setHistoryPrompt, forwardLength, back, go, forward } = useHistoryTravel('');
9
+ const submit = () => {
10
+ if (!prompt.trim()) {
11
+ return;
12
+ }
13
+ go(forwardLength);
14
+ // wait for history to set before submitting
15
+ setTimeout(() => {
16
+ setHistoryPrompt(prompt);
17
+ onSubmit(prompt);
18
+ setPrompt('');
19
+ }, 50);
20
+ };
21
+ return (_jsxs(Box, { ...props, sx: { display: 'flex', gap: 1, alignItems: 'center', ...sx }, component: "form", onSubmit: (e) => e.preventDefault(), children: [startAdornment, _jsx(Input, { fullWidth: true, disableUnderline: true, value: prompt, multiline: true, maxRows: 10, sx: { py: 0.8, px: 1, boxShadow: 2, borderRadius: 1 }, onChange: (e) => setPrompt(e.target.value), onKeyDown: (e) => {
22
+ if (e.keyCode === 229) {
23
+ return;
24
+ }
25
+ if (!e.shiftKey && e.key === 'Enter') {
26
+ e.preventDefault();
27
+ submit();
28
+ }
29
+ else if (e.key === 'ArrowUp') {
30
+ e.preventDefault();
31
+ back();
32
+ setPrompt(historyPrompt || '');
33
+ }
34
+ else if (e.key === 'ArrowDown') {
35
+ e.preventDefault();
36
+ forward();
37
+ setPrompt(historyPrompt || '');
38
+ }
39
+ }, endAdornment: _jsx(InputAdornment, { position: "end", children: _jsx(IconButton, { onClick: submit, size: "small", type: "submit", children: _jsx(Send, { fontSize: "small" }) }) }), ...slotProps }), endAdornment] }));
40
+ }
@@ -0,0 +1,97 @@
1
+ import { produce } from 'immer';
2
+ import { nanoid } from 'nanoid';
3
+ import { useCallback, useState } from 'react';
4
+ const nextId = () => nanoid(16);
5
+ export default function useConversation({ scrollToBottom, textCompletions, imageGenerations, }) {
6
+ const [messages, setMessages] = useState(() => [
7
+ { id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?' },
8
+ ]);
9
+ const add = useCallback(async (prompt, meta) => {
10
+ const id = nextId();
11
+ setMessages((v) => v.concat({ id, prompt, loading: true, meta }));
12
+ scrollToBottom === null || scrollToBottom === void 0 ? void 0 : scrollToBottom({ force: true });
13
+ try {
14
+ if (imageGenerations && typeof prompt === 'string') {
15
+ const m = prompt.match(/^\/image(\s+(?<size>256|512|1024))?(\s+(?<n>[1-9]|10))?\s+(?<prompt>[\s\S]+)/);
16
+ if (m === null || m === void 0 ? void 0 : m.groups) {
17
+ const { size = '256', n = '1', prompt, } = m.groups;
18
+ const response = await imageGenerations({
19
+ prompt,
20
+ n: parseInt(n, 10),
21
+ size: `${size}x${size}`,
22
+ }, { meta });
23
+ setMessages((v) => produce(v, (draft) => {
24
+ const item = draft.find((i) => i.id === id);
25
+ if (item)
26
+ item.response = response;
27
+ }));
28
+ return { id, data: response };
29
+ }
30
+ }
31
+ const result = await textCompletions(prompt, { meta });
32
+ const isText = (i) => i.type === 'text';
33
+ const isImages = (i) => i.type === 'images';
34
+ const reader = result.getReader();
35
+ const decoder = new TextDecoder();
36
+ let response = '';
37
+ for (;;) {
38
+ // eslint-disable-next-line no-await-in-loop
39
+ const { value, done } = await reader.read();
40
+ if (value) {
41
+ let delta = '';
42
+ if (typeof value === 'string') {
43
+ delta = value;
44
+ }
45
+ else if (isText(value)) {
46
+ response = value.text;
47
+ }
48
+ else if (isImages(value)) {
49
+ response = value.images;
50
+ }
51
+ else {
52
+ delta = decoder.decode(value);
53
+ }
54
+ if (typeof response === 'string' && delta) {
55
+ response += delta;
56
+ }
57
+ setMessages((v) => produce(v, (draft) => {
58
+ const item = draft.find((i) => i.id === id);
59
+ if (!item || item.loading === false) {
60
+ return;
61
+ }
62
+ item.response = response;
63
+ item.loading = !done;
64
+ }));
65
+ scrollToBottom === null || scrollToBottom === void 0 ? void 0 : scrollToBottom();
66
+ }
67
+ if (done) {
68
+ break;
69
+ }
70
+ }
71
+ return { id, text: response };
72
+ }
73
+ catch (error) {
74
+ setMessages((v) => produce(v, (draft) => {
75
+ const item = draft.find((i) => i.id === id);
76
+ if (item)
77
+ item.error = error;
78
+ }));
79
+ throw error;
80
+ }
81
+ finally {
82
+ setMessages((v) => produce(v, (draft) => {
83
+ const item = draft.find((i) => i.id === id);
84
+ if (item)
85
+ item.loading = false;
86
+ }));
87
+ }
88
+ }, [imageGenerations, scrollToBottom, textCompletions]);
89
+ const cancel = useCallback(({ id }) => {
90
+ setMessages((v) => produce(v, (draft) => {
91
+ const i = draft.find((i) => i.id === id);
92
+ if (i)
93
+ i.loading = false;
94
+ }));
95
+ }, []);
96
+ return { messages, add, cancel, setMessages };
97
+ }
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import { Alert, Stack } from '@mui/material';
4
+ import { CreditErrorType } from '../../api/error';
5
+ import withLocaleProvider from '../../utils/withLocaleProvider';
6
+ import CreditButton from './button';
7
+ function CreditErrorAlert({ error, ...props }) {
8
+ const { t } = useLocaleContext();
9
+ const isCreditError = (error === null || error === void 0 ? void 0 : error.type) === CreditErrorType.NOT_ENOUGH;
10
+ if (!isCreditError) {
11
+ return (_jsx(Alert, { severity: "error", ...props, children: (error === null || error === void 0 ? void 0 : error.message) || t('unknownError') }));
12
+ }
13
+ return (_jsxs(Alert, { severity: "warning", ...props, sx: {
14
+ px: 1,
15
+ py: 0,
16
+ '& .MuiAlert-message': {
17
+ width: '100%',
18
+ },
19
+ ...props.sx,
20
+ }, children: [t('creditNotEnoughTip'), _jsx(Stack, { direction: "row", sx: { justifyContent: 'flex-end' }, children: _jsx(CreditButton, { shouldOpenInNewTab: true, size: "small", variant: "outlined", color: "warning", children: t('buyCreditsNow') }) })] }));
21
+ }
22
+ export default withLocaleProvider(CreditErrorAlert, {
23
+ translations: {
24
+ en: {
25
+ unknownError: 'An unknown error occurred',
26
+ creditNotEnoughTip: 'Your credit balance is insufficient. Please buy more credits to continue using AI services.',
27
+ buyCreditsNow: 'Buy Credits Now',
28
+ },
29
+ zh: {
30
+ unknownError: '发生了未知错误',
31
+ creditNotEnoughTip: '您的额度不足。请购买更多额度以继续使用AI服务。',
32
+ buyCreditsNow: '立即购买额度',
33
+ },
34
+ },
35
+ });
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import { AccountBalanceWalletRounded } from '@mui/icons-material';
4
+ import { Box, Card, CardContent, CircularProgress, Stack, Typography } from '@mui/material';
5
+ import { blue } from '@mui/material/colors';
6
+ import { useCallback, useEffect, useState } from 'react';
7
+ import { getCreditBalance } from '../../api/app';
8
+ import withLocaleProvider from '../../utils/withLocaleProvider';
9
+ function CreditBalance({ balance = undefined, currency = undefined, useAIKitService = false }) {
10
+ var _a, _b;
11
+ const { t } = useLocaleContext();
12
+ const [creditData, setCreditData] = useState(null);
13
+ const [loading, setLoading] = useState(true);
14
+ const [error, setError] = useState(null);
15
+ const fetchBalance = useCallback(async () => {
16
+ try {
17
+ setLoading(true);
18
+ setError(null);
19
+ const result = await getCreditBalance({ useAIKitService });
20
+ // Safely access response data
21
+ setCreditData(result);
22
+ }
23
+ catch (err) {
24
+ console.error('Failed to fetch balance:', err);
25
+ setError(err instanceof Error ? err.message : t('failedToLoadBalance'));
26
+ }
27
+ finally {
28
+ setLoading(false);
29
+ }
30
+ }, [t, useAIKitService]);
31
+ useEffect(() => {
32
+ fetchBalance();
33
+ }, [fetchBalance]);
34
+ if (loading) {
35
+ return (_jsx(Card, { children: _jsx(CardContent, { children: _jsx(Box, { sx: {
36
+ display: 'flex',
37
+ justifyContent: 'center',
38
+ alignItems: 'center',
39
+ minHeight: '120px',
40
+ }, children: _jsx(CircularProgress, { size: 32 }) }) }) }));
41
+ }
42
+ if (error) {
43
+ return (_jsx(Card, { children: _jsx(CardContent, { children: _jsx(Typography, { color: "error", variant: "body2", sx: {
44
+ textAlign: 'center',
45
+ }, children: error }) }) }));
46
+ }
47
+ // Use props or API data
48
+ const displayBalance = (_a = balance !== null && balance !== void 0 ? balance : creditData === null || creditData === void 0 ? void 0 : creditData.balance) !== null && _a !== void 0 ? _a : '0';
49
+ const displayCurrency = (_b = currency !== null && currency !== void 0 ? currency : creditData === null || creditData === void 0 ? void 0 : creditData.currency) !== null && _b !== void 0 ? _b : 'USD';
50
+ return (_jsxs(Card, { sx: {
51
+ background: `linear-gradient(135deg, ${blue[500]} 0%, ${blue[700]} 100%)`,
52
+ color: 'white',
53
+ position: 'relative',
54
+ overflow: 'hidden',
55
+ }, children: [_jsx(CardContent, { sx: { position: 'relative', zIndex: 1 }, children: _jsxs(Stack, { spacing: 2, children: [_jsxs(Stack, { direction: "row", spacing: 1, sx: {
56
+ alignItems: 'center',
57
+ }, children: [_jsx(AccountBalanceWalletRounded, { sx: { fontSize: 28 } }), _jsx(Typography, { variant: "h6", sx: { fontWeight: 'bold' }, children: t('creditBalance') })] }), _jsxs(Box, { children: [_jsx(Typography, { variant: "h3", sx: { fontWeight: 'bold', lineHeight: 1 }, children: displayBalance }), _jsx(Typography, { variant: "body1", sx: { opacity: 0.9, mt: 0.5 }, children: displayCurrency })] }), _jsx(Typography, { variant: "body2", sx: { opacity: 0.8 }, children: t('availableForUse') })] }) }), _jsx(Box, { sx: {
58
+ position: 'absolute',
59
+ top: -20,
60
+ right: -20,
61
+ width: 80,
62
+ height: 80,
63
+ borderRadius: '50%',
64
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
65
+ zIndex: 0,
66
+ } }), _jsx(Box, { sx: {
67
+ position: 'absolute',
68
+ bottom: -30,
69
+ left: -30,
70
+ width: 100,
71
+ height: 100,
72
+ borderRadius: '50%',
73
+ backgroundColor: 'rgba(255, 255, 255, 0.05)',
74
+ zIndex: 0,
75
+ } })] }));
76
+ }
77
+ export default withLocaleProvider(CreditBalance, {
78
+ translations: {
79
+ en: {
80
+ creditBalance: 'Credit Balance',
81
+ availableForUse: 'Available for use',
82
+ failedToLoadBalance: 'Failed to load balance',
83
+ },
84
+ zh: {
85
+ creditBalance: '信用额度余额',
86
+ availableForUse: '可用余额',
87
+ failedToLoadBalance: '加载余额失败',
88
+ },
89
+ },
90
+ });
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import Toast from '@arcblock/ux/lib/Toast';
4
+ import { LoadingButton } from '@mui/lab';
5
+ import { Typography } from '@mui/material';
6
+ import { useCallback, useState } from 'react';
7
+ import { withQuery } from 'ufo';
8
+ import { getCreditPaymentLink } from '../../api/app';
9
+ import withLocaleProvider from '../../utils/withLocaleProvider';
10
+ function CreditButton({ shouldOpenInNewTab = true, size = 'small', variant = 'outlined', color = 'primary', children = null, useAIKitService = false, ...props }) {
11
+ var _a, _b;
12
+ const { t } = useLocaleContext();
13
+ const [submitting, setSubmitting] = useState(false);
14
+ const buyCredits = useCallback(async () => {
15
+ setSubmitting(true);
16
+ try {
17
+ const link = await getCreditPaymentLink({
18
+ useAIKitService,
19
+ });
20
+ if (link) {
21
+ const { href } = window.location;
22
+ const payLink = withQuery(link, {
23
+ redirect: href,
24
+ cancel_url: href,
25
+ });
26
+ if (shouldOpenInNewTab) {
27
+ const win = window.open(payLink, '_blank');
28
+ win === null || win === void 0 ? void 0 : win.focus();
29
+ }
30
+ else {
31
+ window.location.href = payLink;
32
+ }
33
+ }
34
+ else {
35
+ Toast.error(t('creditPaymentLinkNotAvailable'));
36
+ }
37
+ }
38
+ catch (error) {
39
+ Toast.error(error.message || t('failedToGetCreditPaymentLink'));
40
+ }
41
+ finally {
42
+ setSubmitting(false);
43
+ }
44
+ // eslint-disable-next-line react-hooks/exhaustive-deps
45
+ }, [shouldOpenInNewTab]);
46
+ if (!((_b = (_a = window.blocklet) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.creditBasedBillingEnabled)) {
47
+ return null;
48
+ }
49
+ return (_jsx(LoadingButton, { onClick: buyCredits, size: size, variant: variant, color: color, type: "button", loading: submitting, ...props, children: children || _jsx(Typography, { noWrap: true, children: t('buyCredits') }) }));
50
+ }
51
+ export default withLocaleProvider(CreditButton, {
52
+ translations: {
53
+ en: {
54
+ buyCredits: 'Buy Credits',
55
+ creditPaymentLinkNotAvailable: 'Credit payment link is not available',
56
+ failedToGetCreditPaymentLink: 'Failed to get credit payment link',
57
+ },
58
+ zh: {
59
+ buyCredits: '购买额度',
60
+ creditPaymentLinkNotAvailable: '额度付款链接不可用',
61
+ failedToGetCreditPaymentLink: '获取额度付款链接失败',
62
+ },
63
+ },
64
+ });
@@ -0,0 +1,3 @@
1
+ export { default as CreditButton } from './button';
2
+ export { default as CreditBalance } from './balance';
3
+ export { default as CreditErrorAlert } from './alert';
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { InfoOutlined } from '@mui/icons-material';
3
+ import { Box, FormLabel, Tooltip, Typography } from '@mui/material';
4
+ export default function CustomFormLabel({ children, required = false, tooltip = '', description = '', ...props }) {
5
+ return (_jsxs(Box, { sx: { mb: 1, width: '100%' }, children: [_jsxs(FormLabel, { ...props, sx: {
6
+ display: 'flex',
7
+ alignItems: 'center',
8
+ gap: 0.5,
9
+ fontSize: '0.875rem',
10
+ fontWeight: 500,
11
+ color: 'text.primary',
12
+ '&.MuiFormLabel-root': {
13
+ display: 'flex',
14
+ alignItems: 'center',
15
+ gap: 0.5,
16
+ fontWeight: 500,
17
+ color: 'text.primary',
18
+ },
19
+ ...(props.sx || {}),
20
+ }, children: [children, required && (_jsx(Typography, { component: "span", color: "error", children: "*" })), tooltip &&
21
+ (typeof tooltip === 'string' ? (_jsx(Tooltip, { title: tooltip, children: _jsx(InfoOutlined, { fontSize: "small", sx: { opacity: 0.7, fontSize: '1rem' } }) })) : (tooltip))] }), description && (_jsx(Typography, { variant: "caption", sx: {
22
+ color: 'text.secondary',
23
+ }, children: description }))] }));
24
+ }
@@ -0,0 +1,110 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import CloudDownloadOutlinedIcon from '@mui/icons-material/CloudDownloadOutlined';
3
+ import RotateRightOutlinedIcon from '@mui/icons-material/RotateRightOutlined';
4
+ import ZoomInOutlinedIcon from '@mui/icons-material/ZoomInOutlined';
5
+ import ZoomOutOutlinedIcon from '@mui/icons-material/ZoomOutOutlined';
6
+ import { Box, GlobalStyles, Grid, IconButton } from '@mui/material';
7
+ import { useReactive } from 'ahooks';
8
+ import { saveAs } from 'file-saver';
9
+ import { PhotoProvider, PhotoView } from 'react-photo-view';
10
+ import { withQuery } from 'ufo';
11
+ import LoadingImage from './loading-image';
12
+ const renderIconButton = (children, onClick, { key, ...extraProps } = {}) => {
13
+ return (_jsx(IconButton, { sx: {
14
+ transition: 'all 0.3s',
15
+ color: 'rgba(255,255,255,0.75)',
16
+ '&:hover': {
17
+ color: 'rgba(255,255,255,1)',
18
+ },
19
+ }, onClick: onClick, ...extraProps, children: children }, key));
20
+ };
21
+ function getExtFromBase64(base64) {
22
+ var _a;
23
+ // eslint-disable-next-line prefer-regex-literals
24
+ const re = new RegExp('data:image/([a-z]+);base64,.+');
25
+ const res = re.exec(base64);
26
+ if ((_a = res === null || res === void 0 ? void 0 : res.groups) === null || _a === void 0 ? void 0 : _a.ext) {
27
+ return res.groups.ext;
28
+ }
29
+ return '';
30
+ }
31
+ export default function ImagePreview({ dataSource = [], itemWidth = undefined, itemHeight = undefined, spacing = 1, transition = 'all 0.3s', borderRadius = 0, formatDownloadSrc = (value) => value, showDownloadButton = true, }) {
32
+ const state = useReactive({
33
+ downloadingIndexMap: {},
34
+ });
35
+ const getDownloadButton = (currentIndex, extraProps = {}) => renderIconButton(_jsx(CloudDownloadOutlinedIcon, { fontSize: "inherit" }), async () => {
36
+ const { src } = (dataSource === null || dataSource === void 0 ? void 0 : dataSource[currentIndex]) || {};
37
+ state.downloadingIndexMap = {
38
+ ...state.downloadingIndexMap,
39
+ [currentIndex]: true,
40
+ };
41
+ if (src) {
42
+ // download base64 image
43
+ if (src === null || src === void 0 ? void 0 : src.startsWith('data:image/')) {
44
+ const link = document.createElement('a');
45
+ link.href = src;
46
+ link.download = `image-${currentIndex}.${getExtFromBase64(src) || 'png'}`;
47
+ link.click();
48
+ }
49
+ else {
50
+ // use file saver to download image, will slow down the performance
51
+ await saveAs(formatDownloadSrc(src));
52
+ }
53
+ state.downloadingIndexMap = {
54
+ ...state.downloadingIndexMap,
55
+ [currentIndex]: false,
56
+ };
57
+ }
58
+ }, {
59
+ key: 'download',
60
+ disabled: !!state.downloadingIndexMap[currentIndex],
61
+ ...extraProps,
62
+ });
63
+ return (_jsxs(PhotoProvider, { toolbarRender: ({ index, scale, onScale, rotate, onRotate }) => {
64
+ return [
65
+ renderIconButton(_jsx(ZoomInOutlinedIcon, {}), () => onScale(scale + 0.25), {
66
+ key: 'scale-down',
67
+ }),
68
+ renderIconButton(_jsx(ZoomOutOutlinedIcon, {}), () => onScale(scale - 0.25), {
69
+ key: 'scale-up',
70
+ }),
71
+ renderIconButton(_jsx(RotateRightOutlinedIcon, {}), () => onRotate(rotate + 90), {
72
+ key: 'rotate',
73
+ }),
74
+ getDownloadButton(index),
75
+ ];
76
+ }, children: [_jsx(GlobalStyles, { styles: ".PhotoView-Portal{height:100%;left:0;overflow:hidden;position:fixed;top:0;touch-action:none;width:100%;z-index:2000}@-webkit-keyframes PhotoView__rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes PhotoView__rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@-webkit-keyframes PhotoView__delayIn{0%,50%{opacity:0}to{opacity:1}}@keyframes PhotoView__delayIn{0%,50%{opacity:0}to{opacity:1}}.PhotoView__Spinner{-webkit-animation:PhotoView__delayIn .4s linear both;animation:PhotoView__delayIn .4s linear both}.PhotoView__Spinner svg{-webkit-animation:PhotoView__rotate .6s linear infinite;animation:PhotoView__rotate .6s linear infinite}.PhotoView__Photo{cursor:-webkit-grab;cursor:grab;max-width:none}.PhotoView__Photo:active{cursor:-webkit-grabbing;cursor:grabbing}.PhotoView__icon{display:inline-block;left:0;position:absolute;top:0;transform:translate(-50%,-50%)}.PhotoView__PhotoBox,.PhotoView__PhotoWrap{bottom:0;direction:ltr;left:0;position:absolute;right:0;top:0;touch-action:none;width:100%}.PhotoView__PhotoWrap{overflow:hidden;z-index:10}.PhotoView__PhotoBox{transform-origin:left top}@-webkit-keyframes PhotoView__fade{0%{opacity:0}to{opacity:1}}@keyframes PhotoView__fade{0%{opacity:0}to{opacity:1}}.PhotoView-Slider__clean .PhotoView-Slider__ArrowLeft,.PhotoView-Slider__clean .PhotoView-Slider__ArrowRight,.PhotoView-Slider__clean .PhotoView-Slider__BannerWrap,.PhotoView-Slider__clean .PhotoView-Slider__Overlay,.PhotoView-Slider__willClose .PhotoView-Slider__BannerWrap:hover{opacity:0}.PhotoView-Slider__Backdrop{background:#000;height:100%;left:0;position:absolute;top:0;transition-property:background-color;width:100%;z-index:-1}.PhotoView-Slider__fadeIn{-webkit-animation:PhotoView__fade linear both;animation:PhotoView__fade linear both;opacity:0}.PhotoView-Slider__fadeOut{animation:PhotoView__fade linear reverse both;opacity:0}.PhotoView-Slider__BannerWrap{align-items:center;background-color:rgba(0,0,0,.5);color:#fff;display:flex;height:44px;justify-content:space-between;left:0;position:absolute;top:0;transition:opacity .2s ease-out;width:100%;z-index:20}.PhotoView-Slider__BannerWrap:hover{opacity:1}.PhotoView-Slider__Counter{font-size:14px;opacity:.75;padding:0 10px}.PhotoView-Slider__BannerRight{align-items:center;display:flex;height:100%}.PhotoView-Slider__toolbarIcon{fill:#fff;box-sizing:border-box;cursor:pointer;opacity:.75;padding:10px;transition:opacity .2s linear}.PhotoView-Slider__toolbarIcon:hover{opacity:1}.PhotoView-Slider__ArrowLeft,.PhotoView-Slider__ArrowRight{align-items:center;bottom:0;cursor:pointer;display:flex;height:100px;justify-content:center;margin:auto;opacity:.75;position:absolute;top:0;transition:opacity .2s linear;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:70px;z-index:20}.PhotoView-Slider__ArrowLeft:hover,.PhotoView-Slider__ArrowRight:hover{opacity:1}.PhotoView-Slider__ArrowLeft svg,.PhotoView-Slider__ArrowRight svg{fill:#fff;background:rgba(0,0,0,.3);box-sizing:content-box;height:24px;padding:10px;width:24px}.PhotoView-Slider__ArrowLeft{left:0}.PhotoView-Slider__ArrowRight{right:0}" }), _jsx(Grid, { spacing: spacing, container: true, className: "photo-wrapper", children: dataSource === null || dataSource === void 0 ? void 0 : dataSource.map((item, index) => {
77
+ const { width, height } = item;
78
+ return (_jsx(Grid
79
+ // eslint-disable-next-line react/no-array-index-key
80
+ , { className: "photo-item", sx: {
81
+ transition,
82
+ '&:hover': {
83
+ cursor: 'pointer',
84
+ '& .photo-toolbar': {
85
+ transition,
86
+ opacity: 1,
87
+ },
88
+ },
89
+ }, children: _jsxs(Box, { sx: { position: 'relative' }, children: [_jsx(PhotoView, { ...item, children: _jsx(LoadingImage, { ...item, src: withQuery(item.src, {
90
+ imageFilter: 'resize',
91
+ f: 'webp',
92
+ w: typeof itemWidth === 'number' ? Math.min(itemWidth * 2, 1200) : undefined,
93
+ }), style: {
94
+ transition,
95
+ borderRadius,
96
+ objectFit: 'cover',
97
+ width: width || itemWidth || '100%',
98
+ height: height || itemHeight || '100%',
99
+ } }) }), _jsx(Box, { className: "photo-toolbar", sx: {
100
+ position: 'absolute',
101
+ right: 0,
102
+ top: 0,
103
+ opacity: 0,
104
+ background: 'rgba(0,0,0,0.7)',
105
+ }, children: showDownloadButton &&
106
+ getDownloadButton(index, {
107
+ size: 'small',
108
+ }) })] }) }, index));
109
+ }) })] }));
110
+ }
@@ -0,0 +1,14 @@
1
+ /// <reference path="../env.d.ts" />
2
+ export { default as LoadingImage } from './loading-image';
3
+ export { default as ImagePreview } from './image-preview';
4
+ export { default as Conversation } from './conversation';
5
+ export * from './conversation';
6
+ export { default as SubscribeButton } from './subscribe/button';
7
+ export { default as SubscribeErrorAlert } from './subscribe/alert';
8
+ // Credit components
9
+ export { default as CreditButton } from './credit/button';
10
+ export { default as CreditBalance } from './credit/balance';
11
+ export { default as CreditErrorAlert } from './credit/alert';
12
+ export { default as Switch } from './switch-button';
13
+ export { default as Table } from './table';
14
+ export { default as FormLabel } from './form-label';
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable import/no-extraneous-dependencies */
3
+ import { Skeleton } from '@mui/material';
4
+ import { useReactive } from 'ahooks';
5
+ import { useRef } from 'react';
6
+ function LoadingImage({ ref = undefined, onLoad = () => { }, ...props }) {
7
+ const imageRef = useRef(null);
8
+ const state = useReactive({
9
+ loading: true,
10
+ });
11
+ return (_jsxs("div", { style: { position: 'relative' }, ref: ref || imageRef, children: [_jsx("div", { className: "lazy-image-wrapper", style: {
12
+ visibility: state.loading ? 'hidden' : 'visible',
13
+ background: '#f4f4f4',
14
+ width: '100%',
15
+ height: '100%',
16
+ display: 'flex',
17
+ alignItems: 'center',
18
+ justifyContent: 'center',
19
+ }, children: _jsx("img", { alt: "", ...props, onLoad: () => {
20
+ state.loading = false;
21
+ try {
22
+ onLoad();
23
+ }
24
+ catch (error) {
25
+ console.error('image onLoad error: ', error);
26
+ }
27
+ }, loading: "eager" // must be eager to make sure the image is loaded
28
+ }) }), state.loading && (_jsx(Skeleton, { className: "lazy-image-skeleton", animation: "wave", variant: "rectangular", style: {
29
+ width: '100%',
30
+ height: '100%',
31
+ position: 'absolute',
32
+ top: 0,
33
+ } }))] }));
34
+ }
35
+ export default LoadingImage;