@mangtre/ui 0.1.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/LICENSE +26 -0
- package/dist/MangThemeProvider-BqdGKBP2.d.ts +34 -0
- package/dist/Money-Dw3GnUvX.d.ts +27 -0
- package/dist/actions.d.ts +31 -0
- package/dist/actions.js +13 -0
- package/dist/ai.d.ts +58 -0
- package/dist/ai.js +13 -0
- package/dist/analytics.d.ts +40 -0
- package/dist/analytics.js +15 -0
- package/dist/app.d.ts +24 -0
- package/dist/app.js +9 -0
- package/dist/catalog.d.ts +76 -0
- package/dist/catalog.js +1210 -0
- package/dist/charts.d.ts +89 -0
- package/dist/charts.js +34 -0
- package/dist/chunk-3AL4SUFD.js +301 -0
- package/dist/chunk-4XNSYKQE.js +142 -0
- package/dist/chunk-5Z4VLQKH.js +43 -0
- package/dist/chunk-7P2EQZYD.js +59 -0
- package/dist/chunk-7WHNIEDV.js +120 -0
- package/dist/chunk-ASZKHSMG.js +82 -0
- package/dist/chunk-BCBN2EGH.js +216 -0
- package/dist/chunk-BLYAFV45.js +320 -0
- package/dist/chunk-DLKEXWPA.js +90 -0
- package/dist/chunk-DTASXPTB.js +70 -0
- package/dist/chunk-FZRXVRC7.js +63 -0
- package/dist/chunk-ID233AGM.js +108 -0
- package/dist/chunk-IVYXOKMO.js +74 -0
- package/dist/chunk-IX3DYETF.js +61 -0
- package/dist/chunk-JJB4PJC3.js +166 -0
- package/dist/chunk-K5Q3RCV6.js +119 -0
- package/dist/chunk-LNRUPJDF.js +161 -0
- package/dist/chunk-LZORNMBL.js +0 -0
- package/dist/chunk-OBPXCUVF.js +282 -0
- package/dist/chunk-OJX2EIMB.js +145 -0
- package/dist/chunk-PPOYMKV3.js +170 -0
- package/dist/chunk-PQGUWJG4.js +47 -0
- package/dist/chunk-RE7OWRA4.js +187 -0
- package/dist/chunk-SJF3CHAW.js +108 -0
- package/dist/chunk-UF6ANDJZ.js +112 -0
- package/dist/chunk-VGC5DMOM.js +107 -0
- package/dist/chunk-VP56Z4BS.js +0 -0
- package/dist/chunk-VRD66FIA.js +77 -0
- package/dist/chunk-X7T2DJLU.js +113 -0
- package/dist/chunk-XPV3OOLU.js +147 -0
- package/dist/chunk-YN5O6YL6.js +69 -0
- package/dist/chunk-Z4ANGBPC.js +94 -0
- package/dist/creator.d.ts +55 -0
- package/dist/creator.js +20 -0
- package/dist/data-room.d.ts +50 -0
- package/dist/data-room.js +17 -0
- package/dist/editor.d.ts +32 -0
- package/dist/editor.js +14 -0
- package/dist/feedback.d.ts +48 -0
- package/dist/feedback.js +16 -0
- package/dist/forms.d.ts +91 -0
- package/dist/forms.js +26 -0
- package/dist/handoff.d.ts +37 -0
- package/dist/handoff.js +13 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +338 -0
- package/dist/layout.d.ts +57 -0
- package/dist/layout.js +22 -0
- package/dist/learning.d.ts +46 -0
- package/dist/learning.js +15 -0
- package/dist/media.d.ts +48 -0
- package/dist/media.js +16 -0
- package/dist/monetization.d.ts +30 -0
- package/dist/monetization.js +14 -0
- package/dist/money.d.ts +45 -0
- package/dist/money.js +28 -0
- package/dist/navigation.d.ts +36 -0
- package/dist/navigation.js +14 -0
- package/dist/overlay.d.ts +72 -0
- package/dist/overlay.js +20 -0
- package/dist/platform.d.ts +94 -0
- package/dist/platform.js +42 -0
- package/dist/primitives.d.ts +83 -0
- package/dist/primitives.js +22 -0
- package/dist/privacy.d.ts +28 -0
- package/dist/privacy.js +15 -0
- package/dist/sandbox.d.ts +40 -0
- package/dist/sandbox.js +15 -0
- package/dist/settings.d.ts +29 -0
- package/dist/settings.js +13 -0
- package/dist/surface.d.ts +33 -0
- package/dist/surface.js +16 -0
- package/dist/theme.css +63 -0
- package/dist/theme.d.ts +64 -0
- package/dist/theme.js +27 -0
- package/dist/tokens.css +119 -0
- package/dist/tokens.d.ts +128 -0
- package/dist/tokens.js +8 -0
- package/package.json +151 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cx,
|
|
3
|
+
useAreaStyles,
|
|
4
|
+
useScope
|
|
5
|
+
} from "./chunk-3AL4SUFD.js";
|
|
6
|
+
import {
|
|
7
|
+
tokens
|
|
8
|
+
} from "./chunk-PPOYMKV3.js";
|
|
9
|
+
|
|
10
|
+
// src/charts/chart-utils.ts
|
|
11
|
+
function axisMax(values) {
|
|
12
|
+
return Math.max(1, ...values.map((v) => Number.isFinite(v) ? v : 0));
|
|
13
|
+
}
|
|
14
|
+
function linePoints(values, w, h, pad = 2) {
|
|
15
|
+
if (values.length === 0) return "";
|
|
16
|
+
const max = axisMax(values);
|
|
17
|
+
const span = values.length > 1 ? values.length - 1 : 1;
|
|
18
|
+
return values.map((v, i) => {
|
|
19
|
+
const x = pad + i / span * (w - pad * 2);
|
|
20
|
+
const y = h - pad - Math.max(0, v) / max * (h - pad * 2);
|
|
21
|
+
return `${round(x)},${round(y)}`;
|
|
22
|
+
}).join(" ");
|
|
23
|
+
}
|
|
24
|
+
function barFractions(values) {
|
|
25
|
+
const max = axisMax(values);
|
|
26
|
+
return values.map((v) => Math.max(0, Math.min(1, (Number.isFinite(v) ? v : 0) / max)));
|
|
27
|
+
}
|
|
28
|
+
function pieSegments(values) {
|
|
29
|
+
const total = values.reduce((s, v) => s + Math.max(0, v), 0);
|
|
30
|
+
if (total <= 0) return [];
|
|
31
|
+
let acc = 0;
|
|
32
|
+
return values.map((v) => {
|
|
33
|
+
const frac = Math.max(0, v) / total;
|
|
34
|
+
const seg = { start: acc, end: acc + frac, frac };
|
|
35
|
+
acc += frac;
|
|
36
|
+
return seg;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function round(n) {
|
|
40
|
+
return Math.round(n * 100) / 100;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/charts/Charts.tsx
|
|
44
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
45
|
+
var STYLE_ID = "mang-ui-charts";
|
|
46
|
+
var { color, semantic, font, fontSize, fontWeight, radius } = tokens;
|
|
47
|
+
var SERIES = [
|
|
48
|
+
color.mangGreen,
|
|
49
|
+
color.sun,
|
|
50
|
+
color.soil,
|
|
51
|
+
semantic.state.info,
|
|
52
|
+
color.shoot,
|
|
53
|
+
color.bamboo
|
|
54
|
+
];
|
|
55
|
+
var seriesColor = (i) => SERIES[i % SERIES.length];
|
|
56
|
+
var CSS = (
|
|
57
|
+
/* css */
|
|
58
|
+
`
|
|
59
|
+
.mang-stat { display: grid; gap: 0.15rem; }
|
|
60
|
+
.mang-stat-label { font-size: ${fontSize.xs}; color: var(--m-text-muted); font-weight: ${fontWeight.semibold}; text-transform: uppercase; letter-spacing: 0.08em; }
|
|
61
|
+
.mang-stat-value { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; font-size: ${fontSize["2xl"]}; color: var(--m-text-strong); font-variant-numeric: tabular-nums; line-height: 1.1; }
|
|
62
|
+
.mang-stat-delta { font-size: ${fontSize.xs}; font-weight: ${fontWeight.bold}; }
|
|
63
|
+
.mang-stat-delta[data-dir="up"] { color: var(--m-success); }
|
|
64
|
+
.mang-stat-delta[data-dir="down"] { color: var(--m-danger); }
|
|
65
|
+
.mang-statgroup { display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); gap: 1rem; }
|
|
66
|
+
.mang-chart { display: block; width: 100%; height: auto; overflow: visible; }
|
|
67
|
+
.mang-chart-bars { display: flex; align-items: flex-end; gap: 0.3rem; height: 100%; }
|
|
68
|
+
.mang-chart-bar { flex: 1; border-radius: ${radius.sm} ${radius.sm} 0 0; background: var(--m-accent); min-height: 2px; transition: height 240ms var(--m-ease, cubic-bezier(0.16,1,0.3,1)); }
|
|
69
|
+
.mang-barchart { height: 8rem; }
|
|
70
|
+
.mang-legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
|
|
71
|
+
.mang-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; font-size: ${fontSize.sm}; color: var(--m-text); }
|
|
72
|
+
.mang-legend-dot { width: 0.7rem; height: 0.7rem; border-radius: 3px; flex: none; }
|
|
73
|
+
.mang-heatmap { display: grid; gap: 3px; grid-auto-flow: column; grid-template-rows: repeat(7, 0.85rem); }
|
|
74
|
+
.mang-heatmap-cell { width: 0.85rem; height: 0.85rem; border-radius: 2px; background: var(--m-sunken); }
|
|
75
|
+
@media (prefers-reduced-motion: reduce) { .mang-chart-bar { transition: none; } }
|
|
76
|
+
`
|
|
77
|
+
);
|
|
78
|
+
function Stat({ label, value, delta, direction, theme, className }) {
|
|
79
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
80
|
+
const scope = useScope(theme);
|
|
81
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-stat", className), children: [
|
|
82
|
+
/* @__PURE__ */ jsx("span", { className: "mang-stat-label", children: label }),
|
|
83
|
+
/* @__PURE__ */ jsx("span", { className: "mang-stat-value", children: value }),
|
|
84
|
+
delta != null && /* @__PURE__ */ jsx("span", { className: "mang-stat-delta", "data-dir": direction, children: delta })
|
|
85
|
+
] });
|
|
86
|
+
}
|
|
87
|
+
function StatGroup({ children, theme, className }) {
|
|
88
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
89
|
+
const scope = useScope(theme);
|
|
90
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-statgroup", className), children });
|
|
91
|
+
}
|
|
92
|
+
function Sparkline({
|
|
93
|
+
values,
|
|
94
|
+
width = 120,
|
|
95
|
+
height = 32,
|
|
96
|
+
colorIndex = 0,
|
|
97
|
+
theme,
|
|
98
|
+
className
|
|
99
|
+
}) {
|
|
100
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
101
|
+
const scope = useScope(theme);
|
|
102
|
+
return /* @__PURE__ */ jsx(
|
|
103
|
+
"svg",
|
|
104
|
+
{
|
|
105
|
+
...scope,
|
|
106
|
+
className: cx(scope.className, "mang-chart", className),
|
|
107
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
108
|
+
role: "img",
|
|
109
|
+
"aria-label": "sparkline",
|
|
110
|
+
preserveAspectRatio: "none",
|
|
111
|
+
children: /* @__PURE__ */ jsx(
|
|
112
|
+
"polyline",
|
|
113
|
+
{
|
|
114
|
+
points: linePoints(values, width, height, 2),
|
|
115
|
+
fill: "none",
|
|
116
|
+
stroke: seriesColor(colorIndex),
|
|
117
|
+
strokeWidth: 2,
|
|
118
|
+
strokeLinejoin: "round",
|
|
119
|
+
strokeLinecap: "round"
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function BarChart({ values, labels, theme, className }) {
|
|
126
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
127
|
+
const scope = useScope(theme);
|
|
128
|
+
const fr = barFractions(values);
|
|
129
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-barchart", className), children: /* @__PURE__ */ jsx("div", { className: "mang-chart-bars", children: fr.map((f, i) => /* @__PURE__ */ jsx(
|
|
130
|
+
"div",
|
|
131
|
+
{
|
|
132
|
+
className: "mang-chart-bar",
|
|
133
|
+
style: { height: `${Math.max(2, f * 100)}%` },
|
|
134
|
+
title: labels?.[i]
|
|
135
|
+
},
|
|
136
|
+
i
|
|
137
|
+
)) }) });
|
|
138
|
+
}
|
|
139
|
+
function LineChart({
|
|
140
|
+
values,
|
|
141
|
+
width = 280,
|
|
142
|
+
height = 120,
|
|
143
|
+
colorIndex = 0,
|
|
144
|
+
area,
|
|
145
|
+
theme,
|
|
146
|
+
className
|
|
147
|
+
}) {
|
|
148
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
149
|
+
const scope = useScope(theme);
|
|
150
|
+
const pts = linePoints(values, width, height, 4);
|
|
151
|
+
const c = seriesColor(colorIndex);
|
|
152
|
+
return /* @__PURE__ */ jsxs(
|
|
153
|
+
"svg",
|
|
154
|
+
{
|
|
155
|
+
...scope,
|
|
156
|
+
className: cx(scope.className, "mang-chart", className),
|
|
157
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
158
|
+
role: "img",
|
|
159
|
+
"aria-label": "line chart",
|
|
160
|
+
children: [
|
|
161
|
+
area && pts && /* @__PURE__ */ jsx(
|
|
162
|
+
"polygon",
|
|
163
|
+
{
|
|
164
|
+
points: `${pts} ${width - 4},${height - 4} 4,${height - 4}`,
|
|
165
|
+
fill: c,
|
|
166
|
+
opacity: 0.16
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
"polyline",
|
|
171
|
+
{
|
|
172
|
+
points: pts,
|
|
173
|
+
fill: "none",
|
|
174
|
+
stroke: c,
|
|
175
|
+
strokeWidth: 2.5,
|
|
176
|
+
strokeLinejoin: "round",
|
|
177
|
+
strokeLinecap: "round"
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
function AreaChart(props) {
|
|
185
|
+
return /* @__PURE__ */ jsx(LineChart, { ...props, area: true });
|
|
186
|
+
}
|
|
187
|
+
function DonutChart({
|
|
188
|
+
values,
|
|
189
|
+
size = 120,
|
|
190
|
+
thickness = 16,
|
|
191
|
+
center,
|
|
192
|
+
theme,
|
|
193
|
+
className
|
|
194
|
+
}) {
|
|
195
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
196
|
+
const scope = useScope(theme);
|
|
197
|
+
const r = (size - thickness) / 2;
|
|
198
|
+
const c = 2 * Math.PI * r;
|
|
199
|
+
const segs = pieSegments(values);
|
|
200
|
+
return /* @__PURE__ */ jsxs(
|
|
201
|
+
"div",
|
|
202
|
+
{
|
|
203
|
+
...scope,
|
|
204
|
+
className: cx(scope.className, className),
|
|
205
|
+
style: { position: "relative", width: size, height: size },
|
|
206
|
+
children: [
|
|
207
|
+
/* @__PURE__ */ jsxs(
|
|
208
|
+
"svg",
|
|
209
|
+
{
|
|
210
|
+
viewBox: `0 0 ${size} ${size}`,
|
|
211
|
+
width: size,
|
|
212
|
+
height: size,
|
|
213
|
+
role: "img",
|
|
214
|
+
"aria-label": "donut chart",
|
|
215
|
+
children: [
|
|
216
|
+
/* @__PURE__ */ jsx(
|
|
217
|
+
"circle",
|
|
218
|
+
{
|
|
219
|
+
cx: size / 2,
|
|
220
|
+
cy: size / 2,
|
|
221
|
+
r,
|
|
222
|
+
fill: "none",
|
|
223
|
+
stroke: "var(--m-sunken)",
|
|
224
|
+
strokeWidth: thickness
|
|
225
|
+
}
|
|
226
|
+
),
|
|
227
|
+
segs.map((s, i) => /* @__PURE__ */ jsx(
|
|
228
|
+
"circle",
|
|
229
|
+
{
|
|
230
|
+
cx: size / 2,
|
|
231
|
+
cy: size / 2,
|
|
232
|
+
r,
|
|
233
|
+
fill: "none",
|
|
234
|
+
stroke: seriesColor(i),
|
|
235
|
+
strokeWidth: thickness,
|
|
236
|
+
strokeDasharray: `${s.frac * c} ${c}`,
|
|
237
|
+
strokeDashoffset: -s.start * c,
|
|
238
|
+
transform: `rotate(-90 ${size / 2} ${size / 2})`
|
|
239
|
+
},
|
|
240
|
+
i
|
|
241
|
+
))
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
),
|
|
245
|
+
center != null && /* @__PURE__ */ jsx(
|
|
246
|
+
"div",
|
|
247
|
+
{
|
|
248
|
+
style: {
|
|
249
|
+
position: "absolute",
|
|
250
|
+
inset: 0,
|
|
251
|
+
display: "grid",
|
|
252
|
+
placeItems: "center",
|
|
253
|
+
textAlign: "center"
|
|
254
|
+
},
|
|
255
|
+
children: center
|
|
256
|
+
}
|
|
257
|
+
)
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
function Heatmap({ values, theme, className }) {
|
|
263
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
264
|
+
const scope = useScope(theme);
|
|
265
|
+
return /* @__PURE__ */ jsx(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
...scope,
|
|
269
|
+
className: cx(scope.className, "mang-heatmap", className),
|
|
270
|
+
role: "img",
|
|
271
|
+
"aria-label": "activity heatmap",
|
|
272
|
+
children: values.map((v, i) => /* @__PURE__ */ jsx(
|
|
273
|
+
"div",
|
|
274
|
+
{
|
|
275
|
+
className: "mang-heatmap-cell",
|
|
276
|
+
style: v > 0 ? { background: color.mangGreen, opacity: 0.25 + Math.min(1, v) * 0.75 } : void 0
|
|
277
|
+
},
|
|
278
|
+
i
|
|
279
|
+
))
|
|
280
|
+
}
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
function Legend({ items, theme, className }) {
|
|
284
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
285
|
+
const scope = useScope(theme);
|
|
286
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-legend", className), children: items.map((it, i) => /* @__PURE__ */ jsxs(
|
|
287
|
+
"span",
|
|
288
|
+
{
|
|
289
|
+
className: "mang-legend-item",
|
|
290
|
+
children: [
|
|
291
|
+
/* @__PURE__ */ jsx(
|
|
292
|
+
"span",
|
|
293
|
+
{
|
|
294
|
+
className: "mang-legend-dot",
|
|
295
|
+
style: { background: seriesColor(it.colorIndex ?? i) }
|
|
296
|
+
}
|
|
297
|
+
),
|
|
298
|
+
it.label
|
|
299
|
+
]
|
|
300
|
+
},
|
|
301
|
+
i
|
|
302
|
+
)) });
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
export {
|
|
306
|
+
axisMax,
|
|
307
|
+
linePoints,
|
|
308
|
+
barFractions,
|
|
309
|
+
pieSegments,
|
|
310
|
+
SERIES,
|
|
311
|
+
Stat,
|
|
312
|
+
StatGroup,
|
|
313
|
+
Sparkline,
|
|
314
|
+
BarChart,
|
|
315
|
+
LineChart,
|
|
316
|
+
AreaChart,
|
|
317
|
+
DonutChart,
|
|
318
|
+
Heatmap,
|
|
319
|
+
Legend
|
|
320
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button
|
|
3
|
+
} from "./chunk-YN5O6YL6.js";
|
|
4
|
+
import {
|
|
5
|
+
cx,
|
|
6
|
+
useAreaStyles,
|
|
7
|
+
useScope
|
|
8
|
+
} from "./chunk-3AL4SUFD.js";
|
|
9
|
+
import {
|
|
10
|
+
tokens
|
|
11
|
+
} from "./chunk-PPOYMKV3.js";
|
|
12
|
+
|
|
13
|
+
// src/handoff/Handoff.tsx
|
|
14
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
var STYLE_ID = "mang-ui-handoff";
|
|
16
|
+
var { fontSize, fontWeight, radius, font } = tokens;
|
|
17
|
+
var CSS = (
|
|
18
|
+
/* css */
|
|
19
|
+
`
|
|
20
|
+
.mang-handoff { display: grid; gap: 0.7rem; justify-items: center; text-align: center; padding: 1rem 1.1rem; border: 1px solid var(--m-line); border-radius: ${radius.lg}; background: var(--m-surface); color: var(--m-text); }
|
|
21
|
+
.mang-handoff-title { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; color: var(--m-text-strong); font-size: ${fontSize.base}; }
|
|
22
|
+
.mang-handoff-qr { padding: 0.6rem; background: #fff; border-radius: ${radius.md}; line-height: 0; }
|
|
23
|
+
.mang-handoff-note { font-size: ${fontSize.sm}; color: var(--m-text-muted); max-width: 22rem; }
|
|
24
|
+
.mang-handoff-status { display: inline-flex; align-items: center; gap: 0.4rem; font-size: ${fontSize.sm}; font-weight: ${fontWeight.semibold}; }
|
|
25
|
+
.mang-handoff-status[data-on="true"] { color: var(--m-success); }
|
|
26
|
+
.mang-handoff-status[data-on="false"] { color: var(--m-text-muted); }
|
|
27
|
+
.mang-handoff-banner { display: flex; align-items: center; gap: 0.6rem; padding: 0.7rem 0.9rem; border-radius: ${radius.md}; border: 1px solid var(--m-line); border-left: 4px solid var(--m-accent); background: var(--m-accent-soft); color: var(--m-text); }
|
|
28
|
+
.mang-handoff-banner-msg { flex: 1; font-size: ${fontSize.sm}; }
|
|
29
|
+
.mang-handoff-banner-msg b { color: var(--m-text-strong); }
|
|
30
|
+
`
|
|
31
|
+
);
|
|
32
|
+
function HandoffConnectionStatus({
|
|
33
|
+
connected,
|
|
34
|
+
device,
|
|
35
|
+
locale = "vi"
|
|
36
|
+
}) {
|
|
37
|
+
const label = connected ? locale === "vi" ? `\u{1F4F1} ${device ?? "Thi\u1EBFt b\u1ECB"} \u0111\xE3 k\u1EBFt n\u1ED1i` : `\u{1F4F1} ${device ?? "Device"} connected` : locale === "vi" ? "Ch\u01B0a k\u1EBFt n\u1ED1i" : "Not connected";
|
|
38
|
+
return /* @__PURE__ */ jsx("span", { className: "mang-handoff-status", "data-on": connected ? "true" : "false", children: label });
|
|
39
|
+
}
|
|
40
|
+
function HandoffPairingPanel({
|
|
41
|
+
qr,
|
|
42
|
+
connected = false,
|
|
43
|
+
device,
|
|
44
|
+
title,
|
|
45
|
+
note,
|
|
46
|
+
locale = "vi",
|
|
47
|
+
theme,
|
|
48
|
+
className
|
|
49
|
+
}) {
|
|
50
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
51
|
+
const scope = useScope(theme);
|
|
52
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-handoff", className), children: [
|
|
53
|
+
/* @__PURE__ */ jsx("span", { className: "mang-handoff-title", children: title ?? (locale === "vi" ? "Qu\xE9t \u0111\u1EC3 g\u1EEDi t\u1EEB \u0111i\u1EC7n tho\u1EA1i" : "Scan to send from your phone") }),
|
|
54
|
+
qr != null && /* @__PURE__ */ jsx("div", { className: "mang-handoff-qr", children: qr }),
|
|
55
|
+
/* @__PURE__ */ jsx(HandoffConnectionStatus, { connected, device, locale }),
|
|
56
|
+
note != null && /* @__PURE__ */ jsx("span", { className: "mang-handoff-note", children: note })
|
|
57
|
+
] });
|
|
58
|
+
}
|
|
59
|
+
function HandoffPayloadBanner({
|
|
60
|
+
kind,
|
|
61
|
+
device,
|
|
62
|
+
onPaste,
|
|
63
|
+
onDismiss,
|
|
64
|
+
locale = "vi",
|
|
65
|
+
theme,
|
|
66
|
+
className
|
|
67
|
+
}) {
|
|
68
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
69
|
+
const scope = useScope(theme);
|
|
70
|
+
const live = { role: "status" };
|
|
71
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, ...live, className: cx(scope.className, "mang-handoff-banner", className), children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: "mang-handoff-banner-msg", children: locale === "vi" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
73
|
+
"Nh\u1EADn ",
|
|
74
|
+
/* @__PURE__ */ jsx("b", { children: kind }),
|
|
75
|
+
device ? ` t\u1EEB ${device}` : ""
|
|
76
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
"Got ",
|
|
78
|
+
/* @__PURE__ */ jsx("b", { children: kind }),
|
|
79
|
+
device ? ` from ${device}` : ""
|
|
80
|
+
] }) }),
|
|
81
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", theme, onClick: onPaste, children: locale === "vi" ? "D\xE1n" : "Paste" }),
|
|
82
|
+
onDismiss && /* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", theme, onClick: onDismiss, children: "\u2715" })
|
|
83
|
+
] });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
HandoffConnectionStatus,
|
|
88
|
+
HandoffPairingPanel,
|
|
89
|
+
HandoffPayloadBanner
|
|
90
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cx,
|
|
3
|
+
useKitStyles,
|
|
4
|
+
useScope
|
|
5
|
+
} from "./chunk-3AL4SUFD.js";
|
|
6
|
+
|
|
7
|
+
// src/overlay/Toast.tsx
|
|
8
|
+
import {
|
|
9
|
+
createContext,
|
|
10
|
+
useCallback,
|
|
11
|
+
useContext,
|
|
12
|
+
useEffect,
|
|
13
|
+
useMemo,
|
|
14
|
+
useReducer
|
|
15
|
+
} from "react";
|
|
16
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
17
|
+
function toastReducer(state, action) {
|
|
18
|
+
switch (action.type) {
|
|
19
|
+
case "add":
|
|
20
|
+
return [...state, action.toast].slice(-4);
|
|
21
|
+
case "dismiss":
|
|
22
|
+
return state.filter((t) => t.id !== action.id);
|
|
23
|
+
default:
|
|
24
|
+
return state;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
var Ctx = createContext(null);
|
|
28
|
+
var nextId = 1;
|
|
29
|
+
function ToastProvider({ theme, children }) {
|
|
30
|
+
const [items, dispatch] = useReducer(toastReducer, []);
|
|
31
|
+
const dismiss = useCallback((id) => dispatch({ type: "dismiss", id }), []);
|
|
32
|
+
const toast = useCallback((input) => {
|
|
33
|
+
const id = nextId++;
|
|
34
|
+
dispatch({ type: "add", toast: { id, ...input } });
|
|
35
|
+
return id;
|
|
36
|
+
}, []);
|
|
37
|
+
const api = useMemo(() => ({ toast, dismiss }), [toast, dismiss]);
|
|
38
|
+
return /* @__PURE__ */ jsxs(Ctx.Provider, { value: api, children: [
|
|
39
|
+
children,
|
|
40
|
+
/* @__PURE__ */ jsx(ToastViewport, { items, onDismiss: dismiss, theme })
|
|
41
|
+
] });
|
|
42
|
+
}
|
|
43
|
+
function useToast() {
|
|
44
|
+
const c = useContext(Ctx);
|
|
45
|
+
if (!c) throw new Error("useToast must be used inside <ToastProvider>");
|
|
46
|
+
return c;
|
|
47
|
+
}
|
|
48
|
+
function ToastView({ item, onDismiss }) {
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const ms = item.duration ?? 4e3;
|
|
51
|
+
if (ms <= 0) return;
|
|
52
|
+
const t = setTimeout(() => onDismiss(item.id), ms);
|
|
53
|
+
return () => clearTimeout(t);
|
|
54
|
+
}, [item, onDismiss]);
|
|
55
|
+
const live = { role: "status" };
|
|
56
|
+
return /* @__PURE__ */ jsx("div", { className: "mang-toast", "data-tone": item.tone ?? "default", ...live, children: /* @__PURE__ */ jsx("span", { className: "mang-toast-msg", children: item.message }) });
|
|
57
|
+
}
|
|
58
|
+
function ToastViewport({ items, onDismiss, theme }) {
|
|
59
|
+
useKitStyles();
|
|
60
|
+
const scope = useScope(theme);
|
|
61
|
+
if (items.length === 0) return null;
|
|
62
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-toast-viewport"), "aria-live": "polite", children: items.map((item) => /* @__PURE__ */ jsx(ToastView, { item, onDismiss }, item.id)) });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
toastReducer,
|
|
67
|
+
ToastProvider,
|
|
68
|
+
useToast,
|
|
69
|
+
ToastViewport
|
|
70
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cx,
|
|
3
|
+
useKitStyles,
|
|
4
|
+
useScope
|
|
5
|
+
} from "./chunk-3AL4SUFD.js";
|
|
6
|
+
|
|
7
|
+
// src/platform/Badge.tsx
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function Badge({ tone = "accent", icon, theme, className, children }) {
|
|
10
|
+
useKitStyles();
|
|
11
|
+
const scope = useScope(theme);
|
|
12
|
+
return /* @__PURE__ */ jsxs("span", { ...scope, className: cx(scope.className, "mang-badge", className), "data-tone": tone, children: [
|
|
13
|
+
icon != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: icon }),
|
|
14
|
+
children
|
|
15
|
+
] });
|
|
16
|
+
}
|
|
17
|
+
function VerifiedBadge({
|
|
18
|
+
label = "M\u0103ng Verified",
|
|
19
|
+
compact = false,
|
|
20
|
+
title,
|
|
21
|
+
theme,
|
|
22
|
+
className
|
|
23
|
+
}) {
|
|
24
|
+
useKitStyles();
|
|
25
|
+
const scope = useScope(theme);
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"span",
|
|
28
|
+
{
|
|
29
|
+
...scope,
|
|
30
|
+
className: cx(scope.className, "mang-badge", "mang-verified", className),
|
|
31
|
+
title: title ?? label,
|
|
32
|
+
children: [
|
|
33
|
+
/* @__PURE__ */ jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
|
|
34
|
+
"path",
|
|
35
|
+
{
|
|
36
|
+
d: "M9 12l2 2 4-4M12 3l2.3 1.7 2.8-.2 1 2.7 2.3 1.6-.8 2.7.8 2.7-2.3 1.6-1 2.7-2.8-.2L12 21l-2.3-1.7-2.8.2-1-2.7L3.6 15.4l.8-2.7-.8-2.7 2.3-1.6 1-2.7 2.8.2z",
|
|
37
|
+
stroke: "currentColor",
|
|
38
|
+
strokeWidth: "2",
|
|
39
|
+
strokeLinecap: "round",
|
|
40
|
+
strokeLinejoin: "round"
|
|
41
|
+
}
|
|
42
|
+
) }),
|
|
43
|
+
compact ? /* @__PURE__ */ jsx("span", { style: srOnly, children: label }) : /* @__PURE__ */ jsx("span", { children: label })
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
var srOnly = {
|
|
49
|
+
position: "absolute",
|
|
50
|
+
width: 1,
|
|
51
|
+
height: 1,
|
|
52
|
+
padding: 0,
|
|
53
|
+
margin: -1,
|
|
54
|
+
overflow: "hidden",
|
|
55
|
+
clip: "rect(0 0 0 0)",
|
|
56
|
+
whiteSpace: "nowrap",
|
|
57
|
+
border: 0
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
Badge,
|
|
62
|
+
VerifiedBadge
|
|
63
|
+
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Switch
|
|
3
|
+
} from "./chunk-PQGUWJG4.js";
|
|
4
|
+
import {
|
|
5
|
+
cx,
|
|
6
|
+
useAreaStyles,
|
|
7
|
+
useScope
|
|
8
|
+
} from "./chunk-3AL4SUFD.js";
|
|
9
|
+
import {
|
|
10
|
+
tokens
|
|
11
|
+
} from "./chunk-PPOYMKV3.js";
|
|
12
|
+
|
|
13
|
+
// src/analytics/Analytics.tsx
|
|
14
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
var STYLE_ID = "mang-ui-analytics";
|
|
16
|
+
var { fontSize, fontWeight, radius, font } = tokens;
|
|
17
|
+
var CSS = (
|
|
18
|
+
/* css */
|
|
19
|
+
`
|
|
20
|
+
.mang-gate-badge { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.2rem 0.6rem; border-radius: ${radius.full}; font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; font-size: ${fontSize.xs}; }
|
|
21
|
+
.mang-gate-badge[data-met="true"] { background: var(--m-success-soft); color: var(--m-success-on); }
|
|
22
|
+
.mang-gate-badge[data-met="false"] { background: var(--m-sunken); color: var(--m-text-muted); }
|
|
23
|
+
.mang-atable { width: 100%; border-collapse: collapse; font-size: ${fontSize.sm}; }
|
|
24
|
+
.mang-atable th, .mang-atable td { text-align: left; padding: 0.5rem 0.65rem; border-bottom: 1px solid var(--m-line); }
|
|
25
|
+
.mang-atable th { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.semibold}; color: var(--m-text-muted); font-size: ${fontSize.xs}; text-transform: uppercase; letter-spacing: 0.06em; }
|
|
26
|
+
.mang-atable td { color: var(--m-text); font-variant-numeric: tabular-nums; }
|
|
27
|
+
.mang-atable td b { color: var(--m-text-strong); }
|
|
28
|
+
.mang-atable code { font-size: ${fontSize.xs}; color: var(--m-text-muted); }
|
|
29
|
+
`
|
|
30
|
+
);
|
|
31
|
+
function AnalyticsConsentToggle({
|
|
32
|
+
enabled,
|
|
33
|
+
onChange,
|
|
34
|
+
locale = "vi",
|
|
35
|
+
theme,
|
|
36
|
+
className
|
|
37
|
+
}) {
|
|
38
|
+
return /* @__PURE__ */ jsx(
|
|
39
|
+
Switch,
|
|
40
|
+
{
|
|
41
|
+
theme,
|
|
42
|
+
className,
|
|
43
|
+
checked: enabled,
|
|
44
|
+
onChange: (e) => onChange(e.target.checked),
|
|
45
|
+
label: locale === "vi" ? "G\u1EEDi th\u1ED1ng k\xEA \u1EA9n danh \u0111\u1EC3 c\u1EA3i thi\u1EC7n M\u0103ng" : "Send anonymous usage stats to improve M\u0103ng"
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function GateMetBadge({ met, locale = "vi", theme, className }) {
|
|
50
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
51
|
+
const scope = useScope(theme);
|
|
52
|
+
return /* @__PURE__ */ jsxs(
|
|
53
|
+
"span",
|
|
54
|
+
{
|
|
55
|
+
...scope,
|
|
56
|
+
className: cx(scope.className, "mang-gate-badge", className),
|
|
57
|
+
"data-met": met ? "true" : "false",
|
|
58
|
+
children: [
|
|
59
|
+
met ? "\u2705" : "\u2B1C",
|
|
60
|
+
" ",
|
|
61
|
+
met ? locale === "vi" ? "\u0110\u1EA1t c\u1ED5ng" : "Gate met" : locale === "vi" ? "Ch\u01B0a \u0111\u1EA1t" : "Not met"
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
function GateReport({ rows, locale = "vi", theme, className }) {
|
|
67
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
68
|
+
const scope = useScope(theme);
|
|
69
|
+
return /* @__PURE__ */ jsxs("table", { ...scope, className: cx(scope.className, "mang-atable", className), children: [
|
|
70
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
71
|
+
/* @__PURE__ */ jsx("th", { children: locale === "vi" ? "App" : "App" }),
|
|
72
|
+
/* @__PURE__ */ jsx("th", { children: locale === "vi" ? "Thi\u1EBFt b\u1ECB" : "Devices" }),
|
|
73
|
+
/* @__PURE__ */ jsx("th", { children: locale === "vi" ? "Quay l\u1EA1i" : "Returning" })
|
|
74
|
+
] }) }),
|
|
75
|
+
/* @__PURE__ */ jsx("tbody", { children: rows.map((r) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
76
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("b", { children: r.app }) }),
|
|
77
|
+
/* @__PURE__ */ jsx("td", { children: r.devices }),
|
|
78
|
+
/* @__PURE__ */ jsx("td", { children: r.returning })
|
|
79
|
+
] }, r.app)) })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
function EventLogTable({ events, theme, className }) {
|
|
83
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
84
|
+
const scope = useScope(theme);
|
|
85
|
+
return /* @__PURE__ */ jsxs("table", { ...scope, className: cx(scope.className, "mang-atable", className), children: [
|
|
86
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
87
|
+
/* @__PURE__ */ jsx("th", { children: "event" }),
|
|
88
|
+
/* @__PURE__ */ jsx("th", { children: "props" })
|
|
89
|
+
] }) }),
|
|
90
|
+
/* @__PURE__ */ jsx("tbody", { children: events.map((e, i) => /* @__PURE__ */ jsxs(
|
|
91
|
+
"tr",
|
|
92
|
+
{
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("b", { children: e.name }) }),
|
|
95
|
+
/* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("code", { children: e.props ? JSON.stringify(e.props) : "\u2014" }) })
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
i
|
|
99
|
+
)) })
|
|
100
|
+
] });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
AnalyticsConsentToggle,
|
|
105
|
+
GateMetBadge,
|
|
106
|
+
GateReport,
|
|
107
|
+
EventLogTable
|
|
108
|
+
};
|