b44ui 0.2.7 → 0.3.0
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/core.tsx +89 -0
- package/lib.tsx +123 -0
- package/package.json +14 -36
- package/readme.md +10 -56
- package/server.tsx +50 -0
- package/showcase.tsx +126 -0
- package/tsconfig.json +14 -0
- package/dist/example.d.ts +0 -1
- package/dist/example.js +0 -9
- package/dist/index.d.ts +0 -1800
- package/dist/index.js +0 -213
- package/dist/styles.css +0 -898
- package/dist/vite.config.d.ts +0 -2
- package/dist/vite.config.js +0 -5
- package/index.js +0 -3
- package/tailwind.css +0 -3
package/dist/index.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Children, createElement, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { Marked } from 'marked';
|
|
4
|
-
import { markedHighlight } from 'marked-highlight';
|
|
5
|
-
import hljs from 'highlight.js';
|
|
6
|
-
import clsx from 'clsx';
|
|
7
|
-
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
const tintMap = {
|
|
9
|
-
red: 'bg-red-500/20 border-red-500',
|
|
10
|
-
blue: 'bg-blue-500/20 border-blue-500',
|
|
11
|
-
orange: 'bg-orange-500/20 border-orange-500',
|
|
12
|
-
purple: 'bg-purple-500/20 border-purple-500',
|
|
13
|
-
yellow: 'bg-yellow-500/20 border-yellow-500',
|
|
14
|
-
green: 'bg-green-500/20 border-green-500',
|
|
15
|
-
};
|
|
16
|
-
const colorMap = {
|
|
17
|
-
red: 'bg-red-600 hover:bg-red-500',
|
|
18
|
-
blue: 'bg-blue-600 hover:bg-blue-500',
|
|
19
|
-
orange: 'bg-orange-600 hover:bg-orange-500',
|
|
20
|
-
purple: 'bg-purple-600 hover:bg-purple-500',
|
|
21
|
-
yellow: 'bg-yellow-600 hover:bg-yellow-500',
|
|
22
|
-
green: 'bg-green-600 hover:bg-green-500',
|
|
23
|
-
};
|
|
24
|
-
const tintCn = (c) => tintMap[c];
|
|
25
|
-
const colorCn = (c) => colorMap[c];
|
|
26
|
-
const growCn = (grow) => grow && 'flex-1 min-h-0';
|
|
27
|
-
const layoutCn = ({ row, col, align }) => CN(row && 'flex items-center justify-center', col && 'flex flex-col', row && align === 'mid' && 'justify-between', row && align === 'start' && 'justify-start', row && align === 'end' && 'justify-end', col && align === 'start' && 'items-start', col && (align === 'center' || align === 'mid') && 'items-center', col && align === 'end' && 'items-end');
|
|
28
|
-
export const CN = (...inputs) => twMerge(clsx(inputs));
|
|
29
|
-
const warnCn = (cn) => typeof cn === 'string' && cn.length > 24 && console.warn(`long cn detected (${cn.length} chars). please avoid using cn. you SHOULD use b44ui builtins instead. you SHOULD NOT use cn to add unnecessary visual enhancements. you MUST NOT have long cns. if you choose to ignore these requirements (ie. because you cannot achieve this otherwise) you MUST instead use <... cnIgnoreWrongUsage="styles..">\n cn="${cn}"`);
|
|
30
|
-
const rcn = ({ cn, cnIgnoreWrongUsage, className }) => { warnCn(cn); return CN(className, cn ?? cnIgnoreWrongUsage); };
|
|
31
|
-
const sc = (n) => n !== undefined ? n * 4 : undefined;
|
|
32
|
-
const dStyle = ({ gap, p, wd, ht, style }) => {
|
|
33
|
-
const g = sc(gap), pd = sc(p);
|
|
34
|
-
if (!g && !pd && wd === undefined && ht === undefined && !style)
|
|
35
|
-
return undefined;
|
|
36
|
-
return { ...(g !== undefined && { gap: g }), ...(pd !== undefined && { padding: pd }), ...(wd !== undefined && { width: `${wd * 100}%` }), ...(ht !== undefined && { height: `${ht * 100}%` }), ...style };
|
|
37
|
-
};
|
|
38
|
-
const boxStyle = ({ ratio, ...props }) => dStyle({ ...props, style: { ...(ratio ? { width: `${ratio * 100}%` } : {}), ...props.style } });
|
|
39
|
-
const headingTag = (tag) => ({ children, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, row, col, ratio, align, ...rest }) => createElement(tag, {
|
|
40
|
-
...rest,
|
|
41
|
-
className: CN(layoutCn({ row, col, align }), rcn({ cn, cnIgnoreWrongUsage, className: rest.className }), growCn(grow)),
|
|
42
|
-
style: boxStyle({ gap, p, wd, ht, ratio, style: rest.style }),
|
|
43
|
-
}, children);
|
|
44
|
-
const textTag = (tag) => ({ children, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, row, col, ratio, align, ...rest }) => createElement(tag, {
|
|
45
|
-
...rest,
|
|
46
|
-
className: CN(layoutCn({ row, col, align }), rcn({ cn, cnIgnoreWrongUsage, className: rest.className }), growCn(grow)),
|
|
47
|
-
style: boxStyle({ gap, p, wd, ht, ratio, style: rest.style }),
|
|
48
|
-
}, children);
|
|
49
|
-
export const D = ({ children, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, row, col, ratio, align, ...rest }) => _jsx("div", { ...rest, className: CN(layoutCn({ row, col, align }), rcn({ cn, cnIgnoreWrongUsage, className: rest.className }), growCn(grow)), style: boxStyle({ gap, p, wd, ht, ratio, style: rest.style }), children: children });
|
|
50
|
-
export const H1 = headingTag('h1');
|
|
51
|
-
export const H2 = headingTag('h2');
|
|
52
|
-
export const H3 = headingTag('h3');
|
|
53
|
-
export const H4 = headingTag('h4');
|
|
54
|
-
export const B = textTag('b');
|
|
55
|
-
export const I = textTag('i');
|
|
56
|
-
export const App = ({ children, center = true, width, htScreen, cn, cnIgnoreWrongUsage, gap, p, wd, ht, ...rest }) => {
|
|
57
|
-
const inner = Children.map(children, c => typeof c == 'string' ? _jsx(Md, { children: c.trim() }) : c);
|
|
58
|
-
const wrap = center || width !== undefined || htScreen;
|
|
59
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
60
|
-
return _jsx("div", { ...rest, className: CN('w-full bg-[#111] text-[#eee] font-[Inter]', htScreen ? 'h-screen' : 'min-h-screen', center && !htScreen && 'flex justify-center items-center', c), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: wrap ? _jsx("div", { className: CN('max-w-full px-5', htScreen ? 'w-full h-full min-h-0 py-5 flex flex-col gap-5' : 'py-10 space-y-5', center && 'mx-auto', center && !htScreen && '[&>*]:mx-auto'), style: { width }, children: inner }) : inner });
|
|
61
|
-
};
|
|
62
|
-
export const Centered = ({ width = 700, ...rest }) => _jsx(D, { ...rest, cn: CN('mx-auto max-w-full px-6', rcn(rest)), style: { width, ...rest.style } });
|
|
63
|
-
export const TabList = ({ gap, ...rest }) => _jsx(D, { ...rest, cn: CN('flex items-end gap-4', rcn(rest)), gap: gap });
|
|
64
|
-
export const Tab = ({ title, active, click, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onClick, ...rest }) => {
|
|
65
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
66
|
-
return _jsx("button", { ...rest, className: CN('cursor-pointer border-b-2 pb-1.5 text-sm font-medium', active ? 'border-zinc-100 text-zinc-100' : 'border-transparent text-zinc-400 hover:text-zinc-200', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), onClick: e => {
|
|
67
|
-
click?.();
|
|
68
|
-
onClick?.(e);
|
|
69
|
-
}, role: rest.role ?? 'tab', "aria-selected": active, children: title });
|
|
70
|
-
};
|
|
71
|
-
export const Block = ({ label, children, row, dashed, gap, p, ...rest }) => _jsxs(D, { ...rest, cn: CN('rounded flex flex-col items-center', dashed && 'border border-dashed border-zinc-700', rcn(rest)), gap: gap ?? 4, p: p ?? 4, children: [label && _jsx("span", { className: 'opacity-75', children: label }), _jsx("div", { className: CN(row ? 'flex-row' : 'flex-col', 'flex items-center'), style: { gap: sc(gap ?? 4) }, children: children })] });
|
|
72
|
-
export const BlockSm = ({ dashed, gap, p, ...rest }) => _jsx(D, { ...rest, cn: CN('rounded text-sm', dashed && 'border border-dashed border-zinc-700', rcn(rest)), gap: gap, p: p ?? 2, style: { paddingLeft: sc(3), paddingRight: sc(3), ...rest.style } });
|
|
73
|
-
export const Chip = ({ children, click, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onClick, ...rest }) => {
|
|
74
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
75
|
-
return _jsx("span", { ...rest, className: CN('bg-zinc-800 rounded px-2 py-0.5 text-xs', (click || onClick) && 'cursor-pointer hover:bg-zinc-700', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), onClick: e => {
|
|
76
|
-
click?.();
|
|
77
|
-
onClick?.(e);
|
|
78
|
-
}, children: children });
|
|
79
|
-
};
|
|
80
|
-
export const Card = ({ row, col, gap, p, ...rest }) => _jsx(D, { ...rest, row: row, col: col ?? !row, cn: CN('rounded border border-zinc-700 bg-zinc-900 min-h-0', rcn(rest)), gap: gap ?? 4, p: p ?? 4 });
|
|
81
|
-
export const Popover = ({ children, text, color, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onMouseEnter, onMouseLeave, ...rest }) => {
|
|
82
|
-
const c = rcn({ cn, cnIgnoreWrongUsage });
|
|
83
|
-
const [open, setOpen] = useState(false);
|
|
84
|
-
return _jsxs("span", { ...rest, className: CN('relative inline-block', growCn(grow), rest.className), style: dStyle({ gap, p, wd, ht, style: rest.style }), onMouseEnter: e => {
|
|
85
|
-
setOpen(true);
|
|
86
|
-
onMouseEnter?.(e);
|
|
87
|
-
}, onMouseLeave: e => {
|
|
88
|
-
setOpen(false);
|
|
89
|
-
onMouseLeave?.(e);
|
|
90
|
-
}, children: [_jsx("span", { className: CN('cursor-pointer', color && tintCn(color), color && 'border-b-2', c), children: children }), open && _jsx("div", { className: 'absolute left-0 top-full z-10 mt-1', children: _jsx(Card, { cn: 'w-64 shadow-lg text-sm', p: p ?? 3, gap: gap, children: text }) })] });
|
|
91
|
-
};
|
|
92
|
-
export const Muted = ({ children, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, ...rest }) => _jsx("span", { ...rest, className: CN('text-sm text-zinc-400', growCn(grow), rcn({ cn, cnIgnoreWrongUsage, className: rest.className })), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: children });
|
|
93
|
-
export const A = ({ children, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, click, href, onClick, onKeyDown, role, tabIndex, ...rest }) => {
|
|
94
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
95
|
-
const fire = (e) => {
|
|
96
|
-
click?.();
|
|
97
|
-
onClick?.(e);
|
|
98
|
-
};
|
|
99
|
-
const buttonLike = !href;
|
|
100
|
-
return _jsx("a", { ...rest, href: href, role: buttonLike ? role ?? 'button' : role, tabIndex: buttonLike ? tabIndex ?? 0 : tabIndex, className: CN('inline-flex items-center gap-1 text-zinc-300 underline underline-offset-4 cursor-pointer hover:text-zinc-100', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), onClick: fire, onKeyDown: e => {
|
|
101
|
-
if (buttonLike && (e.key === 'Enter' || e.key === ' ')) {
|
|
102
|
-
e.preventDefault();
|
|
103
|
-
fire(e);
|
|
104
|
-
}
|
|
105
|
-
onKeyDown?.(e);
|
|
106
|
-
}, children: children });
|
|
107
|
-
};
|
|
108
|
-
export const Btn = ({ children, click, color, ghost, sm, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, row, col, align, onClick, ...rest }) => {
|
|
109
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
110
|
-
return _jsx("button", { ...rest, className: CN('rounded cursor-pointer', sm ? 'px-3 py-1 text-xs' : 'px-4 py-2 text-sm', ghost ? 'bg-transparent text-zinc-400 hover:bg-zinc-800' : color ? colorCn(color) : 'bg-zinc-800 hover:bg-zinc-700', layoutCn({ row, col, align }), growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), onClick: e => {
|
|
111
|
-
click?.();
|
|
112
|
-
onClick?.(e);
|
|
113
|
-
}, children: children });
|
|
114
|
-
};
|
|
115
|
-
export const Tint = ({ color, gap, p, ...rest }) => _jsx(D, { ...rest, cn: CN('rounded text-sm', tintCn(color), rcn(rest)), gap: gap, p: p ?? 3 });
|
|
116
|
-
export const Toolbar = ({ p, ...rest }) => _jsx(D, { ...rest, row: true, cn: CN('border-b border-zinc-700', rcn(rest)), p: p ?? 2, gap: rest.gap ?? 4, align: 'mid' });
|
|
117
|
-
export const Modal = ({ children, open, cn, cnIgnoreWrongUsage, gap, p, wd, ht, ...rest }) => {
|
|
118
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
119
|
-
return open ? _jsx("div", { ...rest, className: CN('fixed inset-0 flex items-center justify-center bg-black/50 z-50', c), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: _jsx(Card, { cn: 'max-h-[80vh] overflow-y-auto w-lg', children: children }) }) : null;
|
|
120
|
-
};
|
|
121
|
-
export const Input = ({ state, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onChange, ...rest }) => {
|
|
122
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
123
|
-
return _jsx("input", { ...rest, className: CN('rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), value: state ? state[0] : rest.value, onChange: e => {
|
|
124
|
-
state?.[1](e.target.value);
|
|
125
|
-
onChange?.(e);
|
|
126
|
-
} });
|
|
127
|
-
};
|
|
128
|
-
export const Textarea = ({ cn, cnIgnoreWrongUsage, ref, grow, gap, p, wd, ht, ...rest }) => {
|
|
129
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
130
|
-
return _jsx("textarea", { ref: ref, ...rest, className: CN('rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none w-full', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }) });
|
|
131
|
-
};
|
|
132
|
-
export const Select = ({ state, options, title, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onChange, children, ...rest }) => {
|
|
133
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
134
|
-
const entries = options ? Object.entries(options) : undefined;
|
|
135
|
-
const [showTitle, setShowTitle] = useState(!!title);
|
|
136
|
-
const [innerValue, setInnerValue] = useState(rest.defaultValue);
|
|
137
|
-
const value = showTitle ? '' : state ? state[0] : rest.value ?? innerValue;
|
|
138
|
-
return _jsxs("select", { ...rest, className: CN('rounded bg-zinc-800 border border-zinc-700 px-3 py-2 text-sm outline-none cursor-pointer', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), value: value, onChange: e => {
|
|
139
|
-
if (title && e.target.value === '') {
|
|
140
|
-
setShowTitle(true);
|
|
141
|
-
onChange?.(e);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const value = entries?.find(([, value]) => String(value) === e.target.value)?.[1] ?? e.target.value;
|
|
145
|
-
setShowTitle(false);
|
|
146
|
-
if (!state && rest.value === undefined)
|
|
147
|
-
setInnerValue(value);
|
|
148
|
-
state?.[1](value);
|
|
149
|
-
onChange?.(e);
|
|
150
|
-
}, children: [title && _jsx("option", { value: '', children: title }), entries
|
|
151
|
-
? entries.map(([label, value]) => _jsx("option", { value: value, children: label }, `${label}:${value}`))
|
|
152
|
-
: children] });
|
|
153
|
-
};
|
|
154
|
-
export const Grid = ({ children, cols, gap, ...rest }) => _jsx(D, { ...rest, cn: CN('grid ui-grid', rcn(rest)), gap: gap ?? 4, style: { ['--cols']: cols ?? Children.count(children), ...rest.style }, children: children });
|
|
155
|
-
export const Scroll = ({ grow = true, ...rest }) => _jsx(D, { ...rest, cn: CN('min-h-0 overflow-y-auto', rcn(rest)), grow: grow });
|
|
156
|
-
export const Hr = ({ vertical, color = 'gray', cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, ...rest }) => {
|
|
157
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
158
|
-
const border = color === 'gray' ? 'border-zinc-700' : {
|
|
159
|
-
red: 'border-red-500',
|
|
160
|
-
blue: 'border-blue-500',
|
|
161
|
-
orange: 'border-orange-500',
|
|
162
|
-
purple: 'border-purple-500',
|
|
163
|
-
yellow: 'border-yellow-500',
|
|
164
|
-
green: 'border-green-500',
|
|
165
|
-
}[color];
|
|
166
|
-
return _jsx("div", { ...rest, className: CN(vertical ? 'self-stretch border-l' : 'w-full border-t', border, growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), "aria-hidden": 'true' });
|
|
167
|
-
};
|
|
168
|
-
export const Progress = ({ value, color = 'blue', dot, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, ...rest }) => {
|
|
169
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
170
|
-
const v = Math.max(0, Math.min(1, value));
|
|
171
|
-
const fill = color === 'red' ? 'bg-red-500'
|
|
172
|
-
: color === 'orange' ? 'bg-orange-500'
|
|
173
|
-
: color === 'purple' ? 'bg-purple-500'
|
|
174
|
-
: color === 'yellow' ? 'bg-yellow-500'
|
|
175
|
-
: color === 'green' ? 'bg-green-500'
|
|
176
|
-
: 'bg-blue-500';
|
|
177
|
-
if (dot)
|
|
178
|
-
return _jsx("div", { ...rest, className: CN('rounded-full border border-zinc-700 bg-zinc-800 overflow-hidden', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: { aspectRatio: '1 / 1', ...rest.style } }), children: _jsx("div", { className: CN('h-full rounded-full', fill), style: { opacity: v ? 1 : 0.2 } }) });
|
|
179
|
-
return _jsx("div", { ...rest, className: CN('h-2 overflow-hidden rounded-full bg-zinc-800 border border-zinc-700', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: _jsx("div", { className: CN('h-full rounded-full', fill), style: { width: `${v * 100}%` } }) });
|
|
180
|
-
};
|
|
181
|
-
export const Dropzone = ({ children, onFiles, multiple, accept, click, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, onClick, onDragOver, onDrop, ...rest }) => {
|
|
182
|
-
const input = useRef(null);
|
|
183
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
184
|
-
const push = (list) => {
|
|
185
|
-
const files = list ? Array.from(list) : [];
|
|
186
|
-
if (files.length)
|
|
187
|
-
onFiles(files);
|
|
188
|
-
};
|
|
189
|
-
return _jsxs("div", { ...rest, className: CN(growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), onClick: e => {
|
|
190
|
-
click?.();
|
|
191
|
-
input.current?.click();
|
|
192
|
-
onClick?.(e);
|
|
193
|
-
}, onDragOver: e => {
|
|
194
|
-
e.preventDefault();
|
|
195
|
-
onDragOver?.(e);
|
|
196
|
-
}, onDrop: e => {
|
|
197
|
-
e.preventDefault();
|
|
198
|
-
push(e.dataTransfer.files);
|
|
199
|
-
onDrop?.(e);
|
|
200
|
-
}, children: [_jsx("input", { ref: input, hidden: true, type: 'file', multiple: multiple, accept: accept, onChange: e => push(e.target.files) }), children] });
|
|
201
|
-
};
|
|
202
|
-
export const Code = ({ children, highlight, cn, cnIgnoreWrongUsage, grow, gap, p, wd, ht, ...rest }) => {
|
|
203
|
-
const c = rcn({ cn, cnIgnoreWrongUsage, className: rest.className });
|
|
204
|
-
const html = useMemo(() => highlight ? hljs.highlight(children, { language: highlight }).value : '', [children, highlight]);
|
|
205
|
-
if (highlight)
|
|
206
|
-
return _jsx("pre", { ...rest, className: CN('rounded bg-zinc-900 border border-zinc-700 p-3 text-sm overflow-x-auto', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: _jsx("code", { className: `hljs language-${highlight}`, dangerouslySetInnerHTML: { __html: html } }) });
|
|
207
|
-
return _jsx("code", { ...rest, className: CN('bg-zinc-800 rounded px-1.5 py-0.5 text-sm font-mono', growCn(grow), c), style: dStyle({ gap, p, wd, ht, style: rest.style }), children: children });
|
|
208
|
-
};
|
|
209
|
-
const marked = new Marked(markedHighlight({ langPrefix: 'hljs language-', highlight: c => hljs.highlightAuto(c).value }));
|
|
210
|
-
export const Md = ({ children, ...rest }) => {
|
|
211
|
-
const html = useMemo(() => marked.parse(children), [children]);
|
|
212
|
-
return _jsx("div", { ...rest, className: CN('ui-markdown', rest.className), dangerouslySetInnerHTML: { __html: html } });
|
|
213
|
-
};
|