@leduchai/vmeta-ui-shell 0.1.5 → 0.1.7

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/index.cjs CHANGED
@@ -22,6 +22,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
24
  VmetaAppShell: () => VmetaAppShell,
25
+ VmetaBrandMark: () => VmetaBrandMark,
26
+ VmetaCollapseIcon: () => VmetaCollapseIcon,
25
27
  VmetaSidebar: () => VmetaSidebar,
26
28
  isMenuItemActive: () => isMenuItemActive
27
29
  });
@@ -29,6 +31,25 @@ module.exports = __toCommonJS(index_exports);
29
31
  var import_react = require("react");
30
32
  var import_jsx_runtime = require("react/jsx-runtime");
31
33
  var allowAllPermissions = () => true;
34
+ function VmetaBrandMark({ className }) {
35
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { className, viewBox: "0 0 64 64", role: "img", "aria-label": "VMETA", focusable: "false", children: [
36
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "M7 10h13l12 31 12-31h13L38 55H26L7 10Z" }),
37
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: "currentColor", d: "m25 10 7 18 7-18h10L32 48 15 10h10Z", opacity: ".42" })
38
+ ] });
39
+ }
40
+ function VmetaCollapseIcon({ collapsed }) {
41
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
42
+ "path",
43
+ {
44
+ d: collapsed ? "m9 5 7 7-7 7" : "m15 5-7 7 7 7",
45
+ fill: "none",
46
+ stroke: "currentColor",
47
+ strokeLinecap: "round",
48
+ strokeLinejoin: "round",
49
+ strokeWidth: "1.8"
50
+ }
51
+ ) });
52
+ }
32
53
  function isMenuItemActive(item, activePath) {
33
54
  if (item.match === "exact") return activePath === item.href;
34
55
  if (item.match === "prefix") return activePath === item.href || activePath.startsWith(`${item.href}/`);
@@ -115,7 +136,7 @@ function VmetaSidebar({
115
136
  const menuItems = collapsed ? visibleGroups.flatMap((group) => group.children) : [];
116
137
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", { className: `vmeta-sidebar ${collapsed ? "is-collapsed" : ""}`, "aria-label": `Dieu huong ${app.appName}`, children: [
117
138
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { className: "vmeta-sidebar__brand", href: app.homeHref ?? "/", "aria-label": `${app.appName} - ${app.appSubtitle}`, children: [
118
- app.logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: app.logoSrc, alt: app.logoAlt ?? "", className: "vmeta-sidebar__logo" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "vmeta-sidebar__mark", "aria-hidden": "true", children: "V" }),
139
+ app.logoSrc ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: app.logoSrc, alt: app.logoAlt ?? "", className: "vmeta-sidebar__logo" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VmetaBrandMark, { className: "vmeta-sidebar__mark" }),
119
140
  !collapsed && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "vmeta-sidebar__brand-copy", children: [
120
141
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: app.appName }),
121
142
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("small", { children: app.appSubtitle })
@@ -158,7 +179,7 @@ function VmetaSidebar({
158
179
  onClick: () => onCollapsedChange?.(!collapsed),
159
180
  "aria-label": collapsed ? "Mo rong thanh dieu huong" : "Thu gon thanh dieu huong",
160
181
  title: collapsed ? "Mo rong menu" : "Thu gon menu",
161
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: collapsed ? "\u203A" : "\u2039" })
182
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VmetaCollapseIcon, { collapsed })
162
183
  }
163
184
  )
164
185
  ] });
@@ -262,6 +283,7 @@ function VmetaAppShell({
262
283
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "vmeta-app-shell__menu-button", onClick: () => setMenuOpen(true), "aria-label": "Mo menu dieu huong", children: "\u2630" }),
263
284
  header.leading,
264
285
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "vmeta-app-shell__title", children: [
286
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "vmeta-app-shell__app-name", children: app.appName }),
265
287
  header.eyebrow && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: header.eyebrow }),
266
288
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: header.title }),
267
289
  header.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: header.description })
@@ -276,6 +298,8 @@ function VmetaAppShell({
276
298
  // Annotate the CommonJS export names for ESM import in node:
277
299
  0 && (module.exports = {
278
300
  VmetaAppShell,
301
+ VmetaBrandMark,
302
+ VmetaCollapseIcon,
279
303
  VmetaSidebar,
280
304
  isMenuItemActive
281
305
  });
package/dist/index.d.cts CHANGED
@@ -41,6 +41,12 @@ type VmetaHeader = {
41
41
  leading?: ReactNode;
42
42
  };
43
43
  type VmetaPermissionResolver = (permission: string | string[]) => boolean;
44
+ declare function VmetaBrandMark({ className }: {
45
+ className?: string;
46
+ }): react_jsx_runtime.JSX.Element;
47
+ declare function VmetaCollapseIcon({ collapsed }: {
48
+ collapsed: boolean;
49
+ }): react_jsx_runtime.JSX.Element;
44
50
  declare function isMenuItemActive(item: VmetaMenuItem, activePath: string): boolean;
45
51
  interface VmetaSidebarProps {
46
52
  app: VmetaAppIdentity;
@@ -72,4 +78,4 @@ interface VmetaAppShellProps {
72
78
  }
73
79
  declare function VmetaAppShell({ app, groups, activePath, header, children, account, sidebarFooter, contentClassName, storageKey, canAccess, onNavigate, }: VmetaAppShellProps): react_jsx_runtime.JSX.Element;
74
80
 
75
- export { type VmetaAccount, type VmetaAppIdentity, VmetaAppShell, type VmetaAppShellProps, type VmetaHeader, type VmetaMenuGroup, type VmetaMenuItem, type VmetaMenuMatch, type VmetaPermissionResolver, VmetaSidebar, type VmetaSidebarProps, isMenuItemActive };
81
+ export { type VmetaAccount, type VmetaAppIdentity, VmetaAppShell, type VmetaAppShellProps, VmetaBrandMark, VmetaCollapseIcon, type VmetaHeader, type VmetaMenuGroup, type VmetaMenuItem, type VmetaMenuMatch, type VmetaPermissionResolver, VmetaSidebar, type VmetaSidebarProps, isMenuItemActive };
package/dist/index.d.ts CHANGED
@@ -41,6 +41,12 @@ type VmetaHeader = {
41
41
  leading?: ReactNode;
42
42
  };
43
43
  type VmetaPermissionResolver = (permission: string | string[]) => boolean;
44
+ declare function VmetaBrandMark({ className }: {
45
+ className?: string;
46
+ }): react_jsx_runtime.JSX.Element;
47
+ declare function VmetaCollapseIcon({ collapsed }: {
48
+ collapsed: boolean;
49
+ }): react_jsx_runtime.JSX.Element;
44
50
  declare function isMenuItemActive(item: VmetaMenuItem, activePath: string): boolean;
45
51
  interface VmetaSidebarProps {
46
52
  app: VmetaAppIdentity;
@@ -72,4 +78,4 @@ interface VmetaAppShellProps {
72
78
  }
73
79
  declare function VmetaAppShell({ app, groups, activePath, header, children, account, sidebarFooter, contentClassName, storageKey, canAccess, onNavigate, }: VmetaAppShellProps): react_jsx_runtime.JSX.Element;
74
80
 
75
- export { type VmetaAccount, type VmetaAppIdentity, VmetaAppShell, type VmetaAppShellProps, type VmetaHeader, type VmetaMenuGroup, type VmetaMenuItem, type VmetaMenuMatch, type VmetaPermissionResolver, VmetaSidebar, type VmetaSidebarProps, isMenuItemActive };
81
+ export { type VmetaAccount, type VmetaAppIdentity, VmetaAppShell, type VmetaAppShellProps, VmetaBrandMark, VmetaCollapseIcon, type VmetaHeader, type VmetaMenuGroup, type VmetaMenuItem, type VmetaMenuMatch, type VmetaPermissionResolver, VmetaSidebar, type VmetaSidebarProps, isMenuItemActive };
package/dist/index.js CHANGED
@@ -4,6 +4,25 @@
4
4
  import { useEffect, useId, useMemo, useState } from "react";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  var allowAllPermissions = () => true;
7
+ function VmetaBrandMark({ className }) {
8
+ return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 64 64", role: "img", "aria-label": "VMETA", focusable: "false", children: [
9
+ /* @__PURE__ */ jsx("path", { fill: "currentColor", d: "M7 10h13l12 31 12-31h13L38 55H26L7 10Z" }),
10
+ /* @__PURE__ */ jsx("path", { fill: "currentColor", d: "m25 10 7 18 7-18h10L32 48 15 10h10Z", opacity: ".42" })
11
+ ] });
12
+ }
13
+ function VmetaCollapseIcon({ collapsed }) {
14
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", width: "18", height: "18", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx(
15
+ "path",
16
+ {
17
+ d: collapsed ? "m9 5 7 7-7 7" : "m15 5-7 7 7 7",
18
+ fill: "none",
19
+ stroke: "currentColor",
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round",
22
+ strokeWidth: "1.8"
23
+ }
24
+ ) });
25
+ }
7
26
  function isMenuItemActive(item, activePath) {
8
27
  if (item.match === "exact") return activePath === item.href;
9
28
  if (item.match === "prefix") return activePath === item.href || activePath.startsWith(`${item.href}/`);
@@ -90,7 +109,7 @@ function VmetaSidebar({
90
109
  const menuItems = collapsed ? visibleGroups.flatMap((group) => group.children) : [];
91
110
  return /* @__PURE__ */ jsxs("aside", { className: `vmeta-sidebar ${collapsed ? "is-collapsed" : ""}`, "aria-label": `Dieu huong ${app.appName}`, children: [
92
111
  /* @__PURE__ */ jsxs("a", { className: "vmeta-sidebar__brand", href: app.homeHref ?? "/", "aria-label": `${app.appName} - ${app.appSubtitle}`, children: [
93
- app.logoSrc ? /* @__PURE__ */ jsx("img", { src: app.logoSrc, alt: app.logoAlt ?? "", className: "vmeta-sidebar__logo" }) : /* @__PURE__ */ jsx("span", { className: "vmeta-sidebar__mark", "aria-hidden": "true", children: "V" }),
112
+ app.logoSrc ? /* @__PURE__ */ jsx("img", { src: app.logoSrc, alt: app.logoAlt ?? "", className: "vmeta-sidebar__logo" }) : /* @__PURE__ */ jsx(VmetaBrandMark, { className: "vmeta-sidebar__mark" }),
94
113
  !collapsed && /* @__PURE__ */ jsxs("span", { className: "vmeta-sidebar__brand-copy", children: [
95
114
  /* @__PURE__ */ jsx("strong", { children: app.appName }),
96
115
  /* @__PURE__ */ jsx("small", { children: app.appSubtitle })
@@ -133,7 +152,7 @@ function VmetaSidebar({
133
152
  onClick: () => onCollapsedChange?.(!collapsed),
134
153
  "aria-label": collapsed ? "Mo rong thanh dieu huong" : "Thu gon thanh dieu huong",
135
154
  title: collapsed ? "Mo rong menu" : "Thu gon menu",
136
- children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: collapsed ? "\u203A" : "\u2039" })
155
+ children: /* @__PURE__ */ jsx(VmetaCollapseIcon, { collapsed })
137
156
  }
138
157
  )
139
158
  ] });
@@ -237,6 +256,7 @@ function VmetaAppShell({
237
256
  /* @__PURE__ */ jsx("button", { type: "button", className: "vmeta-app-shell__menu-button", onClick: () => setMenuOpen(true), "aria-label": "Mo menu dieu huong", children: "\u2630" }),
238
257
  header.leading,
239
258
  /* @__PURE__ */ jsxs("div", { className: "vmeta-app-shell__title", children: [
259
+ /* @__PURE__ */ jsx("p", { className: "vmeta-app-shell__app-name", children: app.appName }),
240
260
  header.eyebrow && /* @__PURE__ */ jsx("p", { children: header.eyebrow }),
241
261
  /* @__PURE__ */ jsx("h1", { children: header.title }),
242
262
  header.description && /* @__PURE__ */ jsx("span", { children: header.description })
@@ -250,6 +270,8 @@ function VmetaAppShell({
250
270
  }
251
271
  export {
252
272
  VmetaAppShell,
273
+ VmetaBrandMark,
274
+ VmetaCollapseIcon,
253
275
  VmetaSidebar,
254
276
  isMenuItemActive
255
277
  };
package/dist/styles.css CHANGED
@@ -7,7 +7,9 @@
7
7
  .vmeta-app-shell__header { position: sticky; top: 0; z-index: var(--z-header, 40); min-height: 82px; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 14px var(--page-gutter-desktop, 28px); border-bottom: 1px solid var(--color-border); background: color-mix(in srgb, var(--color-surface) 94%, transparent); box-shadow: var(--shadow-sm); backdrop-filter: blur(16px); }
8
8
  .vmeta-app-shell__header-copy { min-width: 0; display: flex; align-items: center; gap: 12px; }
9
9
  .vmeta-app-shell__title { min-width: 0; }
10
+ .vmeta-app-shell__app-name { margin: 0 0 2px; color: var(--color-primary); font-size: 10px; font-weight: 800; letter-spacing: .12em; line-height: 1.2; text-transform: uppercase; }
10
11
  .vmeta-app-shell__title p { margin: 0; color: var(--color-primary); font-size: 10px; font-weight: 750; letter-spacing: .13em; text-transform: uppercase; }
12
+ .vmeta-app-shell__title .vmeta-app-shell__app-name { margin-bottom: 2px; font-size: 9px; font-weight: 800; }
11
13
  .vmeta-app-shell__title h1 { margin: 3px 0 0; color: var(--color-ink); font-size: clamp(20px, 2.5vw, 26px); line-height: 1.2; letter-spacing: -.035em; }
12
14
  .vmeta-app-shell__title span { display: block; max-width: 740px; margin-top: 4px; overflow: hidden; color: var(--color-muted); font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
13
15
  .vmeta-app-shell__header-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
@@ -15,10 +17,10 @@
15
17
  .vmeta-app-shell__content { min-width: 0; padding: var(--page-gutter-tablet, 20px) var(--page-gutter-desktop, 28px) 48px; }
16
18
  .vmeta-app-shell__overlay { display: none; }
17
19
  .vmeta-sidebar { height: 100%; min-height: 0; display: flex; flex-direction: column; overflow: hidden; border-right: 1px solid var(--color-border); color: var(--color-ink); background: var(--color-surface); box-shadow: var(--shadow-md); }
18
- .vmeta-sidebar__brand { min-height: 82px; display: flex; align-items: center; gap: 11px; margin: 10px; padding: 10px 12px; border: 1px solid var(--color-border); border-radius: 20px; color: inherit; text-decoration: none; background: var(--color-surface); box-shadow: 0 5px 18px rgb(7 19 13 / 5%); transition: border-color var(--motion-fast), box-shadow var(--motion-fast), transform var(--motion-fast); }
20
+ .vmeta-sidebar__brand { min-height: 82px; display: flex; align-items: center; justify-content: flex-start; gap: 11px; margin: 10px; padding: 10px 12px; border: 1px solid var(--color-border); border-radius: 20px; color: inherit; text-decoration: none; background: var(--color-surface); box-shadow: 0 5px 18px rgb(7 19 13 / 5%); transition: border-color var(--motion-fast), box-shadow var(--motion-fast), transform var(--motion-fast); }
19
21
  .vmeta-sidebar__brand:hover { border-color: color-mix(in srgb, var(--color-primary) 25%, var(--color-border)); box-shadow: var(--shadow-sm); transform: translateY(-1px); }
20
22
  .vmeta-sidebar__logo { width: 42px; height: 42px; flex: 0 0 42px; object-fit: contain; }
21
- .vmeta-sidebar__mark { width: 42px; height: 42px; flex: 0 0 42px; display: grid; place-items: center; color: var(--color-primary); font-size: 34px; font-weight: 850; letter-spacing: -.13em; transform: translateX(-2px); }
23
+ .vmeta-sidebar__mark { width: 42px; height: 42px; flex: 0 0 42px; display: block; color: var(--color-primary); }
22
24
  .vmeta-sidebar__brand-copy { min-width: 0; line-height: 1.15; }
23
25
  .vmeta-sidebar__brand-copy strong, .vmeta-sidebar__brand-copy small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
24
26
  .vmeta-sidebar__brand-copy strong { color: var(--color-primary); font-size: 16px; font-weight: 800; letter-spacing: -.025em; }
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@leduchai/vmeta-ui-shell",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Application shell, sidebar, menu va header dung chung cua VMETA.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
- "sideEffects": ["./dist/styles.css"],
7
+ "sideEffects": [
8
+ "./dist/styles.css"
9
+ ],
8
10
  "main": "./dist/index.cjs",
9
11
  "module": "./dist/index.js",
10
12
  "types": "./dist/index.d.ts",
@@ -16,12 +18,15 @@
16
18
  },
17
19
  "./styles.css": "./dist/styles.css"
18
20
  },
19
- "files": ["dist", "README.md"],
21
+ "files": [
22
+ "dist",
23
+ "README.md"
24
+ ],
20
25
  "scripts": {
21
26
  "build": "tsup src/index.tsx --format esm,cjs --dts --clean --external react --external react-dom && node ../../scripts/copy-file.mjs src/styles.css dist/styles.css"
22
27
  },
23
28
  "dependencies": {
24
- "@leduchai/vmeta-ui-tokens": "0.1.5"
29
+ "@leduchai/vmeta-ui-tokens": "0.1.7"
25
30
  },
26
31
  "peerDependencies": {
27
32
  "react": ">=18 <20",