@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,113 @@
|
|
|
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/sandbox/Sandbox.tsx
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var STYLE_ID = "mang-ui-sandbox";
|
|
13
|
+
var { fontSize, fontWeight, radius, font } = tokens;
|
|
14
|
+
var CSS = (
|
|
15
|
+
/* css */
|
|
16
|
+
`
|
|
17
|
+
.mang-sbx { display: flex; flex-direction: column; border: 1px solid var(--m-line); border-radius: ${radius.lg}; overflow: clip; background: var(--m-surface); }
|
|
18
|
+
.mang-sbx-bar { display: flex; align-items: center; gap: 0.5rem; padding: 0.45rem 0.7rem; background: var(--m-sunken); border-bottom: 1px solid var(--m-line); font-size: ${fontSize.xs}; color: var(--m-text-muted); }
|
|
19
|
+
.mang-sbx-origin { font-family: ui-monospace, monospace; }
|
|
20
|
+
.mang-sbx-body { min-height: 8rem; }
|
|
21
|
+
.mang-sbx-error { display: grid; gap: 0.4rem; justify-items: center; text-align: center; padding: 1.5rem; color: var(--m-danger-on); }
|
|
22
|
+
.mang-scan-badge { display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.18rem 0.55rem; border-radius: ${radius.full}; font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.semibold}; font-size: ${fontSize.xs}; }
|
|
23
|
+
.mang-scan-badge[data-level="safe"] { background: var(--m-success-soft); color: var(--m-success-on); }
|
|
24
|
+
.mang-scan-badge[data-level="review"] { background: var(--m-warning-soft); color: var(--m-warning-on); }
|
|
25
|
+
.mang-scan-badge[data-level="blocked"] { background: var(--m-danger-soft); color: var(--m-danger-on); }
|
|
26
|
+
.mang-scan-list { display: grid; gap: 0.4rem; margin: 0; padding: 0; list-style: none; }
|
|
27
|
+
.mang-scan-item { display: flex; gap: 0.5rem; padding: 0.5rem 0.65rem; border: 1px solid var(--m-line); border-radius: ${radius.md}; font-size: ${fontSize.sm}; background: var(--m-sunken); }
|
|
28
|
+
.mang-scan-item[data-sev="error"] { border-left: 3px solid var(--m-danger); }
|
|
29
|
+
.mang-scan-item[data-sev="warn"] { border-left: 3px solid var(--m-warning); }
|
|
30
|
+
`
|
|
31
|
+
);
|
|
32
|
+
function SafetyScanBadge({ level, locale = "vi", theme, className }) {
|
|
33
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
34
|
+
const scope = useScope(theme);
|
|
35
|
+
const label = {
|
|
36
|
+
safe: { vi: "An to\xE0n", en: "Safe" },
|
|
37
|
+
review: { vi: "C\u1EA7n xem", en: "Review" },
|
|
38
|
+
blocked: { vi: "Ch\u1EB7n", en: "Blocked" }
|
|
39
|
+
}[level][locale];
|
|
40
|
+
const icon = { safe: "\u{1F6E1}\uFE0F", review: "\u26A0\uFE0F", blocked: "\u26D4" }[level];
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"span",
|
|
43
|
+
{
|
|
44
|
+
...scope,
|
|
45
|
+
className: cx(scope.className, "mang-scan-badge", className),
|
|
46
|
+
"data-level": level,
|
|
47
|
+
children: [
|
|
48
|
+
icon,
|
|
49
|
+
" ",
|
|
50
|
+
label
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
function SandboxFrame({ children, origin, source, theme, className }) {
|
|
56
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
57
|
+
const scope = useScope(theme);
|
|
58
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-sbx", className), children: [
|
|
59
|
+
/* @__PURE__ */ jsxs("div", { className: "mang-sbx-bar", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u{1F9EA}" }),
|
|
61
|
+
source,
|
|
62
|
+
origin && /* @__PURE__ */ jsx("span", { className: "mang-sbx-origin", children: origin })
|
|
63
|
+
] }),
|
|
64
|
+
/* @__PURE__ */ jsx("div", { className: "mang-sbx-body", children })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
function SandboxError({ message, theme, className }) {
|
|
68
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
69
|
+
const scope = useScope(theme);
|
|
70
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-sbx-error", className), role: "alert", children: [
|
|
71
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { fontSize: "1.6rem" }, children: "\u26D4" }),
|
|
72
|
+
/* @__PURE__ */ jsx("span", { children: message ?? "Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c app trong h\u1ED9p c\xE1t." })
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
function StaticScanResult({
|
|
76
|
+
findings,
|
|
77
|
+
emptyLabel,
|
|
78
|
+
theme,
|
|
79
|
+
className
|
|
80
|
+
}) {
|
|
81
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
82
|
+
const scope = useScope(theme);
|
|
83
|
+
if (findings.length === 0) {
|
|
84
|
+
return /* @__PURE__ */ jsx(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
...scope,
|
|
88
|
+
className: cx(scope.className, className),
|
|
89
|
+
style: { fontSize: tokens.fontSize.sm, color: "var(--m-text-muted)" },
|
|
90
|
+
children: emptyLabel ?? "Kh\xF4ng c\xF3 c\u1EA3nh b\xE1o."
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return /* @__PURE__ */ jsx("ul", { ...scope, className: cx(scope.className, "mang-scan-list", className), children: findings.map((f, i) => /* @__PURE__ */ jsxs(
|
|
95
|
+
"li",
|
|
96
|
+
{
|
|
97
|
+
className: "mang-scan-item",
|
|
98
|
+
"data-sev": f.severity,
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: f.severity === "error" ? "\u26D4" : f.severity === "warn" ? "\u26A0\uFE0F" : "\u2139\uFE0F" }),
|
|
101
|
+
/* @__PURE__ */ jsx("span", { children: f.message })
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
i
|
|
105
|
+
)) });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
SafetyScanBadge,
|
|
110
|
+
SandboxFrame,
|
|
111
|
+
SandboxError,
|
|
112
|
+
StaticScanResult
|
|
113
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
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/layout/Layout.tsx
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
var STYLE_ID = "mang-ui-layout";
|
|
13
|
+
var { fontSize, fontWeight, font, space } = tokens;
|
|
14
|
+
var CSS = (
|
|
15
|
+
/* css */
|
|
16
|
+
`
|
|
17
|
+
.mang-page { width: 100%; max-width: 68rem; margin: 0 auto; padding: clamp(1rem, 3vw, 2rem); }
|
|
18
|
+
.mang-container { width: 100%; max-width: 52rem; margin: 0 auto; }
|
|
19
|
+
.mang-container[data-width="reading"] { max-width: 42rem; }
|
|
20
|
+
.mang-pagehead { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 1rem; }
|
|
21
|
+
.mang-pagehead-titles { display: grid; gap: 0.2rem; }
|
|
22
|
+
.mang-pagehead-eyebrow { font-size: ${fontSize.xs}; font-weight: ${fontWeight.bold}; text-transform: uppercase; letter-spacing: 0.14em; color: var(--m-accent); }
|
|
23
|
+
.mang-pagehead-title { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; font-size: ${fontSize["2xl"]}; color: var(--m-text-strong); margin: 0; }
|
|
24
|
+
.mang-pagehead-actions { display: flex; gap: 0.5rem; align-items: center; }
|
|
25
|
+
.mang-sectionhead { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.semibold}; font-size: ${fontSize.lg}; color: var(--m-text-strong); margin: 0 0 0.5rem; }
|
|
26
|
+
.mang-bottombar { position: sticky; bottom: 0; display: flex; gap: 0.5rem; align-items: center; justify-content: flex-end; padding: 0.7rem clamp(1rem, 3vw, 2rem); background: var(--m-surface); border-top: 1px solid var(--m-line); box-shadow: 0 -8px 24px -18px rgba(0,0,0,0.3); }
|
|
27
|
+
.mang-listrow { display: flex; align-items: center; gap: 0.75rem; width: 100%; box-sizing: border-box; padding: 0.7rem 0.85rem; border-radius: ${tokens.radius.md}; background: var(--m-surface); border: 1px solid var(--m-line); text-align: left; color: var(--m-text); }
|
|
28
|
+
.mang-listrow-lead, .mang-listrow-trail { flex: none; display: flex; align-items: center; }
|
|
29
|
+
.mang-listrow-main { flex: 1; min-width: 0; display: grid; gap: 0.1rem; }
|
|
30
|
+
.mang-listrow-title { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.semibold}; font-size: ${fontSize.base}; color: var(--m-text-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
31
|
+
.mang-listrow-meta { font-size: ${fontSize.sm}; color: var(--m-text-muted); }
|
|
32
|
+
button.mang-listrow { appearance: none; cursor: pointer; font: inherit; transition: border-color 150ms ${"cubic-bezier(0.16,1,0.3,1)"}, transform 150ms ${"cubic-bezier(0.16,1,0.3,1)"}; }
|
|
33
|
+
button.mang-listrow:hover { border-color: var(--m-accent); }
|
|
34
|
+
button.mang-listrow:active { transform: scale(0.995); }
|
|
35
|
+
button.mang-listrow:focus-visible { outline: 3px solid color-mix(in oklab, ${tokens.color.mangGreen} 45%, transparent); outline-offset: 2px; }
|
|
36
|
+
@media (prefers-reduced-motion: reduce) { button.mang-listrow { transition: none; } }
|
|
37
|
+
`
|
|
38
|
+
);
|
|
39
|
+
function AppFrame({ className, style, children }) {
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
41
|
+
"div",
|
|
42
|
+
{
|
|
43
|
+
className,
|
|
44
|
+
style: { display: "flex", flexDirection: "column", minHeight: "100dvh", ...style },
|
|
45
|
+
children
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function Page({ theme, className, children }) {
|
|
50
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
51
|
+
const scope = useScope(theme);
|
|
52
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-page", className), children });
|
|
53
|
+
}
|
|
54
|
+
function Container({ width = "default", theme, className, children }) {
|
|
55
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
56
|
+
const scope = useScope(theme);
|
|
57
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-container", className), "data-width": width, children });
|
|
58
|
+
}
|
|
59
|
+
function PageHeader({ eyebrow, title, actions, theme, className }) {
|
|
60
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
61
|
+
const scope = useScope(theme);
|
|
62
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-pagehead", className), children: [
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "mang-pagehead-titles", children: [
|
|
64
|
+
eyebrow != null && /* @__PURE__ */ jsx("span", { className: "mang-pagehead-eyebrow", children: eyebrow }),
|
|
65
|
+
/* @__PURE__ */ jsx("h1", { className: "mang-pagehead-title", children: title })
|
|
66
|
+
] }),
|
|
67
|
+
actions != null && /* @__PURE__ */ jsx("div", { className: "mang-pagehead-actions", children: actions })
|
|
68
|
+
] });
|
|
69
|
+
}
|
|
70
|
+
function Section({ title, theme, className, children }) {
|
|
71
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
72
|
+
const scope = useScope(theme);
|
|
73
|
+
return /* @__PURE__ */ jsxs(
|
|
74
|
+
"section",
|
|
75
|
+
{
|
|
76
|
+
...scope,
|
|
77
|
+
className: cx(scope.className, className),
|
|
78
|
+
style: { marginBottom: space[6] },
|
|
79
|
+
children: [
|
|
80
|
+
title != null && /* @__PURE__ */ jsx("h2", { className: "mang-sectionhead", children: title }),
|
|
81
|
+
children
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
function BottomActionBar({ theme, className, children }) {
|
|
87
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
88
|
+
const scope = useScope(theme);
|
|
89
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-bottombar", className), children });
|
|
90
|
+
}
|
|
91
|
+
function ListRow({
|
|
92
|
+
leading,
|
|
93
|
+
title,
|
|
94
|
+
meta,
|
|
95
|
+
trailing,
|
|
96
|
+
onClick,
|
|
97
|
+
theme,
|
|
98
|
+
className
|
|
99
|
+
}) {
|
|
100
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
101
|
+
const scope = useScope(theme);
|
|
102
|
+
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
103
|
+
leading != null && /* @__PURE__ */ jsx("span", { className: "mang-listrow-lead", children: leading }),
|
|
104
|
+
/* @__PURE__ */ jsxs("span", { className: "mang-listrow-main", children: [
|
|
105
|
+
/* @__PURE__ */ jsx("span", { className: "mang-listrow-title", children: title }),
|
|
106
|
+
meta != null && /* @__PURE__ */ jsx("span", { className: "mang-listrow-meta", children: meta })
|
|
107
|
+
] }),
|
|
108
|
+
trailing != null && /* @__PURE__ */ jsx("span", { className: "mang-listrow-trail", children: trailing })
|
|
109
|
+
] });
|
|
110
|
+
if (onClick) {
|
|
111
|
+
return /* @__PURE__ */ jsx(
|
|
112
|
+
"button",
|
|
113
|
+
{
|
|
114
|
+
...scope,
|
|
115
|
+
type: "button",
|
|
116
|
+
className: cx(scope.className, "mang-listrow", className),
|
|
117
|
+
onClick,
|
|
118
|
+
children: inner
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-listrow", className), children: inner });
|
|
123
|
+
}
|
|
124
|
+
function SafeArea({
|
|
125
|
+
edges = ["top", "bottom", "left", "right"],
|
|
126
|
+
className,
|
|
127
|
+
style,
|
|
128
|
+
children
|
|
129
|
+
}) {
|
|
130
|
+
const pad = {};
|
|
131
|
+
if (edges.includes("top")) pad.paddingTop = "env(safe-area-inset-top)";
|
|
132
|
+
if (edges.includes("bottom")) pad.paddingBottom = "env(safe-area-inset-bottom)";
|
|
133
|
+
if (edges.includes("left")) pad.paddingLeft = "env(safe-area-inset-left)";
|
|
134
|
+
if (edges.includes("right")) pad.paddingRight = "env(safe-area-inset-right)";
|
|
135
|
+
return /* @__PURE__ */ jsx("div", { className, style: { ...pad, ...style }, children });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
AppFrame,
|
|
140
|
+
Page,
|
|
141
|
+
Container,
|
|
142
|
+
PageHeader,
|
|
143
|
+
Section,
|
|
144
|
+
BottomActionBar,
|
|
145
|
+
ListRow,
|
|
146
|
+
SafeArea
|
|
147
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cx,
|
|
3
|
+
useKitStyles,
|
|
4
|
+
useScope
|
|
5
|
+
} from "./chunk-3AL4SUFD.js";
|
|
6
|
+
|
|
7
|
+
// src/actions/Button.tsx
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function Button({
|
|
10
|
+
variant = "primary",
|
|
11
|
+
size = "md",
|
|
12
|
+
block,
|
|
13
|
+
icon,
|
|
14
|
+
theme,
|
|
15
|
+
className,
|
|
16
|
+
children,
|
|
17
|
+
type,
|
|
18
|
+
...rest
|
|
19
|
+
}) {
|
|
20
|
+
useKitStyles();
|
|
21
|
+
const scope = useScope(theme);
|
|
22
|
+
return /* @__PURE__ */ jsxs(
|
|
23
|
+
"button",
|
|
24
|
+
{
|
|
25
|
+
...rest,
|
|
26
|
+
type: type ?? "button",
|
|
27
|
+
className: cx(scope.className, "mang-btn", className),
|
|
28
|
+
"data-theme": scope["data-theme"],
|
|
29
|
+
"data-density": scope["data-density"],
|
|
30
|
+
"data-variant": variant,
|
|
31
|
+
"data-size": size,
|
|
32
|
+
"data-block": block ? "true" : void 0,
|
|
33
|
+
children: [
|
|
34
|
+
icon != null && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { display: "inline-flex" }, children: icon }),
|
|
35
|
+
children
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function IconButton({
|
|
41
|
+
label,
|
|
42
|
+
size = "md",
|
|
43
|
+
variant = "ghost",
|
|
44
|
+
className,
|
|
45
|
+
children,
|
|
46
|
+
...rest
|
|
47
|
+
}) {
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
Button,
|
|
50
|
+
{
|
|
51
|
+
...rest,
|
|
52
|
+
variant,
|
|
53
|
+
size,
|
|
54
|
+
"aria-label": label,
|
|
55
|
+
title: rest.title ?? label,
|
|
56
|
+
className: cx("mang-iconbtn", className),
|
|
57
|
+
children
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
function ButtonGroup({ className, children }) {
|
|
62
|
+
return /* @__PURE__ */ jsx("div", { className: cx("mang-btn-group", className), children });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
Button,
|
|
67
|
+
IconButton,
|
|
68
|
+
ButtonGroup
|
|
69
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
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/editor/Editor.tsx
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
var STYLE_ID = "mang-ui-editor";
|
|
14
|
+
var { fontSize, fontWeight, radius, font, lineHeight } = tokens;
|
|
15
|
+
var CSS = (
|
|
16
|
+
/* css */
|
|
17
|
+
`
|
|
18
|
+
.mang-prose { color: var(--m-text); line-height: ${lineHeight.relaxed}; font-size: ${fontSize.base}; }
|
|
19
|
+
.mang-prose :where(h1,h2,h3) { font-family: "${font.heading}", system-ui, sans-serif; color: var(--m-text-strong); line-height: ${lineHeight.tight}; margin: 1.2em 0 0.5em; }
|
|
20
|
+
.mang-prose :where(p,ul,ol) { margin: 0.6em 0; }
|
|
21
|
+
.mang-prose :where(a) { color: var(--m-accent); text-underline-offset: 2px; }
|
|
22
|
+
.mang-prose :where(code) { font-family: ui-monospace, monospace; font-size: 0.9em; background: var(--m-sunken); padding: 0.1em 0.35em; border-radius: ${radius.sm}; }
|
|
23
|
+
.mang-prose :where(blockquote) { margin: 0.8em 0; padding-left: 0.9em; border-left: 3px solid var(--m-line-strong); color: var(--m-text-muted); }
|
|
24
|
+
.mang-codeblock { position: relative; }
|
|
25
|
+
.mang-codeblock pre { margin: 0; overflow: auto; padding: 0.85rem 0.95rem; border-radius: ${radius.md}; background: var(--m-sunken); border: 1px solid var(--m-line); }
|
|
26
|
+
.mang-codeblock code { font-family: ui-monospace, monospace; font-size: ${fontSize.sm}; color: var(--m-text); white-space: pre; }
|
|
27
|
+
.mang-codeblock-copy { position: absolute; top: 0.5rem; right: 0.5rem; appearance: none; cursor: pointer; border: 1px solid var(--m-line-strong); background: var(--m-surface); color: var(--m-text); border-radius: ${radius.sm}; padding: 0.2rem 0.5rem; font-size: ${fontSize.xs}; font-weight: ${fontWeight.semibold}; }
|
|
28
|
+
.mang-kbd { font-family: ui-monospace, monospace; font-size: 0.85em; padding: 0.1em 0.45em; border-radius: ${radius.sm}; border: 1px solid var(--m-line-strong); border-bottom-width: 2px; background: var(--m-surface); color: var(--m-text-strong); }
|
|
29
|
+
.mang-callout { display: flex; gap: 0.6rem; padding: 0.75rem 0.9rem; border-radius: ${radius.md}; font-size: ${fontSize.sm}; border: 1px solid var(--m-line); background: var(--m-sunken); color: var(--m-text); }
|
|
30
|
+
.mang-callout[data-tone="tip"] { background: var(--m-success-soft); color: var(--m-success-on); }
|
|
31
|
+
.mang-callout[data-tone="warn"] { background: var(--m-warning-soft); color: var(--m-warning-on); }
|
|
32
|
+
.mang-callout[data-tone="danger"] { background: var(--m-danger-soft); color: var(--m-danger-on); }
|
|
33
|
+
.mang-callout-icon { flex: none; }
|
|
34
|
+
`
|
|
35
|
+
);
|
|
36
|
+
function Prose({ children, theme, className }) {
|
|
37
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
38
|
+
const scope = useScope(theme);
|
|
39
|
+
return /* @__PURE__ */ jsx("div", { ...scope, className: cx(scope.className, "mang-prose", className), children });
|
|
40
|
+
}
|
|
41
|
+
function CodeBlock({
|
|
42
|
+
code,
|
|
43
|
+
copyable = true,
|
|
44
|
+
locale = "vi",
|
|
45
|
+
theme,
|
|
46
|
+
className
|
|
47
|
+
}) {
|
|
48
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
49
|
+
const scope = useScope(theme);
|
|
50
|
+
const [copied, setCopied] = useState(false);
|
|
51
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-codeblock", className), children: [
|
|
52
|
+
/* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: code }) }),
|
|
53
|
+
copyable && /* @__PURE__ */ jsx(
|
|
54
|
+
"button",
|
|
55
|
+
{
|
|
56
|
+
type: "button",
|
|
57
|
+
className: "mang-codeblock-copy",
|
|
58
|
+
onClick: () => {
|
|
59
|
+
void navigator.clipboard?.writeText(code).then(() => {
|
|
60
|
+
setCopied(true);
|
|
61
|
+
setTimeout(() => setCopied(false), 1500);
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
children: copied ? locale === "vi" ? "\u0110\xE3 ch\xE9p" : "Copied" : locale === "vi" ? "Ch\xE9p" : "Copy"
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
] });
|
|
68
|
+
}
|
|
69
|
+
function Kbd({ children, className }) {
|
|
70
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
71
|
+
return /* @__PURE__ */ jsx("kbd", { className: cx("mang-kbd", className), children });
|
|
72
|
+
}
|
|
73
|
+
function CalloutBlock({
|
|
74
|
+
tone = "note",
|
|
75
|
+
icon,
|
|
76
|
+
children,
|
|
77
|
+
theme,
|
|
78
|
+
className
|
|
79
|
+
}) {
|
|
80
|
+
useAreaStyles(STYLE_ID, CSS);
|
|
81
|
+
const scope = useScope(theme);
|
|
82
|
+
const defaultIcon = { note: "\u2139\uFE0F", tip: "\u{1F4A1}", warn: "\u26A0\uFE0F", danger: "\u26D4" }[tone];
|
|
83
|
+
return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-callout", className), "data-tone": tone, children: [
|
|
84
|
+
/* @__PURE__ */ jsx("span", { className: "mang-callout-icon", "aria-hidden": "true", children: icon ?? defaultIcon }),
|
|
85
|
+
/* @__PURE__ */ jsx("span", { children })
|
|
86
|
+
] });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export {
|
|
90
|
+
Prose,
|
|
91
|
+
CodeBlock,
|
|
92
|
+
Kbd,
|
|
93
|
+
CalloutBlock
|
|
94
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { Locale } from '@mangtre/core';
|
|
3
|
+
import { ScanLevel, ScanFinding } from './sandbox.js';
|
|
4
|
+
import { T as ThemeMode } from './MangThemeProvider-BqdGKBP2.js';
|
|
5
|
+
|
|
6
|
+
interface Themed {
|
|
7
|
+
theme?: ThemeMode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
interface BundleUploadDropzoneProps extends Themed {
|
|
11
|
+
onFile: (file: File) => void;
|
|
12
|
+
/** Accept attribute (default ".js,.mjs"). */
|
|
13
|
+
accept?: string;
|
|
14
|
+
/** Currently selected file (for the "selected" state). */
|
|
15
|
+
file?: {
|
|
16
|
+
name: string;
|
|
17
|
+
size: number;
|
|
18
|
+
} | null;
|
|
19
|
+
locale?: Locale;
|
|
20
|
+
}
|
|
21
|
+
declare function BundleUploadDropzone({ onFile, accept, file, locale, theme, className, }: BundleUploadDropzoneProps): react.JSX.Element;
|
|
22
|
+
interface ManifestSummary {
|
|
23
|
+
id: string;
|
|
24
|
+
name?: string;
|
|
25
|
+
version?: string;
|
|
26
|
+
permissions?: string[];
|
|
27
|
+
surfaces?: string[];
|
|
28
|
+
commands?: string[];
|
|
29
|
+
}
|
|
30
|
+
interface ManifestPreviewProps extends Themed {
|
|
31
|
+
manifest: ManifestSummary;
|
|
32
|
+
}
|
|
33
|
+
declare function ManifestPreview({ manifest, theme, className }: ManifestPreviewProps): react.JSX.Element;
|
|
34
|
+
interface StaticScanPanelProps extends Themed {
|
|
35
|
+
level: ScanLevel;
|
|
36
|
+
findings: ScanFinding[];
|
|
37
|
+
locale?: Locale;
|
|
38
|
+
}
|
|
39
|
+
declare function StaticScanPanel({ level, findings, locale, theme, className, }: StaticScanPanelProps): react.JSX.Element;
|
|
40
|
+
type ReviewStatus = "draft" | "pending_review" | "changes" | "live" | "rejected";
|
|
41
|
+
interface ReviewStatusBadgeProps extends Themed {
|
|
42
|
+
status: ReviewStatus;
|
|
43
|
+
locale?: Locale;
|
|
44
|
+
}
|
|
45
|
+
declare function ReviewStatusBadge({ status, locale, theme, className, }: ReviewStatusBadgeProps): react.JSX.Element;
|
|
46
|
+
interface VersionBadgeProps extends Themed {
|
|
47
|
+
version: string;
|
|
48
|
+
}
|
|
49
|
+
declare function VersionBadge({ version, theme, className }: VersionBadgeProps): react.JSX.Element;
|
|
50
|
+
interface BuildBadgeProps extends Themed {
|
|
51
|
+
sha: string;
|
|
52
|
+
}
|
|
53
|
+
declare function BuildBadge({ sha, theme, className }: BuildBadgeProps): react.JSX.Element;
|
|
54
|
+
|
|
55
|
+
export { BuildBadge, type BuildBadgeProps, BundleUploadDropzone, type BundleUploadDropzoneProps, ManifestPreview, type ManifestPreviewProps, type ManifestSummary, type ReviewStatus, ReviewStatusBadge, type ReviewStatusBadgeProps, StaticScanPanel, type StaticScanPanelProps, VersionBadge, type VersionBadgeProps };
|
package/dist/creator.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BuildBadge,
|
|
3
|
+
BundleUploadDropzone,
|
|
4
|
+
ManifestPreview,
|
|
5
|
+
ReviewStatusBadge,
|
|
6
|
+
StaticScanPanel,
|
|
7
|
+
VersionBadge
|
|
8
|
+
} from "./chunk-JJB4PJC3.js";
|
|
9
|
+
import "./chunk-X7T2DJLU.js";
|
|
10
|
+
import "./chunk-FZRXVRC7.js";
|
|
11
|
+
import "./chunk-3AL4SUFD.js";
|
|
12
|
+
import "./chunk-PPOYMKV3.js";
|
|
13
|
+
export {
|
|
14
|
+
BuildBadge,
|
|
15
|
+
BundleUploadDropzone,
|
|
16
|
+
ManifestPreview,
|
|
17
|
+
ReviewStatusBadge,
|
|
18
|
+
StaticScanPanel,
|
|
19
|
+
VersionBadge
|
|
20
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { Locale } from '@mangtre/core';
|
|
4
|
+
import { T as ThemeMode } from './MangThemeProvider-BqdGKBP2.js';
|
|
5
|
+
|
|
6
|
+
type RoomStatus = "offline" | "cloud" | "realtime";
|
|
7
|
+
interface RoomStatusBadgeProps {
|
|
8
|
+
status: RoomStatus;
|
|
9
|
+
/** Connected peers (shown when realtime). */
|
|
10
|
+
peers?: number;
|
|
11
|
+
locale?: Locale;
|
|
12
|
+
theme?: ThemeMode;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function RoomStatusBadge({ status, peers, locale, theme, className, }: RoomStatusBadgeProps): react.JSX.Element;
|
|
16
|
+
interface RoomShareButtonProps {
|
|
17
|
+
onShare: () => void;
|
|
18
|
+
locale?: Locale;
|
|
19
|
+
theme?: ThemeMode;
|
|
20
|
+
className?: string;
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
declare function RoomShareButton({ onShare, locale, theme, className, children, }: RoomShareButtonProps): react.JSX.Element;
|
|
24
|
+
interface RoomLinkCardProps {
|
|
25
|
+
url: string;
|
|
26
|
+
onCopy?: () => void;
|
|
27
|
+
locale?: Locale;
|
|
28
|
+
theme?: ThemeMode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
declare function RoomLinkCard({ url, onCopy, locale, theme, className }: RoomLinkCardProps): react.JSX.Element;
|
|
32
|
+
interface RoomPresenceProps {
|
|
33
|
+
/** Peer initials/labels (first letter shown). */
|
|
34
|
+
peers: string[];
|
|
35
|
+
/** Cap avatars shown; rest collapse into "+N". */
|
|
36
|
+
max?: number;
|
|
37
|
+
theme?: ThemeMode;
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
declare function RoomPresence({ peers, max, theme, className }: RoomPresenceProps): react.JSX.Element;
|
|
41
|
+
interface RoomConflictNoticeProps {
|
|
42
|
+
onReload: () => void;
|
|
43
|
+
locale?: Locale;
|
|
44
|
+
theme?: ThemeMode;
|
|
45
|
+
className?: string;
|
|
46
|
+
}
|
|
47
|
+
/** Shown when a remote change conflicts with a local edit (P2). */
|
|
48
|
+
declare function RoomConflictNotice({ onReload, locale, theme, className, }: RoomConflictNoticeProps): react.JSX.Element;
|
|
49
|
+
|
|
50
|
+
export { RoomConflictNotice, type RoomConflictNoticeProps, RoomLinkCard, type RoomLinkCardProps, RoomPresence, type RoomPresenceProps, RoomShareButton, type RoomShareButtonProps, type RoomStatus, RoomStatusBadge, type RoomStatusBadgeProps };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RoomConflictNotice,
|
|
3
|
+
RoomLinkCard,
|
|
4
|
+
RoomPresence,
|
|
5
|
+
RoomShareButton,
|
|
6
|
+
RoomStatusBadge
|
|
7
|
+
} from "./chunk-OJX2EIMB.js";
|
|
8
|
+
import "./chunk-YN5O6YL6.js";
|
|
9
|
+
import "./chunk-3AL4SUFD.js";
|
|
10
|
+
import "./chunk-PPOYMKV3.js";
|
|
11
|
+
export {
|
|
12
|
+
RoomConflictNotice,
|
|
13
|
+
RoomLinkCard,
|
|
14
|
+
RoomPresence,
|
|
15
|
+
RoomShareButton,
|
|
16
|
+
RoomStatusBadge
|
|
17
|
+
};
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { T as ThemeMode } from './MangThemeProvider-BqdGKBP2.js';
|
|
4
|
+
import '@mangtre/core';
|
|
5
|
+
|
|
6
|
+
interface Themed {
|
|
7
|
+
theme?: ThemeMode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function Prose({ children, theme, className }: Themed & {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}): react.JSX.Element;
|
|
13
|
+
interface CodeBlockProps extends Themed {
|
|
14
|
+
code: string;
|
|
15
|
+
/** Show a copy button. Default true. */
|
|
16
|
+
copyable?: boolean;
|
|
17
|
+
locale?: "vi" | "en";
|
|
18
|
+
}
|
|
19
|
+
declare function CodeBlock({ code, copyable, locale, theme, className, }: CodeBlockProps): react.JSX.Element;
|
|
20
|
+
declare function Kbd({ children, className }: {
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
className?: string;
|
|
23
|
+
}): react.JSX.Element;
|
|
24
|
+
type CalloutTone = "note" | "tip" | "warn" | "danger";
|
|
25
|
+
interface CalloutBlockProps extends Themed {
|
|
26
|
+
tone?: CalloutTone;
|
|
27
|
+
icon?: ReactNode;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
declare function CalloutBlock({ tone, icon, children, theme, className, }: CalloutBlockProps): react.JSX.Element;
|
|
31
|
+
|
|
32
|
+
export { CalloutBlock, type CalloutBlockProps, type CalloutTone, CodeBlock, type CodeBlockProps, Kbd, Prose };
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
3
|
+
import { T as ThemeMode } from './MangThemeProvider-BqdGKBP2.js';
|
|
4
|
+
import '@mangtre/core';
|
|
5
|
+
|
|
6
|
+
interface StateProps {
|
|
7
|
+
icon?: ReactNode;
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/** Optional action (e.g. a Button). */
|
|
11
|
+
action?: ReactNode;
|
|
12
|
+
theme?: ThemeMode;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
interface EmptyStateProps extends StateProps {
|
|
16
|
+
}
|
|
17
|
+
declare function EmptyState({ icon, title, description, action, theme, className, }: EmptyStateProps): react.JSX.Element;
|
|
18
|
+
interface ErrorStateProps extends StateProps {
|
|
19
|
+
}
|
|
20
|
+
declare function ErrorState({ icon, title, description, action, theme, className, }: ErrorStateProps): react.JSX.Element;
|
|
21
|
+
interface SkeletonProps {
|
|
22
|
+
width?: string | number;
|
|
23
|
+
height?: string | number;
|
|
24
|
+
/** Pill shape (e.g. for avatars/lines). */
|
|
25
|
+
rounded?: boolean;
|
|
26
|
+
theme?: ThemeMode;
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
}
|
|
30
|
+
declare function Skeleton({ width, height, rounded, theme, className, style, }: SkeletonProps): react.JSX.Element;
|
|
31
|
+
interface SpinnerProps {
|
|
32
|
+
/** Diameter (px or CSS length). */
|
|
33
|
+
size?: string | number;
|
|
34
|
+
label?: string;
|
|
35
|
+
theme?: ThemeMode;
|
|
36
|
+
className?: string;
|
|
37
|
+
}
|
|
38
|
+
declare function Spinner({ size, label, theme, className }: SpinnerProps): react.JSX.Element;
|
|
39
|
+
interface ProgressProps {
|
|
40
|
+
/** 0–100. Omit for an indeterminate bar. */
|
|
41
|
+
value?: number;
|
|
42
|
+
theme?: ThemeMode;
|
|
43
|
+
className?: string;
|
|
44
|
+
label?: string;
|
|
45
|
+
}
|
|
46
|
+
declare function Progress({ value, theme, className, label }: ProgressProps): react.JSX.Element;
|
|
47
|
+
|
|
48
|
+
export { EmptyState, type EmptyStateProps, ErrorState, type ErrorStateProps, Progress, type ProgressProps, Skeleton, type SkeletonProps, Spinner, type SpinnerProps };
|