@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.
Files changed (95) hide show
  1. package/LICENSE +26 -0
  2. package/dist/MangThemeProvider-BqdGKBP2.d.ts +34 -0
  3. package/dist/Money-Dw3GnUvX.d.ts +27 -0
  4. package/dist/actions.d.ts +31 -0
  5. package/dist/actions.js +13 -0
  6. package/dist/ai.d.ts +58 -0
  7. package/dist/ai.js +13 -0
  8. package/dist/analytics.d.ts +40 -0
  9. package/dist/analytics.js +15 -0
  10. package/dist/app.d.ts +24 -0
  11. package/dist/app.js +9 -0
  12. package/dist/catalog.d.ts +76 -0
  13. package/dist/catalog.js +1210 -0
  14. package/dist/charts.d.ts +89 -0
  15. package/dist/charts.js +34 -0
  16. package/dist/chunk-3AL4SUFD.js +301 -0
  17. package/dist/chunk-4XNSYKQE.js +142 -0
  18. package/dist/chunk-5Z4VLQKH.js +43 -0
  19. package/dist/chunk-7P2EQZYD.js +59 -0
  20. package/dist/chunk-7WHNIEDV.js +120 -0
  21. package/dist/chunk-ASZKHSMG.js +82 -0
  22. package/dist/chunk-BCBN2EGH.js +216 -0
  23. package/dist/chunk-BLYAFV45.js +320 -0
  24. package/dist/chunk-DLKEXWPA.js +90 -0
  25. package/dist/chunk-DTASXPTB.js +70 -0
  26. package/dist/chunk-FZRXVRC7.js +63 -0
  27. package/dist/chunk-ID233AGM.js +108 -0
  28. package/dist/chunk-IVYXOKMO.js +74 -0
  29. package/dist/chunk-IX3DYETF.js +61 -0
  30. package/dist/chunk-JJB4PJC3.js +166 -0
  31. package/dist/chunk-K5Q3RCV6.js +119 -0
  32. package/dist/chunk-LNRUPJDF.js +161 -0
  33. package/dist/chunk-LZORNMBL.js +0 -0
  34. package/dist/chunk-OBPXCUVF.js +282 -0
  35. package/dist/chunk-OJX2EIMB.js +145 -0
  36. package/dist/chunk-PPOYMKV3.js +170 -0
  37. package/dist/chunk-PQGUWJG4.js +47 -0
  38. package/dist/chunk-RE7OWRA4.js +187 -0
  39. package/dist/chunk-SJF3CHAW.js +108 -0
  40. package/dist/chunk-UF6ANDJZ.js +112 -0
  41. package/dist/chunk-VGC5DMOM.js +107 -0
  42. package/dist/chunk-VP56Z4BS.js +0 -0
  43. package/dist/chunk-VRD66FIA.js +77 -0
  44. package/dist/chunk-X7T2DJLU.js +113 -0
  45. package/dist/chunk-XPV3OOLU.js +147 -0
  46. package/dist/chunk-YN5O6YL6.js +69 -0
  47. package/dist/chunk-Z4ANGBPC.js +94 -0
  48. package/dist/creator.d.ts +55 -0
  49. package/dist/creator.js +20 -0
  50. package/dist/data-room.d.ts +50 -0
  51. package/dist/data-room.js +17 -0
  52. package/dist/editor.d.ts +32 -0
  53. package/dist/editor.js +14 -0
  54. package/dist/feedback.d.ts +48 -0
  55. package/dist/feedback.js +16 -0
  56. package/dist/forms.d.ts +91 -0
  57. package/dist/forms.js +26 -0
  58. package/dist/handoff.d.ts +37 -0
  59. package/dist/handoff.js +13 -0
  60. package/dist/index.css +2 -0
  61. package/dist/index.d.ts +62 -0
  62. package/dist/index.js +338 -0
  63. package/dist/layout.d.ts +57 -0
  64. package/dist/layout.js +22 -0
  65. package/dist/learning.d.ts +46 -0
  66. package/dist/learning.js +15 -0
  67. package/dist/media.d.ts +48 -0
  68. package/dist/media.js +16 -0
  69. package/dist/monetization.d.ts +30 -0
  70. package/dist/monetization.js +14 -0
  71. package/dist/money.d.ts +45 -0
  72. package/dist/money.js +28 -0
  73. package/dist/navigation.d.ts +36 -0
  74. package/dist/navigation.js +14 -0
  75. package/dist/overlay.d.ts +72 -0
  76. package/dist/overlay.js +20 -0
  77. package/dist/platform.d.ts +94 -0
  78. package/dist/platform.js +42 -0
  79. package/dist/primitives.d.ts +83 -0
  80. package/dist/primitives.js +22 -0
  81. package/dist/privacy.d.ts +28 -0
  82. package/dist/privacy.js +15 -0
  83. package/dist/sandbox.d.ts +40 -0
  84. package/dist/sandbox.js +15 -0
  85. package/dist/settings.d.ts +29 -0
  86. package/dist/settings.js +13 -0
  87. package/dist/surface.d.ts +33 -0
  88. package/dist/surface.js +16 -0
  89. package/dist/theme.css +63 -0
  90. package/dist/theme.d.ts +64 -0
  91. package/dist/theme.js +27 -0
  92. package/dist/tokens.css +119 -0
  93. package/dist/tokens.d.ts +128 -0
  94. package/dist/tokens.js +8 -0
  95. package/package.json +151 -0
@@ -0,0 +1,74 @@
1
+ import {
2
+ Badge
3
+ } from "./chunk-FZRXVRC7.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/privacy/Privacy.tsx
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ var STYLE_ID = "mang-ui-privacy";
16
+ var { fontSize, radius } = tokens;
17
+ var CSS = (
18
+ /* css */
19
+ `
20
+ .mang-privacy { display: flex; align-items: flex-start; gap: 0.5rem; padding: 0.7rem 0.85rem; border-radius: ${radius.md}; background: var(--m-success-soft); color: var(--m-success-on); font-size: ${fontSize.sm}; }
21
+ .mang-privacy[data-tone="warn"] { background: var(--m-warning-soft); color: var(--m-warning-on); }
22
+ .mang-privacy-icon { flex: none; }
23
+ `
24
+ );
25
+ function PrivacyNotice({ children, icon = "\u{1F512}", theme, className }) {
26
+ useAreaStyles(STYLE_ID, CSS);
27
+ const scope = useScope(theme);
28
+ return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-privacy", className), role: "note", children: [
29
+ /* @__PURE__ */ jsx("span", { className: "mang-privacy-icon", "aria-hidden": "true", children: icon }),
30
+ /* @__PURE__ */ jsx("span", { children })
31
+ ] });
32
+ }
33
+ function LocalFirstNotice({
34
+ locale = "vi",
35
+ theme,
36
+ className
37
+ }) {
38
+ return /* @__PURE__ */ jsx(PrivacyNotice, { theme, className, children: locale === "vi" ? "Ch\u1EA1y offline \xB7 d\u1EEF li\u1EC7u ch\u1EC9 \u1EDF tr\xEAn m\xE1y b\u1EA1n" : "Runs offline \xB7 data stays on your device" });
39
+ }
40
+ function NoPiiBadge({ locale = "vi", theme, className }) {
41
+ return /* @__PURE__ */ jsx(Badge, { tone: "success", icon: "\u{1F512}", theme, className, children: locale === "vi" ? "Kh\xF4ng thu th\u1EADp PII" : "No PII" });
42
+ }
43
+ function ExternalLinkWarning({
44
+ href,
45
+ locale = "vi",
46
+ theme,
47
+ className
48
+ }) {
49
+ useAreaStyles(STYLE_ID, CSS);
50
+ const scope = useScope(theme);
51
+ return /* @__PURE__ */ jsxs(
52
+ "div",
53
+ {
54
+ ...scope,
55
+ className: cx(scope.className, "mang-privacy", className),
56
+ "data-tone": "warn",
57
+ role: "note",
58
+ children: [
59
+ /* @__PURE__ */ jsx("span", { className: "mang-privacy-icon", "aria-hidden": "true", children: "\u2197" }),
60
+ /* @__PURE__ */ jsxs("span", { children: [
61
+ locale === "vi" ? "M\u1EDF li\xEAn k\u1EBFt ngo\xE0i: " : "Opens an external link: ",
62
+ /* @__PURE__ */ jsx("b", { children: href })
63
+ ] })
64
+ ]
65
+ }
66
+ );
67
+ }
68
+
69
+ export {
70
+ PrivacyNotice,
71
+ LocalFirstNotice,
72
+ NoPiiBadge,
73
+ ExternalLinkWarning
74
+ };
@@ -0,0 +1,61 @@
1
+ import {
2
+ cx,
3
+ useKitStyles,
4
+ useScope
5
+ } from "./chunk-3AL4SUFD.js";
6
+
7
+ // src/platform/Money.tsx
8
+ import { jsx } from "react/jsx-runtime";
9
+ function formatVnd(amount) {
10
+ const rounded = Math.round(amount);
11
+ const grouped = new Intl.NumberFormat("vi-VN").format(Math.abs(rounded));
12
+ return `${rounded < 0 ? "-" : ""}${grouped} \u0111`;
13
+ }
14
+ function signAttr(value, sign) {
15
+ if (sign === "none") return void 0;
16
+ if (sign === "positive") return "positive";
17
+ if (sign === "negative") return "negative";
18
+ if (value > 0) return "positive";
19
+ if (value < 0) return "negative";
20
+ return void 0;
21
+ }
22
+ function VndText({ amount, sign = "none", theme, className }) {
23
+ useKitStyles();
24
+ const scope = useScope(theme);
25
+ return /* @__PURE__ */ jsx(
26
+ "span",
27
+ {
28
+ ...scope,
29
+ className: cx(scope.className, "mang-money", className),
30
+ "data-sign": signAttr(amount, sign),
31
+ children: formatVnd(amount)
32
+ }
33
+ );
34
+ }
35
+ function MoneyText({
36
+ amount,
37
+ locale = "vi-VN",
38
+ currency = "VND",
39
+ sign = "none",
40
+ theme,
41
+ className
42
+ }) {
43
+ useKitStyles();
44
+ const scope = useScope(theme);
45
+ const text = new Intl.NumberFormat(locale, { style: "currency", currency }).format(amount);
46
+ return /* @__PURE__ */ jsx(
47
+ "span",
48
+ {
49
+ ...scope,
50
+ className: cx(scope.className, "mang-money", className),
51
+ "data-sign": signAttr(amount, sign),
52
+ children: text
53
+ }
54
+ );
55
+ }
56
+
57
+ export {
58
+ formatVnd,
59
+ VndText,
60
+ MoneyText
61
+ };
@@ -0,0 +1,166 @@
1
+ import {
2
+ SafetyScanBadge,
3
+ StaticScanResult
4
+ } from "./chunk-X7T2DJLU.js";
5
+ import {
6
+ Badge
7
+ } from "./chunk-FZRXVRC7.js";
8
+ import {
9
+ cx,
10
+ useAreaStyles,
11
+ useScope
12
+ } from "./chunk-3AL4SUFD.js";
13
+ import {
14
+ tokens
15
+ } from "./chunk-PPOYMKV3.js";
16
+
17
+ // src/creator/Creator.tsx
18
+ import { useRef, useState } from "react";
19
+ import { jsx, jsxs } from "react/jsx-runtime";
20
+ var STYLE_ID = "mang-ui-creator";
21
+ var { fontSize, fontWeight, radius, font } = tokens;
22
+ var CSS = (
23
+ /* css */
24
+ `
25
+ .mang-drop { display: grid; gap: 0.4rem; justify-items: center; text-align: center; padding: 1.75rem 1.25rem; border: 2px dashed var(--m-line-strong); border-radius: ${radius.lg}; background: var(--m-sunken); color: var(--m-text-muted); cursor: pointer; transition: border-color 140ms, background 140ms; }
26
+ .mang-drop[data-over="true"] { border-color: var(--m-accent); background: var(--m-accent-soft); }
27
+ .mang-drop-icon { font-size: 1.8rem; }
28
+ .mang-drop-title { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; color: var(--m-text-strong); font-size: ${fontSize.base}; }
29
+ .mang-drop-file { font-size: ${fontSize.sm}; color: var(--m-text); }
30
+ .mang-manifest { display: grid; gap: 0.5rem; padding: 0.9rem 1rem; border: 1px solid var(--m-line); border-radius: ${radius.lg}; background: var(--m-surface); }
31
+ .mang-manifest-row { display: grid; grid-template-columns: 7rem 1fr; gap: 0.5rem; font-size: ${fontSize.sm}; }
32
+ .mang-manifest-key { color: var(--m-text-muted); font-weight: ${fontWeight.semibold}; }
33
+ .mang-manifest-val { color: var(--m-text); }
34
+ .mang-manifest-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; }
35
+ .mang-scanpanel { display: grid; gap: 0.6rem; }
36
+ `
37
+ );
38
+ function BundleUploadDropzone({
39
+ onFile,
40
+ accept = ".js,.mjs",
41
+ file,
42
+ locale = "vi",
43
+ theme,
44
+ className
45
+ }) {
46
+ useAreaStyles(STYLE_ID, CSS);
47
+ const scope = useScope(theme);
48
+ const inputRef = useRef(null);
49
+ const [over, setOver] = useState(false);
50
+ const pick = (f) => {
51
+ if (f) onFile(f);
52
+ };
53
+ const onDrop = (e) => {
54
+ e.preventDefault();
55
+ setOver(false);
56
+ pick(e.dataTransfer.files?.[0]);
57
+ };
58
+ const trigger = { role: "button", tabIndex: 0 };
59
+ return /* @__PURE__ */ jsxs(
60
+ "div",
61
+ {
62
+ ...scope,
63
+ ...trigger,
64
+ className: cx(scope.className, "mang-drop", className),
65
+ "data-over": over ? "true" : void 0,
66
+ onClick: () => inputRef.current?.click(),
67
+ onKeyDown: (e) => {
68
+ if (e.key === "Enter" || e.key === " ") inputRef.current?.click();
69
+ },
70
+ onDragOver: (e) => {
71
+ e.preventDefault();
72
+ setOver(true);
73
+ },
74
+ onDragLeave: () => setOver(false),
75
+ onDrop,
76
+ children: [
77
+ /* @__PURE__ */ jsx("span", { className: "mang-drop-icon", "aria-hidden": "true", children: "\u{1F4E6}" }),
78
+ /* @__PURE__ */ jsx("span", { className: "mang-drop-title", children: locale === "vi" ? "K\xE9o th\u1EA3 bundle ho\u1EB7c b\u1EA5m \u0111\u1EC3 ch\u1ECDn" : "Drop a bundle or click to choose" }),
79
+ file && /* @__PURE__ */ jsxs("span", { className: "mang-drop-file", children: [
80
+ file.name,
81
+ " \xB7 ",
82
+ (file.size / 1024).toFixed(0),
83
+ " KB"
84
+ ] }),
85
+ /* @__PURE__ */ jsx(
86
+ "input",
87
+ {
88
+ ref: inputRef,
89
+ type: "file",
90
+ accept,
91
+ hidden: true,
92
+ onChange: (e) => {
93
+ pick(e.target.files?.[0]);
94
+ e.target.value = "";
95
+ }
96
+ }
97
+ )
98
+ ]
99
+ }
100
+ );
101
+ }
102
+ function ManifestPreview({ manifest, theme, className }) {
103
+ useAreaStyles(STYLE_ID, CSS);
104
+ const scope = useScope(theme);
105
+ const row = (k, v) => /* @__PURE__ */ jsxs("div", { className: "mang-manifest-row", children: [
106
+ /* @__PURE__ */ jsx("span", { className: "mang-manifest-key", children: k }),
107
+ /* @__PURE__ */ jsx("span", { className: "mang-manifest-val", children: v })
108
+ ] });
109
+ const chips = (items) => items && items.length > 0 ? /* @__PURE__ */ jsx("span", { className: "mang-manifest-chips", children: items.map((it) => /* @__PURE__ */ jsx(Badge, { tone: "neutral", theme, children: it }, it)) }) : "\u2014";
110
+ return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-manifest", className), children: [
111
+ row("id", /* @__PURE__ */ jsx("code", { children: manifest.id })),
112
+ manifest.name != null && row("name", manifest.name),
113
+ manifest.version != null && row("version", /* @__PURE__ */ jsx("code", { children: manifest.version })),
114
+ row("permissions", chips(manifest.permissions)),
115
+ row("surfaces", chips(manifest.surfaces)),
116
+ row("commands", chips(manifest.commands))
117
+ ] });
118
+ }
119
+ function StaticScanPanel({
120
+ level,
121
+ findings,
122
+ locale = "vi",
123
+ theme,
124
+ className
125
+ }) {
126
+ useAreaStyles(STYLE_ID, CSS);
127
+ const scope = useScope(theme);
128
+ return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-scanpanel", className), children: [
129
+ /* @__PURE__ */ jsx(SafetyScanBadge, { level, locale, theme }),
130
+ /* @__PURE__ */ jsx(StaticScanResult, { findings, theme })
131
+ ] });
132
+ }
133
+ var REVIEW_META = {
134
+ draft: { tone: "neutral", icon: "\u{1F4DD}", vi: "Nh\xE1p", en: "Draft" },
135
+ pending_review: { tone: "info", icon: "\u23F3", vi: "Ch\u1EDD duy\u1EC7t", en: "Pending review" },
136
+ changes: { tone: "warning", icon: "\u270F\uFE0F", vi: "C\u1EA7n s\u1EEDa", en: "Changes requested" },
137
+ live: { tone: "success", icon: "\u{1F7E2}", vi: "\u0110ang ch\u1EA1y", en: "Live" },
138
+ rejected: { tone: "danger", icon: "\u26D4", vi: "T\u1EEB ch\u1ED1i", en: "Rejected" }
139
+ };
140
+ function ReviewStatusBadge({
141
+ status,
142
+ locale = "vi",
143
+ theme,
144
+ className
145
+ }) {
146
+ const m = REVIEW_META[status];
147
+ return /* @__PURE__ */ jsx(Badge, { tone: m.tone, icon: m.icon, theme, className, children: locale === "vi" ? m.vi : m.en });
148
+ }
149
+ function VersionBadge({ version, theme, className }) {
150
+ return /* @__PURE__ */ jsxs(Badge, { tone: "neutral", theme, className, children: [
151
+ "v",
152
+ version.replace(/^v/, "")
153
+ ] });
154
+ }
155
+ function BuildBadge({ sha, theme, className }) {
156
+ return /* @__PURE__ */ jsx(Badge, { tone: "neutral", icon: "\u{1F3D7}\uFE0F", theme, className, children: sha.slice(0, 7) });
157
+ }
158
+
159
+ export {
160
+ BundleUploadDropzone,
161
+ ManifestPreview,
162
+ StaticScanPanel,
163
+ ReviewStatusBadge,
164
+ VersionBadge,
165
+ BuildBadge
166
+ };
@@ -0,0 +1,119 @@
1
+ import {
2
+ Badge
3
+ } from "./chunk-FZRXVRC7.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/platform/StatusBadges.tsx
14
+ import { jsx } from "react/jsx-runtime";
15
+ var SURFACE_META = {
16
+ desktop: { icon: "\u{1F5A5}\uFE0F", vi: "M\xE1y t\xEDnh", en: "Desktop" },
17
+ web: { icon: "\u{1F310}", vi: "Web", en: "Web" },
18
+ zalo: { icon: "\u{1F4AC}", vi: "Zalo", en: "Zalo" }
19
+ };
20
+ function SurfaceBadge({ surface, locale = "vi", theme, className }) {
21
+ const m = SURFACE_META[surface];
22
+ return /* @__PURE__ */ jsx(Badge, { tone: "neutral", icon: m.icon, theme, className, children: locale === "vi" ? m.vi : m.en });
23
+ }
24
+ function PermissionBadge({ permission, sensitive, theme, className }) {
25
+ return /* @__PURE__ */ jsx(
26
+ Badge,
27
+ {
28
+ tone: sensitive ? "warning" : "neutral",
29
+ icon: sensitive ? "\u{1F512}" : "\u{1F511}",
30
+ theme,
31
+ className,
32
+ children: permission
33
+ }
34
+ );
35
+ }
36
+ function LocalBadge({ locale = "vi", theme, className }) {
37
+ return /* @__PURE__ */ jsx(Badge, { tone: "neutral", icon: "\u{1F4E6}", theme, className, children: locale === "vi" ? "Tr\xEAn m\xE1y" : "On-device" });
38
+ }
39
+ function CloudBadge({ locale = "vi", theme, className }) {
40
+ return /* @__PURE__ */ jsx(Badge, { tone: "info", icon: "\u2601\uFE0F", theme, className, children: locale === "vi" ? "\u0110\xE1m m\xE2y" : "Cloud" });
41
+ }
42
+ function RealtimeBadge({ locale = "vi", theme, className }) {
43
+ return /* @__PURE__ */ jsx(Badge, { tone: "success", icon: "\u26A1", theme, className, children: locale === "vi" ? "Tr\u1EF1c ti\u1EBFp" : "Live" });
44
+ }
45
+
46
+ // src/platform/Gates.tsx
47
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
48
+ var STYLE_ID = "mang-ui-gates";
49
+ var { fontSize, fontWeight, radius, font } = tokens;
50
+ var CSS = (
51
+ /* css */
52
+ `
53
+ .mang-degrade { display: grid; gap: 0.4rem; justify-items: center; text-align: center; padding: 1.25rem; border: 1px dashed var(--m-line-strong); border-radius: ${radius.lg}; background: var(--m-sunken); color: var(--m-text-muted); }
54
+ .mang-degrade-icon { font-size: 1.6rem; }
55
+ .mang-degrade-title { font-family: "${font.heading}", system-ui, sans-serif; font-weight: ${fontWeight.bold}; color: var(--m-text-strong); font-size: ${fontSize.base}; }
56
+ .mang-degrade-body { font-size: ${fontSize.sm}; max-width: 28rem; }
57
+ `
58
+ );
59
+ var SURFACE_LABEL = {
60
+ desktop: { vi: "m\xE1y t\xEDnh", en: "desktop" },
61
+ web: { vi: "web", en: "web" },
62
+ zalo: { vi: "Zalo", en: "Zalo" }
63
+ };
64
+ function GracefulDegradePanel({
65
+ icon = "\u{1F6A7}",
66
+ title,
67
+ children,
68
+ theme,
69
+ className
70
+ }) {
71
+ useAreaStyles(STYLE_ID, CSS);
72
+ const scope = useScope(theme);
73
+ return /* @__PURE__ */ jsxs("div", { ...scope, className: cx(scope.className, "mang-degrade", className), role: "note", children: [
74
+ /* @__PURE__ */ jsx2("span", { className: "mang-degrade-icon", "aria-hidden": "true", children: icon }),
75
+ title != null && /* @__PURE__ */ jsx2("span", { className: "mang-degrade-title", children: title }),
76
+ children != null && /* @__PURE__ */ jsx2("span", { className: "mang-degrade-body", children })
77
+ ] });
78
+ }
79
+ function SurfaceGate({
80
+ surfaces,
81
+ current,
82
+ locale = "vi",
83
+ fallback,
84
+ theme,
85
+ children
86
+ }) {
87
+ const allowed = !surfaces || surfaces.length === 0 || surfaces.includes(current);
88
+ if (allowed) return /* @__PURE__ */ jsx2(Fragment, { children });
89
+ if (fallback !== void 0) return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
90
+ const where = (surfaces ?? []).map((s) => SURFACE_LABEL[s][locale]).join(" / ");
91
+ return /* @__PURE__ */ jsx2(
92
+ GracefulDegradePanel,
93
+ {
94
+ theme,
95
+ title: locale === "vi" ? "Ch\u01B0a h\u1ED7 tr\u1EE3 \u1EDF \u0111\xE2y" : "Not available here",
96
+ children: locale === "vi" ? `T\xEDnh n\u0103ng n\xE0y ch\u1EA1y tr\xEAn ${where}.` : `This feature runs on ${where}.`
97
+ }
98
+ );
99
+ }
100
+ function PermissionGate({ granted, fallback = null, children }) {
101
+ return /* @__PURE__ */ jsx2(Fragment, { children: granted ? children : fallback });
102
+ }
103
+ var DesktopOnly = ({ current, children }) => current === "desktop" ? /* @__PURE__ */ jsx2(Fragment, { children }) : null;
104
+ var WebOnly = ({ current, children }) => current === "web" ? /* @__PURE__ */ jsx2(Fragment, { children }) : null;
105
+ var ZaloOnly = ({ current, children }) => current === "zalo" ? /* @__PURE__ */ jsx2(Fragment, { children }) : null;
106
+
107
+ export {
108
+ SurfaceBadge,
109
+ PermissionBadge,
110
+ LocalBadge,
111
+ CloudBadge,
112
+ RealtimeBadge,
113
+ GracefulDegradePanel,
114
+ SurfaceGate,
115
+ PermissionGate,
116
+ DesktopOnly,
117
+ WebOnly,
118
+ ZaloOnly
119
+ };
@@ -0,0 +1,161 @@
1
+ import {
2
+ cx,
3
+ useKitStyles,
4
+ useScope
5
+ } from "./chunk-3AL4SUFD.js";
6
+
7
+ // src/overlay/Dialog.tsx
8
+ import { useId, useRef } from "react";
9
+
10
+ // src/overlay/useOverlay.ts
11
+ import { useEffect } from "react";
12
+ var FOCUSABLE = 'a[href],button:not(:disabled),textarea:not(:disabled),input:not(:disabled),select:not(:disabled),[tabindex]:not([tabindex="-1"])';
13
+ function useOverlay(open, onClose, ref) {
14
+ useEffect(() => {
15
+ if (!open) return;
16
+ const node = ref.current;
17
+ const prevActive = document.activeElement;
18
+ const prevOverflow = document.body.style.overflow;
19
+ document.body.style.overflow = "hidden";
20
+ const focusables = node ? Array.from(node.querySelectorAll(FOCUSABLE)) : [];
21
+ (focusables[0] ?? node)?.focus();
22
+ const onKeyDown = (e) => {
23
+ if (e.key === "Escape") {
24
+ e.stopPropagation();
25
+ onClose();
26
+ return;
27
+ }
28
+ if (e.key !== "Tab" || !node) return;
29
+ const items = Array.from(node.querySelectorAll(FOCUSABLE)).filter(
30
+ (el) => el.offsetParent !== null
31
+ );
32
+ const first = items[0];
33
+ const last = items[items.length - 1];
34
+ if (!first || !last) {
35
+ e.preventDefault();
36
+ return;
37
+ }
38
+ const active = document.activeElement;
39
+ if (e.shiftKey && active === first) {
40
+ e.preventDefault();
41
+ last.focus();
42
+ } else if (!e.shiftKey && active === last) {
43
+ e.preventDefault();
44
+ first.focus();
45
+ }
46
+ };
47
+ document.addEventListener("keydown", onKeyDown, true);
48
+ return () => {
49
+ document.removeEventListener("keydown", onKeyDown, true);
50
+ document.body.style.overflow = prevOverflow;
51
+ prevActive?.focus?.();
52
+ };
53
+ }, [open, onClose, ref]);
54
+ }
55
+
56
+ // src/overlay/Dialog.tsx
57
+ import { jsx, jsxs } from "react/jsx-runtime";
58
+ function Dialog({
59
+ open,
60
+ onClose,
61
+ title,
62
+ footer,
63
+ dismissOnBackdrop = true,
64
+ theme,
65
+ className,
66
+ children
67
+ }) {
68
+ useKitStyles();
69
+ const scope = useScope(theme);
70
+ const ref = useRef(null);
71
+ const titleId = useId();
72
+ useOverlay(open, onClose, ref);
73
+ if (!open) return null;
74
+ const panel = {
75
+ role: "dialog",
76
+ "aria-modal": true,
77
+ "aria-labelledby": title ? titleId : void 0
78
+ };
79
+ return /* @__PURE__ */ jsx(
80
+ "div",
81
+ {
82
+ className: "mang-overlay-backdrop",
83
+ onMouseDown: (e) => {
84
+ if (dismissOnBackdrop && e.target === e.currentTarget) onClose();
85
+ },
86
+ children: /* @__PURE__ */ jsxs(
87
+ "div",
88
+ {
89
+ ref,
90
+ ...scope,
91
+ ...panel,
92
+ tabIndex: -1,
93
+ className: cx(scope.className, "mang-dialog", className),
94
+ children: [
95
+ title != null && /* @__PURE__ */ jsx("div", { className: "mang-dialog-head", children: /* @__PURE__ */ jsx("h2", { className: "mang-dialog-title", id: titleId, children: title }) }),
96
+ /* @__PURE__ */ jsx("div", { className: "mang-dialog-body", children }),
97
+ footer != null && /* @__PURE__ */ jsx("div", { className: "mang-dialog-foot", children: footer })
98
+ ]
99
+ }
100
+ )
101
+ }
102
+ );
103
+ }
104
+
105
+ // src/overlay/Sheet.tsx
106
+ import { useId as useId2, useRef as useRef2 } from "react";
107
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
108
+ function Sheet({
109
+ open,
110
+ onClose,
111
+ side = "right",
112
+ title,
113
+ footer,
114
+ dismissOnBackdrop = true,
115
+ theme,
116
+ className,
117
+ children
118
+ }) {
119
+ useKitStyles();
120
+ const scope = useScope(theme);
121
+ const ref = useRef2(null);
122
+ const titleId = useId2();
123
+ useOverlay(open, onClose, ref);
124
+ if (!open) return null;
125
+ const panel = {
126
+ role: "dialog",
127
+ "aria-modal": true,
128
+ "aria-labelledby": title ? titleId : void 0
129
+ };
130
+ return /* @__PURE__ */ jsx2(
131
+ "div",
132
+ {
133
+ className: "mang-overlay-backdrop",
134
+ "data-variant": "sheet",
135
+ onMouseDown: (e) => {
136
+ if (dismissOnBackdrop && e.target === e.currentTarget) onClose();
137
+ },
138
+ children: /* @__PURE__ */ jsxs2(
139
+ "div",
140
+ {
141
+ ref,
142
+ ...scope,
143
+ ...panel,
144
+ tabIndex: -1,
145
+ "data-side": side,
146
+ className: cx(scope.className, "mang-sheet", className),
147
+ children: [
148
+ title != null && /* @__PURE__ */ jsx2("div", { className: "mang-sheet-head", children: /* @__PURE__ */ jsx2("h2", { className: "mang-sheet-title", id: titleId, children: title }) }),
149
+ /* @__PURE__ */ jsx2("div", { className: "mang-sheet-body", style: { flex: 1, overflow: "auto" }, children }),
150
+ footer != null && /* @__PURE__ */ jsx2("div", { className: "mang-sheet-foot", children: footer })
151
+ ]
152
+ }
153
+ )
154
+ }
155
+ );
156
+ }
157
+
158
+ export {
159
+ Dialog,
160
+ Sheet
161
+ };
File without changes