@yugnex/nexui 2.0.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 (138) hide show
  1. package/LICENSE +59 -0
  2. package/css/nexui-base.css +157 -0
  3. package/css/nexui-icons.css +86 -0
  4. package/css/nexui-tokens.css +113 -0
  5. package/css/nexui.css +16 -0
  6. package/dist/assets/geometry.d.ts +98 -0
  7. package/dist/assets/geometry.d.ts.map +1 -0
  8. package/dist/assets/geometry.js +114 -0
  9. package/dist/assets/geometry.js.map +1 -0
  10. package/dist/assets/typography.d.ts +3 -0
  11. package/dist/assets/typography.d.ts.map +1 -0
  12. package/dist/assets/typography.js +178 -0
  13. package/dist/assets/typography.js.map +1 -0
  14. package/dist/core/compiler.d.ts +30 -0
  15. package/dist/core/compiler.d.ts.map +1 -0
  16. package/dist/core/compiler.js +124 -0
  17. package/dist/core/compiler.js.map +1 -0
  18. package/dist/core/cx.d.ts +7 -0
  19. package/dist/core/cx.d.ts.map +1 -0
  20. package/dist/core/cx.js +34 -0
  21. package/dist/core/cx.js.map +1 -0
  22. package/dist/core/matrix.d.ts +118 -0
  23. package/dist/core/matrix.d.ts.map +1 -0
  24. package/dist/core/matrix.js +180 -0
  25. package/dist/core/matrix.js.map +1 -0
  26. package/dist/index.d.ts +27 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +74 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/primitives/avatar.d.ts +8 -0
  31. package/dist/primitives/avatar.d.ts.map +1 -0
  32. package/dist/primitives/avatar.js +146 -0
  33. package/dist/primitives/avatar.js.map +1 -0
  34. package/dist/primitives/badge.d.ts +8 -0
  35. package/dist/primitives/badge.d.ts.map +1 -0
  36. package/dist/primitives/badge.js +88 -0
  37. package/dist/primitives/badge.js.map +1 -0
  38. package/dist/primitives/button.d.ts +10 -0
  39. package/dist/primitives/button.d.ts.map +1 -0
  40. package/dist/primitives/button.js +137 -0
  41. package/dist/primitives/button.js.map +1 -0
  42. package/dist/primitives/checkbox.d.ts +13 -0
  43. package/dist/primitives/checkbox.d.ts.map +1 -0
  44. package/dist/primitives/checkbox.js +107 -0
  45. package/dist/primitives/checkbox.js.map +1 -0
  46. package/dist/primitives/input.d.ts +14 -0
  47. package/dist/primitives/input.d.ts.map +1 -0
  48. package/dist/primitives/input.js +177 -0
  49. package/dist/primitives/input.js.map +1 -0
  50. package/dist/primitives/panel.d.ts +9 -0
  51. package/dist/primitives/panel.d.ts.map +1 -0
  52. package/dist/primitives/panel.js +101 -0
  53. package/dist/primitives/panel.js.map +1 -0
  54. package/dist/primitives/progress.d.ts +8 -0
  55. package/dist/primitives/progress.d.ts.map +1 -0
  56. package/dist/primitives/progress.js +105 -0
  57. package/dist/primitives/progress.js.map +1 -0
  58. package/dist/primitives/separator.d.ts +8 -0
  59. package/dist/primitives/separator.d.ts.map +1 -0
  60. package/dist/primitives/separator.js +69 -0
  61. package/dist/primitives/separator.js.map +1 -0
  62. package/dist/primitives/skeleton.d.ts +8 -0
  63. package/dist/primitives/skeleton.d.ts.map +1 -0
  64. package/dist/primitives/skeleton.js +61 -0
  65. package/dist/primitives/skeleton.js.map +1 -0
  66. package/dist/primitives/spinner.d.ts +8 -0
  67. package/dist/primitives/spinner.d.ts.map +1 -0
  68. package/dist/primitives/spinner.js +64 -0
  69. package/dist/primitives/spinner.js.map +1 -0
  70. package/dist/primitives/status-ring.d.ts +8 -0
  71. package/dist/primitives/status-ring.d.ts.map +1 -0
  72. package/dist/primitives/status-ring.js +101 -0
  73. package/dist/primitives/status-ring.js.map +1 -0
  74. package/dist/primitives/switch.d.ts +12 -0
  75. package/dist/primitives/switch.d.ts.map +1 -0
  76. package/dist/primitives/switch.js +124 -0
  77. package/dist/primitives/switch.js.map +1 -0
  78. package/dist/primitives/text-stream.d.ts +23 -0
  79. package/dist/primitives/text-stream.d.ts.map +1 -0
  80. package/dist/primitives/text-stream.js +167 -0
  81. package/dist/primitives/text-stream.js.map +1 -0
  82. package/dist/tokens/colors.d.ts +127 -0
  83. package/dist/tokens/colors.d.ts.map +1 -0
  84. package/dist/tokens/colors.js +135 -0
  85. package/dist/tokens/colors.js.map +1 -0
  86. package/dist/tokens/motion.d.ts +37 -0
  87. package/dist/tokens/motion.d.ts.map +1 -0
  88. package/dist/tokens/motion.js +93 -0
  89. package/dist/tokens/motion.js.map +1 -0
  90. package/dist/tokens/shadows.d.ts +34 -0
  91. package/dist/tokens/shadows.d.ts.map +1 -0
  92. package/dist/tokens/shadows.js +45 -0
  93. package/dist/tokens/shadows.js.map +1 -0
  94. package/dist/tokens/spacing.d.ts +69 -0
  95. package/dist/tokens/spacing.d.ts.map +1 -0
  96. package/dist/tokens/spacing.js +71 -0
  97. package/dist/tokens/spacing.js.map +1 -0
  98. package/dist/tokens/type.d.ts +166 -0
  99. package/dist/tokens/type.d.ts.map +1 -0
  100. package/dist/tokens/type.js +215 -0
  101. package/dist/tokens/type.js.map +1 -0
  102. package/fonts/NexuiIcons.woff2 +0 -0
  103. package/fonts/NexuiMono-Regular.otf +0 -0
  104. package/fonts/NexuiMono-Regular.woff2 +0 -0
  105. package/fonts/NexuiSans-Bold.otf +0 -0
  106. package/fonts/NexuiSans-Bold.woff2 +0 -0
  107. package/fonts/NexuiSans-Medium.otf +0 -0
  108. package/fonts/NexuiSans-Medium.woff2 +0 -0
  109. package/fonts/NexuiSans-Regular.otf +0 -0
  110. package/fonts/NexuiSans-Regular.woff2 +0 -0
  111. package/native/Cargo.toml +16 -0
  112. package/native/src/lib.rs +127 -0
  113. package/nexui-utils.css +485 -0
  114. package/package.json +58 -0
  115. package/src/assets/geometry.ts +144 -0
  116. package/src/assets/typography.ts +184 -0
  117. package/src/core/compiler.ts +139 -0
  118. package/src/core/cx.ts +50 -0
  119. package/src/core/matrix.ts +195 -0
  120. package/src/index.ts +78 -0
  121. package/src/primitives/avatar.ts +159 -0
  122. package/src/primitives/badge.ts +98 -0
  123. package/src/primitives/button.ts +149 -0
  124. package/src/primitives/checkbox.ts +113 -0
  125. package/src/primitives/input.ts +187 -0
  126. package/src/primitives/panel.ts +111 -0
  127. package/src/primitives/progress.ts +112 -0
  128. package/src/primitives/separator.ts +73 -0
  129. package/src/primitives/skeleton.ts +68 -0
  130. package/src/primitives/spinner.ts +71 -0
  131. package/src/primitives/status-ring.ts +109 -0
  132. package/src/primitives/switch.ts +134 -0
  133. package/src/primitives/text-stream.ts +187 -0
  134. package/src/tokens/colors.ts +149 -0
  135. package/src/tokens/motion.ts +97 -0
  136. package/src/tokens/shadows.ts +58 -0
  137. package/src/tokens/spacing.ts +79 -0
  138. package/src/tokens/type.ts +224 -0
@@ -0,0 +1,105 @@
1
+ // @yugnex/nexui — NexProgress Web Component
2
+ // Linear and circular progress indicators.
3
+ // Attributes:
4
+ // value: 0-100 (default 0). Omit for indeterminate.
5
+ // variant: linear | circular (default: linear)
6
+ // size: sm | md | lg
7
+ // color: accent | live | success | error | warning (default: accent)
8
+ // label: string — accessible label
9
+ // show-value: boolean — renders the percentage text
10
+ import { nexui_compiler } from "../core/compiler";
11
+ export class NexProgress extends HTMLElement {
12
+ static get observedAttributes() {
13
+ return ["value", "variant", "size", "color", "label", "show-value"];
14
+ }
15
+ constructor() {
16
+ super();
17
+ this.attachShadow({ mode: "open" });
18
+ }
19
+ connectedCallback() { this.render(); }
20
+ attributeChangedCallback() { this.render(); }
21
+ render() {
22
+ if (!this.shadowRoot)
23
+ return;
24
+ const rawVal = this.getAttribute("value");
25
+ const value = rawVal !== null ? Math.min(100, Math.max(0, parseFloat(rawVal))) : null;
26
+ const variant = this.getAttribute("variant") ?? "linear";
27
+ const size = this.getAttribute("size") ?? "md";
28
+ const color = this.getAttribute("color") ?? "accent";
29
+ const label = this.getAttribute("label") ?? "Progress";
30
+ const showValue = this.getAttribute("show-value") === "true";
31
+ const indeterminate = value === null;
32
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
33
+ const colorMap = {
34
+ accent: "var(--nx-accent, #E89010)",
35
+ live: "var(--nx-live, #0FD4C6)",
36
+ success: "var(--nx-success, #22C55E)",
37
+ error: "var(--nx-error, #EF4444)",
38
+ warning: "var(--nx-warning, #EAB308)",
39
+ };
40
+ const fillColor = colorMap[color] ?? colorMap.accent;
41
+ if (variant === "circular") {
42
+ const szMap = { sm: 32, md: 48, lg: 64 };
43
+ const sz = szMap[size] ?? 48;
44
+ const r = (sz / 2) - 4;
45
+ const circ = 2 * Math.PI * r;
46
+ const offset = indeterminate ? circ * 0.25 : circ - (value / 100) * circ;
47
+ this.shadowRoot.innerHTML = `
48
+ <style>
49
+ ${themeCSS}
50
+ :host { display: inline-flex; align-items: center; gap: 8px; }
51
+ .arc {
52
+ transition: stroke-dashoffset 400ms cubic-bezier(0,0,0.2,1);
53
+ transform-origin: center;
54
+ transform: rotate(-90deg);
55
+ }
56
+ .indeterminate { animation: nx-spin-arc 1.4s linear infinite; }
57
+ @keyframes nx-spin-arc { to { transform: rotate(270deg); } }
58
+ .val { font-family: var(--nx-font-mono, monospace); font-size: ${Math.round(sz * 0.22)}px; fill: var(--nx-text, #E6EDF3); }
59
+ </style>
60
+ <svg width="${sz}" height="${sz}" viewBox="0 0 ${sz} ${sz}" aria-label="${label}${value !== null ? `: ${value}%` : ""}" role="progressbar" aria-valuenow="${value ?? ""}" aria-valuemin="0" aria-valuemax="100">
61
+ <circle cx="${sz / 2}" cy="${sz / 2}" r="${r}" fill="none" stroke="var(--nx-border, rgba(255,255,255,0.08))" stroke-width="4"/>
62
+ <circle class="arc${indeterminate ? " indeterminate" : ""}" cx="${sz / 2}" cy="${sz / 2}" r="${r}" fill="none"
63
+ stroke="${fillColor}" stroke-width="4" stroke-linecap="round"
64
+ stroke-dasharray="${circ}" stroke-dashoffset="${offset}"/>
65
+ ${showValue && !indeterminate ? `<text class="val" x="${sz / 2}" y="${sz / 2 + sz * 0.08}" text-anchor="middle" font-weight="600">${Math.round(value)}%</text>` : ""}
66
+ </svg>
67
+ ${showValue && !indeterminate ? "" : ""}
68
+ `;
69
+ }
70
+ else {
71
+ const hMap = { sm: "3px", md: "5px", lg: "8px" };
72
+ const h = hMap[size] ?? "5px";
73
+ this.shadowRoot.innerHTML = `
74
+ <style>
75
+ ${themeCSS}
76
+ :host { display: block; }
77
+ .track {
78
+ width: 100%;
79
+ height: ${h};
80
+ background: var(--nx-border, rgba(255,255,255,0.08));
81
+ border-radius: 9999px;
82
+ overflow: hidden;
83
+ }
84
+ .fill {
85
+ height: 100%;
86
+ background: ${fillColor};
87
+ border-radius: 9999px;
88
+ transition: width 400ms cubic-bezier(0,0,0.2,1);
89
+ ${indeterminate ? `animation: nx-indeterminate 1.6s ease-in-out infinite; width: 40%;` : `width: ${value}%;`}
90
+ }
91
+ .label-row { display: flex; justify-content: space-between; margin-bottom: 6px; font-family: var(--nx-font-sans, system-ui); font-size: 11px; color: var(--nx-text-3, #6E7681); }
92
+ @keyframes nx-indeterminate {
93
+ 0% { transform: translateX(-100%); }
94
+ 100% { transform: translateX(350%); }
95
+ }
96
+ </style>
97
+ <div role="progressbar" aria-label="${label}" aria-valuenow="${value ?? ""}" aria-valuemin="0" aria-valuemax="100">
98
+ ${label || showValue ? `<div class="label-row"><span>${label}</span>${showValue && !indeterminate ? `<span>${Math.round(value)}%</span>` : ""}</div>` : ""}
99
+ <div class="track"><div class="fill"></div></div>
100
+ </div>
101
+ `;
102
+ }
103
+ }
104
+ }
105
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/primitives/progress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare class NexSeparator extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ constructor();
4
+ connectedCallback(): void;
5
+ attributeChangedCallback(): void;
6
+ private render;
7
+ }
8
+ //# sourceMappingURL=separator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../src/primitives/separator.ts"],"names":[],"mappings":"AASA,qBAAa,YAAa,SAAQ,WAAW;IAC3C,MAAM,KAAK,kBAAkB,aAE5B;;IAOD,iBAAiB;IACjB,wBAAwB;IAExB,OAAO,CAAC,MAAM;CAkDf"}
@@ -0,0 +1,69 @@
1
+ // @yugnex/nexui — NexSeparator Web Component
2
+ // Horizontal or vertical divider line.
3
+ // Attributes:
4
+ // orientation: horizontal | vertical (default: horizontal)
5
+ // variant: default | strong | muted (default: default)
6
+ // label: string — centered label text
7
+ import { nexui_compiler } from "../core/compiler";
8
+ export class NexSeparator extends HTMLElement {
9
+ static get observedAttributes() {
10
+ return ["orientation", "variant", "label"];
11
+ }
12
+ constructor() {
13
+ super();
14
+ this.attachShadow({ mode: "open" });
15
+ }
16
+ connectedCallback() { this.render(); }
17
+ attributeChangedCallback() { this.render(); }
18
+ render() {
19
+ if (!this.shadowRoot)
20
+ return;
21
+ const orientation = this.getAttribute("orientation") ?? "horizontal";
22
+ const variant = this.getAttribute("variant") ?? "default";
23
+ const label = this.getAttribute("label") ?? "";
24
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
25
+ const colorMap = {
26
+ default: "var(--nx-border, rgba(255,255,255,0.08))",
27
+ strong: "var(--nx-border-strong, rgba(255,255,255,0.16))",
28
+ muted: "rgba(255,255,255,0.04)",
29
+ };
30
+ const borderColor = colorMap[variant] ?? colorMap.default;
31
+ if (orientation === "vertical") {
32
+ this.shadowRoot.innerHTML = `
33
+ <style>
34
+ ${themeCSS}
35
+ :host { display: inline-block; width: 1px; align-self: stretch; }
36
+ .line { width: 1px; height: 100%; background: ${borderColor}; }
37
+ </style>
38
+ <div class="line" role="separator" aria-orientation="vertical"></div>
39
+ `;
40
+ }
41
+ else if (label) {
42
+ this.shadowRoot.innerHTML = `
43
+ <style>
44
+ ${themeCSS}
45
+ :host { display: block; }
46
+ .row { display: flex; align-items: center; gap: 12px; }
47
+ .line { flex: 1; height: 1px; background: ${borderColor}; }
48
+ .text { font-family: var(--nx-font-sans, system-ui); font-size: 11px; font-weight: 500; color: var(--nx-text-4, #484F58); letter-spacing: 0.06em; text-transform: uppercase; white-space: nowrap; }
49
+ </style>
50
+ <div class="row" role="separator">
51
+ <div class="line"></div>
52
+ <span class="text">${label}</span>
53
+ <div class="line"></div>
54
+ </div>
55
+ `;
56
+ }
57
+ else {
58
+ this.shadowRoot.innerHTML = `
59
+ <style>
60
+ ${themeCSS}
61
+ :host { display: block; }
62
+ .line { width: 100%; height: 1px; background: ${borderColor}; }
63
+ </style>
64
+ <div class="line" role="separator" aria-orientation="horizontal"></div>
65
+ `;
66
+ }
67
+ }
68
+ }
69
+ //# sourceMappingURL=separator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.js","sourceRoot":"","sources":["../../src/primitives/separator.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,uCAAuC;AACvC,cAAc;AACd,6DAA6D;AAC7D,6DAA6D;AAC7D,8CAA8C;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,MAAM,KAAK,kBAAkB;QAC3B,OAAO,CAAC,aAAa,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iBAAiB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtC,wBAAwB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAErC,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC;QACrE,MAAM,OAAO,GAAO,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC;QAC9D,MAAM,KAAK,GAAS,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,QAAQ,GAAM,cAAc,CAAC,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;QAEzF,MAAM,QAAQ,GAA2B;YACvC,OAAO,EAAE,0CAA0C;YACnD,MAAM,EAAG,iDAAiD;YAC1D,KAAK,EAAI,wBAAwB;SAClC,CAAC;QACF,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC;QAE1D,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;YAC/B,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;;YAEtB,QAAQ;;0DAEsC,WAAW;;;OAG9D,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;;YAEtB,QAAQ;;;sDAGkC,WAAW;;;;;+BAKlC,KAAK;;;OAG7B,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;;YAEtB,QAAQ;;0DAEsC,WAAW;;;OAG9D,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export declare class NexSkeleton extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ constructor();
4
+ connectedCallback(): void;
5
+ attributeChangedCallback(): void;
6
+ private render;
7
+ }
8
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../src/primitives/skeleton.ts"],"names":[],"mappings":"AAWA,qBAAa,WAAY,SAAQ,WAAW;IAC1C,MAAM,KAAK,kBAAkB,aAE5B;;IAOD,iBAAiB;IACjB,wBAAwB;IAExB,OAAO,CAAC,MAAM;CA2Cf"}
@@ -0,0 +1,61 @@
1
+ // @yugnex/nexui — NexSkeleton Web Component
2
+ // Loading placeholder with shimmer animation.
3
+ // Attributes:
4
+ // variant: text | circle | rect (default: rect)
5
+ // width: CSS value (default: 100%)
6
+ // height: CSS value (default: 16px for text, 40px for rect)
7
+ // lines: number — for text variant, renders N stacked lines
8
+ // animate: boolean (default: true)
9
+ import { nexui_compiler } from "../core/compiler";
10
+ export class NexSkeleton extends HTMLElement {
11
+ static get observedAttributes() {
12
+ return ["variant", "width", "height", "lines", "animate"];
13
+ }
14
+ constructor() {
15
+ super();
16
+ this.attachShadow({ mode: "open" });
17
+ }
18
+ connectedCallback() { this.render(); }
19
+ attributeChangedCallback() { this.render(); }
20
+ render() {
21
+ if (!this.shadowRoot)
22
+ return;
23
+ const variant = this.getAttribute("variant") ?? "rect";
24
+ const width = this.getAttribute("width") ?? "100%";
25
+ const animate = this.getAttribute("animate") !== "false";
26
+ const lines = Math.max(1, parseInt(this.getAttribute("lines") ?? "1", 10));
27
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
28
+ let height = this.getAttribute("height");
29
+ if (!height) {
30
+ height = variant === "text" ? "12px" : variant === "circle" ? width : "40px";
31
+ }
32
+ const baseStyle = `
33
+ background: linear-gradient(
34
+ 90deg,
35
+ var(--nx-bg-elevated, #1C2128) 25%,
36
+ var(--nx-bg-overlay, #21262D) 50%,
37
+ var(--nx-bg-elevated, #1C2128) 75%
38
+ );
39
+ background-size: 200% 100%;
40
+ ${animate ? "animation: nx-shimmer 1.8s ease-in-out infinite;" : ""}
41
+ border-radius: ${variant === "circle" ? "50%" : variant === "text" ? "4px" : "6px"};
42
+ `;
43
+ if (variant === "text" && lines > 1) {
44
+ const lineEls = Array.from({ length: lines }, (_, i) => {
45
+ const w = i === lines - 1 ? "65%" : "100%";
46
+ return `<div style="${baseStyle} width:${w}; height:${height}; margin-bottom:${i < lines - 1 ? "8px" : "0"};"></div>`;
47
+ }).join("");
48
+ this.shadowRoot.innerHTML = `
49
+ <style>${themeCSS} :host{display:block;} @keyframes nx-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}</style>
50
+ <div role="status" aria-label="Loading..." style="width:${width};">${lineEls}</div>
51
+ `;
52
+ }
53
+ else {
54
+ this.shadowRoot.innerHTML = `
55
+ <style>${themeCSS} :host{display:block;} @keyframes nx-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}</style>
56
+ <div role="status" aria-label="Loading..." style="${baseStyle} width:${width}; height:${height};"></div>
57
+ `;
58
+ }
59
+ }
60
+ }
61
+ //# sourceMappingURL=skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.js","sourceRoot":"","sources":["../../src/primitives/skeleton.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,8CAA8C;AAC9C,cAAc;AACd,kDAAkD;AAClD,uCAAuC;AACvC,+DAA+D;AAC/D,gEAAgE;AAChE,qCAAqC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC1C,MAAM,KAAK,kBAAkB;QAC3B,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iBAAiB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtC,wBAAwB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAErC,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC;QACvD,MAAM,KAAK,GAAK,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC;QACzD,MAAM,KAAK,GAAK,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;QAEtF,IAAI,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/E,CAAC;QAED,MAAM,SAAS,GAAG;;;;;;;;QAQd,OAAO,CAAC,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC,EAAE;uBAClD,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;KACnF,CAAC;QAEF,IAAI,OAAO,KAAK,MAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACrD,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC3C,OAAO,eAAe,SAAS,UAAU,CAAC,YAAY,MAAM,mBAAmB,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC;YACxH,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEZ,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;iBACjB,QAAQ;kEACyC,KAAK,MAAM,OAAO;OAC7E,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;iBACjB,QAAQ;4DACmC,SAAS,UAAU,KAAK,YAAY,MAAM;OAC/F,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export declare class NexSpinner extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ constructor();
4
+ connectedCallback(): void;
5
+ attributeChangedCallback(): void;
6
+ private render;
7
+ }
8
+ //# sourceMappingURL=spinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/primitives/spinner.ts"],"names":[],"mappings":"AASA,qBAAa,UAAW,SAAQ,WAAW;IACzC,MAAM,KAAK,kBAAkB,aAE5B;;IAOD,iBAAiB;IACjB,wBAAwB;IAExB,OAAO,CAAC,MAAM;CAgDf"}
@@ -0,0 +1,64 @@
1
+ // @yugnex/nexui — NexSpinner Web Component
2
+ // Loading spinner. Lightweight — just CSS animation, no JS after render.
3
+ // Attributes:
4
+ // size: xs | sm | md | lg | xl (default: md)
5
+ // color: accent | live | success | error | muted (default: accent)
6
+ // label: accessible label (default: "Loading")
7
+ import { nexui_compiler } from "../core/compiler";
8
+ export class NexSpinner extends HTMLElement {
9
+ static get observedAttributes() {
10
+ return ["size", "color", "label"];
11
+ }
12
+ constructor() {
13
+ super();
14
+ this.attachShadow({ mode: "open" });
15
+ }
16
+ connectedCallback() { this.render(); }
17
+ attributeChangedCallback() { this.render(); }
18
+ render() {
19
+ if (!this.shadowRoot)
20
+ return;
21
+ const size = this.getAttribute("size") ?? "md";
22
+ const color = this.getAttribute("color") ?? "accent";
23
+ const label = this.getAttribute("label") ?? "Loading";
24
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
25
+ const szMap = {
26
+ xs: { px: 12, sw: 1.5 },
27
+ sm: { px: 16, sw: 2 },
28
+ md: { px: 24, sw: 2.5 },
29
+ lg: { px: 32, sw: 3 },
30
+ xl: { px: 48, sw: 3.5 },
31
+ };
32
+ const { px, sw } = szMap[size] ?? szMap.md;
33
+ const colorMap = {
34
+ accent: "var(--nx-accent, #E89010)",
35
+ live: "var(--nx-live, #0FD4C6)",
36
+ success: "var(--nx-success, #22C55E)",
37
+ error: "var(--nx-error, #EF4444)",
38
+ muted: "var(--nx-text-4, #484F58)",
39
+ };
40
+ const spinColor = colorMap[color] ?? colorMap.accent;
41
+ this.shadowRoot.innerHTML = `
42
+ <style>
43
+ ${themeCSS}
44
+ :host { display: inline-flex; align-items: center; justify-content: center; }
45
+ .ring {
46
+ width: ${px}px;
47
+ height: ${px}px;
48
+ border-radius: 50%;
49
+ border: ${sw}px solid rgba(255,255,255,0.08);
50
+ border-top-color: ${spinColor};
51
+ animation: nx-spin 700ms linear infinite;
52
+ }
53
+ @media (prefers-reduced-motion: reduce) {
54
+ .ring { animation-duration: 2s; }
55
+ }
56
+ @keyframes nx-spin { to { transform: rotate(360deg); } }
57
+ </style>
58
+ <div class="ring" role="status" aria-label="${label}">
59
+ <span style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0)">${label}</span>
60
+ </div>
61
+ `;
62
+ }
63
+ }
64
+ //# sourceMappingURL=spinner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/primitives/spinner.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,yEAAyE;AACzE,cAAc;AACd,gDAAgD;AAChD,qEAAqE;AACrE,iDAAiD;AAEjD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,OAAO,UAAW,SAAQ,WAAW;IACzC,MAAM,KAAK,kBAAkB;QAC3B,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iBAAiB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtC,wBAAwB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAErC,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,MAAM,IAAI,GAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;QAClD,MAAM,KAAK,GAAK,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC;QACvD,MAAM,KAAK,GAAK,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;QACxD,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;QAEtF,MAAM,KAAK,GAA+C;YACxD,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE;YACvB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE;YACrB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE;YACvB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE;YACrB,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE;SACxB,CAAC;QACF,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAE3C,MAAM,QAAQ,GAA2B;YACvC,MAAM,EAAG,2BAA2B;YACpC,IAAI,EAAK,yBAAyB;YAClC,OAAO,EAAE,4BAA4B;YACrC,KAAK,EAAI,0BAA0B;YACnC,KAAK,EAAI,2BAA2B;SACrC,CAAC;QACF,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC;QAErD,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;;UAEtB,QAAQ;;;mBAGC,EAAE;oBACD,EAAE;;oBAEF,EAAE;8BACQ,SAAS;;;;;;;;oDAQa,KAAK;kGACyC,KAAK;;KAElG,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export declare class NexStatusRing extends HTMLElement {
2
+ static get observedAttributes(): string[];
3
+ constructor();
4
+ connectedCallback(): void;
5
+ attributeChangedCallback(): void;
6
+ private render;
7
+ }
8
+ //# sourceMappingURL=status-ring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-ring.d.ts","sourceRoot":"","sources":["../../src/primitives/status-ring.ts"],"names":[],"mappings":"AAMA,qBAAa,aAAc,SAAQ,WAAW;IAC5C,MAAM,KAAK,kBAAkB,aAE5B;;IAOD,iBAAiB;IAIjB,wBAAwB;IAIxB,OAAO,CAAC,MAAM;CAoFf"}
@@ -0,0 +1,101 @@
1
+ // @yugnex/nexui — NexStatusRing Web Component
2
+ // Circular progress ring with animated entry.
3
+ // Attributes: score (0-100), label, color, size
4
+ import { nexui_compiler } from "../core/compiler";
5
+ export class NexStatusRing extends HTMLElement {
6
+ static get observedAttributes() {
7
+ return ["score", "label", "color", "size"];
8
+ }
9
+ constructor() {
10
+ super();
11
+ this.attachShadow({ mode: "open" });
12
+ }
13
+ connectedCallback() {
14
+ this.render();
15
+ }
16
+ attributeChangedCallback() {
17
+ this.render();
18
+ }
19
+ render() {
20
+ if (!this.shadowRoot)
21
+ return;
22
+ const score = Math.min(100, Math.max(0, parseInt(this.getAttribute("score") ?? "0", 10)));
23
+ const label = this.getAttribute("label") ?? "METRIC";
24
+ const color = this.getAttribute("color") ?? "var(--nx-accent, #E89010)";
25
+ const size = Math.max(40, parseInt(this.getAttribute("size") ?? "80", 10));
26
+ const cx = size / 2;
27
+ const cy = size / 2;
28
+ const radius = (size / 2) - (size * 0.075);
29
+ const sw = size * 0.075;
30
+ const circumference = 2 * Math.PI * radius;
31
+ const targetOffset = circumference - (score / 100) * circumference;
32
+ const fontSize = Math.round(size * 0.175);
33
+ const labelSize = Math.round(size * 0.08);
34
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
35
+ // Key technique: render at full offset (empty ring), then in the next frame
36
+ // update to the target offset so the CSS transition actually fires.
37
+ // Without this two-frame approach the element starts at the final value
38
+ // and the transition is never observed.
39
+ this.shadowRoot.innerHTML = `
40
+ <style>
41
+ ${themeCSS}
42
+ :host {
43
+ display: inline-flex;
44
+ flex-direction: column;
45
+ align-items: center;
46
+ font-family: var(--nx-font-mono, 'JetBrains Mono', monospace);
47
+ }
48
+ .ring-arc {
49
+ transition: stroke-dashoffset 700ms cubic-bezier(0, 0, 0.2, 1);
50
+ transform-origin: center;
51
+ transform: rotate(-90deg);
52
+ }
53
+ .label {
54
+ font-size: ${labelSize}px;
55
+ color: var(--nx-text-3, #6E7681);
56
+ margin-top: ${Math.round(size * 0.04)}px;
57
+ text-transform: uppercase;
58
+ letter-spacing: 0.06em;
59
+ user-select: none;
60
+ }
61
+ </style>
62
+ <svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" aria-label="${label}: ${score}%" role="img">
63
+ <circle
64
+ cx="${cx}" cy="${cy}" r="${radius}"
65
+ fill="none"
66
+ stroke="var(--nx-border, rgba(255,255,255,0.08))"
67
+ stroke-width="${sw}"
68
+ />
69
+ <circle
70
+ class="ring-arc"
71
+ cx="${cx}" cy="${cy}" r="${radius}"
72
+ fill="none"
73
+ stroke="${color}"
74
+ stroke-width="${sw}"
75
+ stroke-linecap="round"
76
+ stroke-dasharray="${circumference}"
77
+ stroke-dashoffset="${circumference}"
78
+ />
79
+ <text
80
+ x="${cx}" y="${cy + fontSize * 0.35}"
81
+ text-anchor="middle"
82
+ fill="var(--nx-text, #E6EDF3)"
83
+ font-size="${fontSize}"
84
+ font-weight="600"
85
+ font-family="inherit"
86
+ >${score}</text>
87
+ </svg>
88
+ <div class="label">${label}</div>
89
+ `;
90
+ // Two-frame update triggers the CSS transition
91
+ const arc = this.shadowRoot.querySelector(".ring-arc");
92
+ if (arc) {
93
+ requestAnimationFrame(() => {
94
+ requestAnimationFrame(() => {
95
+ arc.style.strokeDashoffset = String(targetOffset);
96
+ });
97
+ });
98
+ }
99
+ }
100
+ }
101
+ //# sourceMappingURL=status-ring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-ring.js","sourceRoot":"","sources":["../../src/primitives/status-ring.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,8CAA8C;AAC9C,gDAAgD;AAEhD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C,MAAM,KAAK,kBAAkB;QAC3B,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,wBAAwB;QACtB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,MAAM,KAAK,GAAI,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC;QACtD,MAAM,KAAK,GAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,2BAA2B,CAAC;QACzE,MAAM,IAAI,GAAK,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QAE7E,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC;QACpB,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAC3C,MAAM,EAAE,GAAO,IAAI,GAAG,KAAK,CAAC;QAC5B,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC;QAC3C,MAAM,YAAY,GAAI,aAAa,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,aAAa,CAAC;QACpE,MAAM,QAAQ,GAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAO,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAQ,cAAc,CAAC,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,OAAO,CAAC,CAAC;QAE3F,4EAA4E;QAC5E,oEAAoE;QACpE,wEAAwE;QACxE,wCAAwC;QACxC,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG;;UAEtB,QAAQ;;;;;;;;;;;;;uBAaK,SAAS;;wBAER,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;;;;;;oBAM3B,IAAI,aAAa,IAAI,kBAAkB,IAAI,IAAI,IAAI,iBAAiB,KAAK,KAAK,KAAK;;gBAEvF,EAAE,SAAS,EAAE,QAAQ,MAAM;;;0BAGjB,EAAE;;;;gBAIZ,EAAE,SAAS,EAAE,QAAQ,MAAM;;oBAEvB,KAAK;0BACC,EAAE;;8BAEE,aAAa;+BACZ,aAAa;;;eAG7B,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,IAAI;;;uBAGtB,QAAQ;;;WAGpB,KAAK;;2BAEW,KAAK;KAC3B,CAAC;QAEF,+CAA+C;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAmB,WAAW,CAAC,CAAC;QACzE,IAAI,GAAG,EAAE,CAAC;YACR,qBAAqB,CAAC,GAAG,EAAE;gBACzB,qBAAqB,CAAC,GAAG,EAAE;oBACzB,GAAG,CAAC,KAAK,CAAC,gBAAgB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;gBACpD,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ export declare class NexSwitch extends HTMLElement {
2
+ private _checked;
3
+ static get observedAttributes(): string[];
4
+ constructor();
5
+ connectedCallback(): void;
6
+ attributeChangedCallback(name: string, _old: string, val: string): void;
7
+ get checked(): boolean;
8
+ set checked(v: boolean);
9
+ private toggle;
10
+ private render;
11
+ }
12
+ //# sourceMappingURL=switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../src/primitives/switch.ts"],"names":[],"mappings":"AAWA,qBAAa,SAAU,SAAQ,WAAW;IACxC,OAAO,CAAC,QAAQ,CAAS;IAEzB,MAAM,KAAK,kBAAkB,aAE5B;;IAOD,iBAAiB;IAYjB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAKhE,IAAI,OAAO,IACI,OAAO,CADiB;IACvC,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,EAIrB;IAED,OAAO,CAAC,MAAM;IAMd,OAAO,CAAC,MAAM;CAgFf"}
@@ -0,0 +1,124 @@
1
+ // @yugnex/nexui — NexSwitch Web Component
2
+ // Toggle switch with label and ARIA.
3
+ // Attributes:
4
+ // checked: boolean
5
+ // disabled: boolean
6
+ // label: string
7
+ // size: sm | md | lg
8
+ // color: accent | live | success (default: accent)
9
+ import { nexui_compiler } from "../core/compiler";
10
+ export class NexSwitch extends HTMLElement {
11
+ static get observedAttributes() {
12
+ return ["checked", "disabled", "label", "size", "color"];
13
+ }
14
+ constructor() {
15
+ super();
16
+ this._checked = false;
17
+ this.attachShadow({ mode: "open" });
18
+ }
19
+ connectedCallback() {
20
+ this._checked = this.hasAttribute("checked");
21
+ this.render();
22
+ this.shadowRoot?.querySelector(".track")?.addEventListener("click", () => this.toggle());
23
+ this.shadowRoot?.querySelector(".track")?.addEventListener("keydown", (e) => {
24
+ if (e.key === " " || e.key === "Enter") {
25
+ e.preventDefault();
26
+ this.toggle();
27
+ }
28
+ });
29
+ }
30
+ attributeChangedCallback(name, _old, val) {
31
+ if (name === "checked")
32
+ this._checked = val !== null;
33
+ this.render();
34
+ }
35
+ get checked() { return this._checked; }
36
+ set checked(v) {
37
+ this._checked = v;
38
+ v ? this.setAttribute("checked", "") : this.removeAttribute("checked");
39
+ this.render();
40
+ }
41
+ toggle() {
42
+ if (this.hasAttribute("disabled"))
43
+ return;
44
+ this.checked = !this._checked;
45
+ this.dispatchEvent(new CustomEvent("change", { detail: { checked: this._checked }, bubbles: true }));
46
+ }
47
+ render() {
48
+ if (!this.shadowRoot)
49
+ return;
50
+ const size = this.getAttribute("size") ?? "md";
51
+ const color = this.getAttribute("color") ?? "accent";
52
+ const label = this.getAttribute("label") ?? "";
53
+ const disabled = this.hasAttribute("disabled");
54
+ const themeCSS = nexui_compiler.getThemeCSS(nexui_compiler.getActiveTheme(), ":host");
55
+ const colorMap = {
56
+ accent: "var(--nx-accent, #E89010)",
57
+ live: "var(--nx-live, #0FD4C6)",
58
+ success: "var(--nx-success, #22C55E)",
59
+ };
60
+ const activeColor = colorMap[color] ?? colorMap.accent;
61
+ const dims = {
62
+ sm: { w: 28, h: 16, thumb: 12, fs: "11px" },
63
+ md: { w: 36, h: 20, thumb: 16, fs: "12px" },
64
+ lg: { w: 44, h: 24, thumb: 20, fs: "13px" },
65
+ };
66
+ const d = dims[size] ?? dims.md;
67
+ const thumbTravel = d.w - d.thumb - 4;
68
+ this.shadowRoot.innerHTML = `
69
+ <style>
70
+ ${themeCSS}
71
+ :host { display: inline-flex; align-items: center; gap: 8px; }
72
+ .track {
73
+ position: relative;
74
+ width: ${d.w}px;
75
+ height: ${d.h}px;
76
+ border-radius: 9999px;
77
+ background: ${this._checked ? activeColor : "var(--nx-bg-elevated, #1C2128)"};
78
+ border: 1px solid ${this._checked ? "transparent" : "var(--nx-border-strong, rgba(255,255,255,0.16))"};
79
+ cursor: ${disabled ? "not-allowed" : "pointer"};
80
+ opacity: ${disabled ? 0.45 : 1};
81
+ transition: background 150ms ease, border-color 150ms ease;
82
+ outline: none;
83
+ flex-shrink: 0;
84
+ }
85
+ .track:focus-visible {
86
+ box-shadow: 0 0 0 2px var(--nx-bg-base, #0D1117), 0 0 0 4px ${activeColor};
87
+ }
88
+ .thumb {
89
+ position: absolute;
90
+ top: 50%;
91
+ left: 2px;
92
+ transform: translateY(-50%) translateX(${this._checked ? `${thumbTravel}px` : "0"});
93
+ width: ${d.thumb}px;
94
+ height: ${d.thumb}px;
95
+ border-radius: 50%;
96
+ background: ${this._checked ? "var(--nx-bg-base, #0D1117)" : "var(--nx-text-4, #484F58)"};
97
+ transition: transform 150ms cubic-bezier(0.34,1.56,0.64,1), background 150ms ease;
98
+ pointer-events: none;
99
+ }
100
+ .label {
101
+ font-family: var(--nx-font-sans, system-ui, sans-serif);
102
+ font-size: ${d.fs};
103
+ color: ${disabled ? "var(--nx-text-4, #484F58)" : "var(--nx-text-2, #8B949E)"};
104
+ user-select: none;
105
+ cursor: ${disabled ? "not-allowed" : "pointer"};
106
+ }
107
+ </style>
108
+ <div class="track" role="switch" aria-checked="${this._checked}" tabindex="${disabled ? -1 : 0}" part="track">
109
+ <div class="thumb" part="thumb"></div>
110
+ </div>
111
+ ${label ? `<span class="label" part="label">${label}</span>` : ""}
112
+ `;
113
+ // Re-attach events after innerHTML reset
114
+ const track = this.shadowRoot.querySelector(".track");
115
+ track?.addEventListener("click", () => this.toggle());
116
+ track?.addEventListener("keydown", (e) => {
117
+ if (e.key === " " || e.key === "Enter") {
118
+ e.preventDefault();
119
+ this.toggle();
120
+ }
121
+ });
122
+ }
123
+ }
124
+ //# sourceMappingURL=switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"switch.js","sourceRoot":"","sources":["../../src/primitives/switch.ts"],"names":[],"mappings":"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"}