@twentyfirstmedia/ui-core 0.5.0 → 0.6.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/dist/components/admin.d.ts.map +1 -1
- package/dist/components/admin.js +31 -21
- package/dist/components/admin.js.map +1 -1
- package/dist/components/agents.d.ts.map +1 -1
- package/dist/components/agents.js +21 -18
- package/dist/components/agents.js.map +1 -1
- package/dist/components/app-chrome.d.ts.map +1 -1
- package/dist/components/app-chrome.js +5 -5
- package/dist/components/app-chrome.js.map +1 -1
- package/dist/components/approvals.d.ts.map +1 -1
- package/dist/components/approvals.js +2 -2
- package/dist/components/approvals.js.map +1 -1
- package/dist/components/building-blocks.d.ts.map +1 -1
- package/dist/components/building-blocks.js +13 -10
- package/dist/components/building-blocks.js.map +1 -1
- package/dist/components/charts.d.ts +2 -2
- package/dist/components/charts.d.ts.map +1 -1
- package/dist/components/charts.js +14 -11
- package/dist/components/charts.js.map +1 -1
- package/dist/components/chat.d.ts +2 -2
- package/dist/components/chat.d.ts.map +1 -1
- package/dist/components/chat.js +22 -18
- package/dist/components/chat.js.map +1 -1
- package/dist/components/commerce.d.ts.map +1 -1
- package/dist/components/commerce.js +20 -16
- package/dist/components/commerce.js.map +1 -1
- package/dist/components/data-display.d.ts +0 -5
- package/dist/components/data-display.d.ts.map +1 -1
- package/dist/components/data-display.js +41 -22
- package/dist/components/data-display.js.map +1 -1
- package/dist/components/data-table.d.ts +2 -2
- package/dist/components/data-table.d.ts.map +1 -1
- package/dist/components/data-table.js +3 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/developer.d.ts.map +1 -1
- package/dist/components/developer.js +7 -6
- package/dist/components/developer.js.map +1 -1
- package/dist/components/feedback.d.ts.map +1 -1
- package/dist/components/feedback.js +5 -4
- package/dist/components/feedback.js.map +1 -1
- package/dist/components/forms.d.ts.map +1 -1
- package/dist/components/forms.js +63 -21
- package/dist/components/forms.js.map +1 -1
- package/dist/components/foundation.d.ts.map +1 -1
- package/dist/components/foundation.js +13 -9
- package/dist/components/foundation.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/inputs.d.ts.map +1 -1
- package/dist/components/inputs.js +33 -8
- package/dist/components/inputs.js.map +1 -1
- package/dist/components/mail.d.ts.map +1 -1
- package/dist/components/mail.js +5 -5
- package/dist/components/mail.js.map +1 -1
- package/dist/components/media.d.ts.map +1 -1
- package/dist/components/media.js +62 -11
- package/dist/components/media.js.map +1 -1
- package/dist/components/navigation.d.ts +3 -1
- package/dist/components/navigation.d.ts.map +1 -1
- package/dist/components/navigation.js +287 -20
- package/dist/components/navigation.js.map +1 -1
- package/dist/components/operations.d.ts.map +1 -1
- package/dist/components/operations.js +10 -10
- package/dist/components/operations.js.map +1 -1
- package/dist/components/overlays.d.ts.map +1 -1
- package/dist/components/overlays.js +2 -2
- package/dist/components/overlays.js.map +1 -1
- package/dist/components/previews.js +2 -2
- package/dist/components/previews.js.map +1 -1
- package/dist/components/primitives.js +2 -2
- package/dist/components/primitives.js.map +1 -1
- package/dist/components/qr-code.d.ts +8 -0
- package/dist/components/qr-code.d.ts.map +1 -0
- package/dist/components/qr-code.js +18 -0
- package/dist/components/qr-code.js.map +1 -0
- package/dist/components/real-estate.d.ts.map +1 -1
- package/dist/components/real-estate.js +5 -5
- package/dist/components/real-estate.js.map +1 -1
- package/dist/components/rich-text-editor.d.ts.map +1 -1
- package/dist/components/rich-text-editor.js +1 -1
- package/dist/components/rich-text-editor.js.map +1 -1
- package/dist/components/select-menu.js +1 -1
- package/dist/components/select-menu.js.map +1 -1
- package/dist/components/shell.d.ts +0 -4
- package/dist/components/shell.d.ts.map +1 -1
- package/dist/components/shell.js +100 -7
- package/dist/components/shell.js.map +1 -1
- package/dist/components/site.d.ts.map +1 -1
- package/dist/components/site.js +8 -6
- package/dist/components/site.js.map +1 -1
- package/dist/components/status.d.ts.map +1 -1
- package/dist/components/status.js +2 -2
- package/dist/components/status.js.map +1 -1
- package/dist/components/system.d.ts.map +1 -1
- package/dist/components/system.js +3 -2
- package/dist/components/system.js.map +1 -1
- package/dist/components/types.d.ts +257 -18
- package/dist/components/types.d.ts.map +1 -1
- package/dist/components/workspace.d.ts.map +1 -1
- package/dist/components/workspace.js +15 -12
- package/dist/components/workspace.js.map +1 -1
- package/dist/qr.d.ts +14 -0
- package/dist/qr.d.ts.map +1 -0
- package/dist/qr.js +298 -0
- package/dist/qr.js.map +1 -0
- package/dist/strings.d.ts +30 -4
- package/dist/strings.d.ts.map +1 -1
- package/dist/strings.js +15 -0
- package/dist/strings.js.map +1 -1
- package/dist/themes.css +2345 -176
- package/package.json +2 -1
- package/src/components/admin.tsx +66 -23
- package/src/components/agents.tsx +22 -20
- package/src/components/app-chrome.tsx +9 -5
- package/src/components/approvals.tsx +3 -1
- package/src/components/building-blocks.tsx +24 -13
- package/src/components/charts.tsx +17 -12
- package/src/components/chat.tsx +54 -31
- package/src/components/commerce.tsx +58 -24
- package/src/components/data-display.tsx +106 -38
- package/src/components/data-table.tsx +11 -7
- package/src/components/developer.tsx +15 -6
- package/src/components/feedback.tsx +5 -3
- package/src/components/forms.tsx +101 -23
- package/src/components/foundation.tsx +9 -5
- package/src/components/index.ts +10 -1
- package/src/components/inputs.tsx +44 -7
- package/src/components/mail.tsx +7 -3
- package/src/components/media.tsx +88 -16
- package/src/components/navigation.tsx +651 -71
- package/src/components/operations.tsx +17 -8
- package/src/components/overlays.tsx +7 -2
- package/src/components/previews.tsx +2 -2
- package/src/components/primitives.tsx +2 -2
- package/src/components/qr-code.tsx +30 -0
- package/src/components/real-estate.tsx +7 -4
- package/src/components/rich-text-editor.tsx +7 -1
- package/src/components/select-menu.tsx +1 -1
- package/src/components/shell.tsx +237 -11
- package/src/components/site.tsx +18 -4
- package/src/components/status.tsx +2 -0
- package/src/components/system.tsx +3 -2
- package/src/components/types.ts +261 -18
- package/src/components/workspace.tsx +37 -15
- package/src/qr.ts +300 -0
- package/src/strings.ts +56 -1
|
@@ -8,6 +8,7 @@ import { cx } from "../cx.js";
|
|
|
8
8
|
import { Icon } from "../Icon.js";
|
|
9
9
|
import { CountUp } from "./data-display.js";
|
|
10
10
|
import type {
|
|
11
|
+
BaseProps,
|
|
11
12
|
AreaChartProps,
|
|
12
13
|
BarChartProps,
|
|
13
14
|
DonutProps,
|
|
@@ -37,7 +38,7 @@ export function BarChart(p: BarChartProps) {
|
|
|
37
38
|
bw = Math.max(1, Math.min(p.barWidth || 28, gw * 0.62)),
|
|
38
39
|
ticks = [0, 0.5, 1];
|
|
39
40
|
return (
|
|
40
|
-
<div ref={mw[0]} className="tf-chart-wrap">
|
|
41
|
+
<div style={p.style} ref={mw[0]} className={cx("tf-chart-wrap", p.className)}>
|
|
41
42
|
<svg
|
|
42
43
|
className="tf-chart"
|
|
43
44
|
width={W}
|
|
@@ -117,7 +118,7 @@ export function LineChart(p: LineChartProps) {
|
|
|
117
118
|
return vals.map((v, i) => (i ? "L" : "M") + X(i).toFixed(1) + " " + Y(v).toFixed(1)).join(" ");
|
|
118
119
|
}
|
|
119
120
|
return (
|
|
120
|
-
<div ref={mw[0]} className="tf-chart-wrap">
|
|
121
|
+
<div style={p.style} ref={mw[0]} className={cx("tf-chart-wrap", p.className)}>
|
|
121
122
|
<svg
|
|
122
123
|
className="tf-chart"
|
|
123
124
|
width={W}
|
|
@@ -202,7 +203,8 @@ export function Sparkline(p: SparklineProps) {
|
|
|
202
203
|
.join(" ");
|
|
203
204
|
return (
|
|
204
205
|
<svg
|
|
205
|
-
|
|
206
|
+
style={p.style}
|
|
207
|
+
className={cx("tf-chart", p.className)}
|
|
206
208
|
viewBox={"0 0 " + W + " " + Hh}
|
|
207
209
|
width={W}
|
|
208
210
|
height={Hh}
|
|
@@ -233,9 +235,10 @@ export function Donut(p: DonutProps) {
|
|
|
233
235
|
const gap = data.length > 1 ? 6 : 0;
|
|
234
236
|
return (
|
|
235
237
|
<div
|
|
236
|
-
className="tf-donut"
|
|
238
|
+
className={cx("tf-donut", p.className)}
|
|
237
239
|
style={{
|
|
238
240
|
gap: 24,
|
|
241
|
+
...p.style,
|
|
239
242
|
}}
|
|
240
243
|
>
|
|
241
244
|
<div
|
|
@@ -323,7 +326,7 @@ export function Donut(p: DonutProps) {
|
|
|
323
326
|
}
|
|
324
327
|
|
|
325
328
|
/* ── More charts ── */
|
|
326
|
-
export interface ChartTipProps {
|
|
329
|
+
export interface ChartTipProps extends BaseProps {
|
|
327
330
|
x: number;
|
|
328
331
|
y: number;
|
|
329
332
|
title: React.ReactNode;
|
|
@@ -336,10 +339,11 @@ export interface ChartTipProps {
|
|
|
336
339
|
export function ChartTip(p: ChartTipProps) {
|
|
337
340
|
return (
|
|
338
341
|
<div
|
|
339
|
-
className="tf-chart-tip"
|
|
342
|
+
className={cx("tf-chart-tip", p.className)}
|
|
340
343
|
style={{
|
|
341
344
|
left: p.x,
|
|
342
345
|
top: p.y,
|
|
346
|
+
...p.style,
|
|
343
347
|
}}
|
|
344
348
|
>
|
|
345
349
|
<b>{p.title}</b>
|
|
@@ -355,7 +359,7 @@ export function ChartTip(p: ChartTipProps) {
|
|
|
355
359
|
}
|
|
356
360
|
export function Legend(p: LegendProps) {
|
|
357
361
|
return (
|
|
358
|
-
<div className="tf-legend">
|
|
362
|
+
<div style={p.style} className={cx("tf-legend", p.className)}>
|
|
359
363
|
{(p.items || []).map((s) => (
|
|
360
364
|
<span key={s.name || s.label}>
|
|
361
365
|
<i className={"tf-sw tf-sw-" + (s.tint || "ink")} />
|
|
@@ -381,7 +385,7 @@ export function StackedBarChart(p: StackedBarChartProps) {
|
|
|
381
385
|
gw = Math.max(1, (W - pad) / n),
|
|
382
386
|
bw = Math.max(1, Math.min(p.barWidth || 28, gw * 0.62));
|
|
383
387
|
return (
|
|
384
|
-
<div ref={mw[0]} className="tf-chart-wrap tf-chart-hover">
|
|
388
|
+
<div style={p.style} ref={mw[0]} className={cx("tf-chart-wrap tf-chart-hover", p.className)}>
|
|
385
389
|
<svg
|
|
386
390
|
className="tf-chart"
|
|
387
391
|
width={W}
|
|
@@ -573,7 +577,7 @@ export function AreaChart(p: AreaChartProps) {
|
|
|
573
577
|
return Hh - (v / max) * (Hh - 12);
|
|
574
578
|
}
|
|
575
579
|
return (
|
|
576
|
-
<div ref={mw[0]} className="tf-chart-wrap tf-chart-hover">
|
|
580
|
+
<div style={p.style} ref={mw[0]} className={cx("tf-chart-wrap tf-chart-hover", p.className)}>
|
|
577
581
|
<svg
|
|
578
582
|
className="tf-chart"
|
|
579
583
|
width={W}
|
|
@@ -691,7 +695,7 @@ export function Heatmap(p: HeatmapProps) {
|
|
|
691
695
|
return v <= 0 ? 0 : Math.min(4, Math.ceil((v / max) * 4));
|
|
692
696
|
}
|
|
693
697
|
return (
|
|
694
|
-
<div className="tf-heat-wrap">
|
|
698
|
+
<div style={p.style} className={cx("tf-heat-wrap", p.className)}>
|
|
695
699
|
<div
|
|
696
700
|
className="tf-heat"
|
|
697
701
|
style={{
|
|
@@ -763,7 +767,7 @@ export function Funnel(p: FunnelProps) {
|
|
|
763
767
|
f = p.format || ((v) => formatNumber(v)),
|
|
764
768
|
on = useMounted(120);
|
|
765
769
|
return (
|
|
766
|
-
<div className="tf-funnel">
|
|
770
|
+
<div style={p.style} className={cx("tf-funnel", p.className)}>
|
|
767
771
|
{steps.map((s, i) => {
|
|
768
772
|
const pct = (s.value / top) * 100,
|
|
769
773
|
conv = i ? (s.value / (steps[i - 1].value || 1)) * 100 : null;
|
|
@@ -819,9 +823,10 @@ export function Gauge(p: GaugeProps) {
|
|
|
819
823
|
: "ink");
|
|
820
824
|
return (
|
|
821
825
|
<div
|
|
822
|
-
className="tf-gauge"
|
|
826
|
+
className={cx("tf-gauge", p.className)}
|
|
823
827
|
style={{
|
|
824
828
|
width: size,
|
|
829
|
+
...p.style,
|
|
825
830
|
}}
|
|
826
831
|
>
|
|
827
832
|
<svg
|
package/src/components/chat.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { useControlled } from "../hooks.js";
|
|
|
8
8
|
import { Avatar, Badge, TintIcon } from "./foundation.js";
|
|
9
9
|
import { Popover, Tooltip } from "./overlays.js";
|
|
10
10
|
import type {
|
|
11
|
+
BaseProps,
|
|
11
12
|
AgentMarkProps,
|
|
12
13
|
AgentStatusProps,
|
|
13
14
|
ChatMessageProps,
|
|
@@ -123,7 +124,7 @@ export function RichText(p: RichTextProps) {
|
|
|
123
124
|
});
|
|
124
125
|
});
|
|
125
126
|
return (
|
|
126
|
-
<div className={cx("tf-rt", p.className)}>
|
|
127
|
+
<div style={p.style} className={cx("tf-rt", p.className)}>
|
|
127
128
|
{blocks}
|
|
128
129
|
{p.streaming && <span className="tf-caret" aria-hidden />}
|
|
129
130
|
</div>
|
|
@@ -167,7 +168,7 @@ export function CodeBlock(p: CodeBlockProps) {
|
|
|
167
168
|
}, 1400);
|
|
168
169
|
}
|
|
169
170
|
return (
|
|
170
|
-
<div className="tf-code">
|
|
171
|
+
<div style={p.style} className={cx("tf-code", p.className)}>
|
|
171
172
|
<div className="tf-code-head">
|
|
172
173
|
<span>{p.lang || "text"}</span>
|
|
173
174
|
<button type="button" className="tf-code-copy" onClick={copy} aria-label={t.copyCode}>
|
|
@@ -192,10 +193,15 @@ export function CodeBlock(p: CodeBlockProps) {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
/* ── Chat building blocks ── */
|
|
195
|
-
export function TypingDots(p: { label?: string }) {
|
|
196
|
+
export function TypingDots(p: BaseProps & { label?: string }) {
|
|
196
197
|
const t = useStrings(CHAT_STRINGS);
|
|
197
198
|
return (
|
|
198
|
-
<span
|
|
199
|
+
<span
|
|
200
|
+
style={p.style}
|
|
201
|
+
className={cx("tf-typing", p.className)}
|
|
202
|
+
role="status"
|
|
203
|
+
aria-label={p.label || t.working}
|
|
204
|
+
>
|
|
199
205
|
<i />
|
|
200
206
|
<i />
|
|
201
207
|
<i />
|
|
@@ -211,6 +217,7 @@ export function AgentMark(p: AgentMarkProps) {
|
|
|
211
217
|
style={{
|
|
212
218
|
width: s,
|
|
213
219
|
height: s,
|
|
220
|
+
...p.style,
|
|
214
221
|
}}
|
|
215
222
|
aria-hidden
|
|
216
223
|
>
|
|
@@ -242,7 +249,7 @@ export function ChatMessage(p: ChatMessageProps) {
|
|
|
242
249
|
}, 1400);
|
|
243
250
|
}
|
|
244
251
|
return (
|
|
245
|
-
<div className={cx("tf-msg", me ? "me" : "ai", p.className)}>
|
|
252
|
+
<div style={p.style} className={cx("tf-msg", me ? "me" : "ai", p.className)}>
|
|
246
253
|
{me ? (
|
|
247
254
|
<Avatar name={p.name || t.you} size={32} />
|
|
248
255
|
) : (
|
|
@@ -282,25 +289,35 @@ export function ChatMessage(p: ChatMessageProps) {
|
|
|
282
289
|
)}
|
|
283
290
|
{p.sources && p.sources.length > 0 && (
|
|
284
291
|
<div className="tf-msg-sources">
|
|
285
|
-
{p.sources.map((s, i) =>
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
s.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
292
|
+
{p.sources.map((s, i) => {
|
|
293
|
+
const chip = (
|
|
294
|
+
<a
|
|
295
|
+
key={i}
|
|
296
|
+
className="tf-source"
|
|
297
|
+
href={s.url || "#"}
|
|
298
|
+
title={s.detail ? undefined : s.title}
|
|
299
|
+
onClick={
|
|
300
|
+
s.onClick
|
|
301
|
+
? (e) => {
|
|
302
|
+
e.preventDefault();
|
|
303
|
+
s.onClick?.();
|
|
304
|
+
}
|
|
305
|
+
: undefined
|
|
306
|
+
}
|
|
307
|
+
>
|
|
308
|
+
<span className="tf-source-n">{i + 1}</span>
|
|
309
|
+
<Icon name={s.icon || "book"} size={12} />
|
|
310
|
+
<span className="tf-source-title">{s.title}</span>
|
|
311
|
+
</a>
|
|
312
|
+
);
|
|
313
|
+
return s.detail ? (
|
|
314
|
+
<Tooltip key={i} label={s.detail}>
|
|
315
|
+
{chip}
|
|
316
|
+
</Tooltip>
|
|
317
|
+
) : (
|
|
318
|
+
chip
|
|
319
|
+
);
|
|
320
|
+
})}
|
|
304
321
|
</div>
|
|
305
322
|
)}
|
|
306
323
|
{!me && !p.streaming && p.actions !== false && (
|
|
@@ -371,7 +388,7 @@ export function ToolCall(p: ToolCallProps) {
|
|
|
371
388
|
const open = React.useState(!!p.defaultOpen),
|
|
372
389
|
st = p.status || "done";
|
|
373
390
|
return (
|
|
374
|
-
<div className={cx("tf-tool", "is-" + st, open[0] && "open")}>
|
|
391
|
+
<div style={p.style} className={cx("tf-tool", "is-" + st, open[0] && "open", p.className)}>
|
|
375
392
|
<button
|
|
376
393
|
type="button"
|
|
377
394
|
className="tf-tool-head"
|
|
@@ -419,7 +436,10 @@ export function Reasoning(p: ReasoningProps) {
|
|
|
419
436
|
const t = useStrings(CHAT_STRINGS);
|
|
420
437
|
const open = React.useState(!!p.defaultOpen);
|
|
421
438
|
return (
|
|
422
|
-
<div
|
|
439
|
+
<div
|
|
440
|
+
style={p.style}
|
|
441
|
+
className={cx("tf-reason", open[0] && "open", p.streaming && "live", p.className)}
|
|
442
|
+
>
|
|
423
443
|
<button
|
|
424
444
|
type="button"
|
|
425
445
|
className="tf-reason-head"
|
|
@@ -451,7 +471,7 @@ export function Reasoning(p: ReasoningProps) {
|
|
|
451
471
|
|
|
452
472
|
export function PromptStarters(p: PromptStartersProps) {
|
|
453
473
|
return (
|
|
454
|
-
<div className="tf-starters">
|
|
474
|
+
<div style={p.style} className={cx("tf-starters", p.className)}>
|
|
455
475
|
{(p.items || []).map((s, i) => (
|
|
456
476
|
<button
|
|
457
477
|
key={i}
|
|
@@ -481,6 +501,8 @@ export function ModelPicker(p: ModelPickerProps) {
|
|
|
481
501
|
cur = models.find((m) => m.id === p.value) || models[0] || {};
|
|
482
502
|
return (
|
|
483
503
|
<Popover
|
|
504
|
+
style={p.style}
|
|
505
|
+
className={p.className}
|
|
484
506
|
side={p.side || "top"}
|
|
485
507
|
width={300}
|
|
486
508
|
flush
|
|
@@ -555,7 +577,8 @@ export function Composer(p: ComposerProps) {
|
|
|
555
577
|
}
|
|
556
578
|
return (
|
|
557
579
|
<div
|
|
558
|
-
|
|
580
|
+
style={p.style}
|
|
581
|
+
className={cx("tf-composer", p.busy && "busy", p.className)}
|
|
559
582
|
onDragOver={(e) => {
|
|
560
583
|
if (p.onAttach) e.preventDefault();
|
|
561
584
|
}}
|
|
@@ -723,7 +746,7 @@ export function AgentStatus(p: AgentStatusProps) {
|
|
|
723
746
|
const t = useStrings(CHAT_STRINGS);
|
|
724
747
|
const s = p.status || "Idle";
|
|
725
748
|
return (
|
|
726
|
-
<span className="tf-agentstatus">
|
|
749
|
+
<span style={p.style} className={cx("tf-agentstatus", p.className)}>
|
|
727
750
|
<Badge tone={AGENT_TONE[s] || "neutral"} live={s === "Running" || s === "Thinking"}>
|
|
728
751
|
{t.agentStatus[s] ?? s}
|
|
729
752
|
</Badge>
|
|
@@ -754,7 +777,7 @@ export function RunTrace(p: RunTraceProps) {
|
|
|
754
777
|
: `${formatNumber(ms)} ms`;
|
|
755
778
|
}
|
|
756
779
|
return (
|
|
757
|
-
<div className="tf-trace">
|
|
780
|
+
<div style={p.style} className={cx("tf-trace", p.className)}>
|
|
758
781
|
<div className="tf-trace-head">
|
|
759
782
|
<span>{t.step}</span>
|
|
760
783
|
<span>{t.timeline(fms(total))}</span>
|
|
@@ -807,7 +830,7 @@ export function UsageMeter(p: UsageMeterProps) {
|
|
|
807
830
|
const pct = Math.min(100, ((p.used || 0) / (p.limit || 1)) * 100),
|
|
808
831
|
tone = pct >= 90 ? "blush" : pct >= 70 ? "butter" : "mint";
|
|
809
832
|
return (
|
|
810
|
-
<div className="tf-usage">
|
|
833
|
+
<div style={p.style} className={cx("tf-usage", p.className)}>
|
|
811
834
|
<div className="tf-usage-top">
|
|
812
835
|
<span>{p.label || t.context}</span>
|
|
813
836
|
<b>{(p.format || String)(p.used) + " / " + (p.format || String)(p.limit)}</b>
|
|
@@ -39,14 +39,15 @@ export function ProductArt(p: ProductArtProps) {
|
|
|
39
39
|
return (
|
|
40
40
|
<span
|
|
41
41
|
className={cx("tf-art", "tf-bg-" + (p.tint || "sky"), p.className)}
|
|
42
|
-
style={
|
|
43
|
-
size
|
|
42
|
+
style={{
|
|
43
|
+
...(size
|
|
44
44
|
? {
|
|
45
45
|
width: size,
|
|
46
46
|
height: size,
|
|
47
47
|
}
|
|
48
|
-
: undefined
|
|
49
|
-
|
|
48
|
+
: undefined),
|
|
49
|
+
...p.style,
|
|
50
|
+
}}
|
|
50
51
|
role={p.label ? "img" : undefined}
|
|
51
52
|
aria-label={p.label}
|
|
52
53
|
aria-hidden={p.label ? undefined : true}
|
|
@@ -82,7 +83,7 @@ export function Price(p: PriceProps) {
|
|
|
82
83
|
const { formatPercent } = useFormat();
|
|
83
84
|
const sale = p.compareAt && p.compareAt > p.value;
|
|
84
85
|
return (
|
|
85
|
-
<span className={cx("tf-price", p.size && "tf-price-" + p.size)}>
|
|
86
|
+
<span style={p.style} className={cx("tf-price", p.size && "tf-price-" + p.size, p.className)}>
|
|
86
87
|
<b>{money(p.value, p.currency)}</b>
|
|
87
88
|
{sale && <s>{money(p.compareAt ?? 0, p.currency)}</s>}
|
|
88
89
|
{sale && p.showSave !== false && (
|
|
@@ -100,7 +101,12 @@ export function Rating(p: RatingProps) {
|
|
|
100
101
|
const v = p.value || 0,
|
|
101
102
|
shown = formatNumber(v, { minimumFractionDigits: 1, maximumFractionDigits: 1 });
|
|
102
103
|
return (
|
|
103
|
-
<span
|
|
104
|
+
<span
|
|
105
|
+
style={p.style}
|
|
106
|
+
className={cx("tf-rating", p.className)}
|
|
107
|
+
role="img"
|
|
108
|
+
aria-label={t.ratingLabel(shown, p.count)}
|
|
109
|
+
>
|
|
104
110
|
<span className="tf-stars" aria-hidden>
|
|
105
111
|
{[0, 1, 2, 3, 4].map((i) => {
|
|
106
112
|
const f = Math.max(0, Math.min(1, v - i));
|
|
@@ -141,7 +147,7 @@ export function StockBadge(p: StockBadgeProps) {
|
|
|
141
147
|
export function ProductCard(p: ProductCardProps) {
|
|
142
148
|
const t = useStrings(COMMERCE_STRINGS);
|
|
143
149
|
return (
|
|
144
|
-
<div className={cx("tf-product", p.className)} onClick={p.onClick}>
|
|
150
|
+
<div style={p.style} className={cx("tf-product", p.className)} onClick={p.onClick}>
|
|
145
151
|
<div className="tf-product-media">
|
|
146
152
|
<ProductArt kind={p.art} tint={p.tint} />
|
|
147
153
|
{p.badge && (
|
|
@@ -202,7 +208,7 @@ export function VariantPicker(p: VariantPickerProps) {
|
|
|
202
208
|
color = p.type === "color";
|
|
203
209
|
const cur = opts.find((o) => o.value === v[0]);
|
|
204
210
|
return (
|
|
205
|
-
<fieldset className="tf-variants">
|
|
211
|
+
<fieldset style={p.style} className={cx("tf-variants", p.className)}>
|
|
206
212
|
<legend className="tf-field-label">
|
|
207
213
|
{p.label}
|
|
208
214
|
{cur && <span className="tf-variants-cur">{cur.label || cur.value}</span>}
|
|
@@ -247,7 +253,7 @@ export function VariantPicker(p: VariantPickerProps) {
|
|
|
247
253
|
export function CartLine(p: CartLineProps) {
|
|
248
254
|
const t = useStrings(COMMERCE_STRINGS);
|
|
249
255
|
return (
|
|
250
|
-
<div className="tf-cartline">
|
|
256
|
+
<div style={p.style} className={cx("tf-cartline", p.className)}>
|
|
251
257
|
<ProductArt kind={p.art} tint={p.tint} size={64} />
|
|
252
258
|
<div className="tf-cartline-text">
|
|
253
259
|
<b>{p.name}</b>
|
|
@@ -302,7 +308,7 @@ export function OrderSummary(p: OrderSummaryProps) {
|
|
|
302
308
|
err = React.useState<string | null>(null),
|
|
303
309
|
toFree = (p.freeShippingFrom || 75) - (sub - disc);
|
|
304
310
|
return (
|
|
305
|
-
<div className="tf-summary">
|
|
311
|
+
<div style={p.style} className={cx("tf-summary", p.className)}>
|
|
306
312
|
{p.title !== false && <b className="tf-summary-title">{p.title || t.orderSummary}</b>}
|
|
307
313
|
{p.showLines && (
|
|
308
314
|
<div
|
|
@@ -425,7 +431,11 @@ export function CheckoutSteps(p: CheckoutStepsProps) {
|
|
|
425
431
|
const steps = p.steps || t.checkoutSteps,
|
|
426
432
|
cur = p.current || 0;
|
|
427
433
|
return (
|
|
428
|
-
<ol
|
|
434
|
+
<ol
|
|
435
|
+
style={p.style}
|
|
436
|
+
className={cx("tf-csteps", p.compact && "compact", p.className)}
|
|
437
|
+
aria-label={t.checkoutProgress}
|
|
438
|
+
>
|
|
429
439
|
{steps.map((s, i) => (
|
|
430
440
|
<li
|
|
431
441
|
key={s}
|
|
@@ -440,7 +450,7 @@ export function CheckoutSteps(p: CheckoutStepsProps) {
|
|
|
440
450
|
}}
|
|
441
451
|
>
|
|
442
452
|
<span className="tf-cstep-n">{i < cur ? <Icon name="check" size={12} /> : i + 1}</span>
|
|
443
|
-
{s}
|
|
453
|
+
<span className="tf-cstep-label">{s}</span>
|
|
444
454
|
</button>
|
|
445
455
|
</li>
|
|
446
456
|
))}
|
|
@@ -458,7 +468,7 @@ export function OrderTimeline(p: OrderTimelineProps) {
|
|
|
458
468
|
times = p.times || {},
|
|
459
469
|
cancelled = p.status === "Cancelled" || p.status === "Refunded";
|
|
460
470
|
return (
|
|
461
|
-
<div className={cx("tf-otl", cancelled && "cancelled")}>
|
|
471
|
+
<div style={p.style} className={cx("tf-otl", cancelled && "cancelled", p.className)}>
|
|
462
472
|
{ORDER_STEPS.map((s, i) => {
|
|
463
473
|
const done = !cancelled && i <= cur;
|
|
464
474
|
return (
|
|
@@ -490,34 +500,58 @@ export function OrderTimeline(p: OrderTimelineProps) {
|
|
|
490
500
|
export function PlanCard(p: PlanCardProps) {
|
|
491
501
|
const t = useStrings(COMMERCE_STRINGS);
|
|
492
502
|
const money = useMoney();
|
|
503
|
+
const Link = (p.linkAs || "a") as React.ElementType;
|
|
493
504
|
return (
|
|
494
|
-
<div
|
|
505
|
+
<div
|
|
506
|
+
style={p.style}
|
|
507
|
+
className={cx("tf-plan", p.featured && "featured", p.current && "current", p.className)}
|
|
508
|
+
>
|
|
495
509
|
{p.featured && <span className="tf-plan-flag">{p.flag || t.mostPopular}</span>}
|
|
496
510
|
<div className="tf-plan-head">
|
|
497
511
|
<b>{p.name}</b>
|
|
512
|
+
{p.current && (
|
|
513
|
+
<Badge tone="success" className="tf-plan-current">
|
|
514
|
+
{t.currentPlan}
|
|
515
|
+
</Badge>
|
|
516
|
+
)}
|
|
498
517
|
{p.text && <span>{p.text}</span>}
|
|
499
518
|
</div>
|
|
500
519
|
<div className="tf-plan-price">
|
|
520
|
+
{p.pricePrefix && <span className="tf-plan-prefix">{p.pricePrefix}</span>}
|
|
501
521
|
{p.price === 0 ? (
|
|
502
522
|
<b>{t.free}</b>
|
|
503
|
-
) : p.price
|
|
523
|
+
) : p.price === null || p.price === undefined ? (
|
|
504
524
|
<b>{t.letsTalk}</b>
|
|
505
|
-
) : (
|
|
525
|
+
) : typeof p.price === "number" ? (
|
|
506
526
|
<>
|
|
507
527
|
<b>{money(p.price)}</b>
|
|
508
528
|
<span>{p.per || t.perSeatMonth}</span>
|
|
509
529
|
</>
|
|
530
|
+
) : (
|
|
531
|
+
<>
|
|
532
|
+
<b>{p.price}</b>
|
|
533
|
+
{p.per && <span>{p.per}</span>}
|
|
534
|
+
</>
|
|
510
535
|
)}
|
|
511
536
|
{p.was && <s>{money(p.was)}</s>}
|
|
512
537
|
</div>
|
|
513
|
-
<
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
538
|
+
{p.priceNote && <p className="tf-plan-note">{p.priceNote}</p>}
|
|
539
|
+
{p.href && !p.current && !p.disabled ? (
|
|
540
|
+
<Button variant={p.featured ? "primary" : "secondary"} className="tf-plan-cta" asChild>
|
|
541
|
+
<Link href={p.href} onClick={p.onPick}>
|
|
542
|
+
{p.cta || t.choosePlan(p.name)}
|
|
543
|
+
</Link>
|
|
544
|
+
</Button>
|
|
545
|
+
) : (
|
|
546
|
+
<Button
|
|
547
|
+
variant={p.current ? "soft" : p.featured ? "primary" : "secondary"}
|
|
548
|
+
disabled={p.current || p.disabled}
|
|
549
|
+
onClick={p.onPick}
|
|
550
|
+
className="tf-plan-cta"
|
|
551
|
+
>
|
|
552
|
+
{p.current ? t.currentPlan : p.cta || t.choosePlan(p.name)}
|
|
553
|
+
</Button>
|
|
554
|
+
)}
|
|
521
555
|
<ul className="tf-plan-feats">
|
|
522
556
|
{(p.features || []).map((f, i) => (
|
|
523
557
|
<li key={i} className={f[0] === "-" ? "no" : undefined}>
|