@genomicx/ui 0.2.0 → 0.3.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/dist/index.js CHANGED
@@ -1,233 +1,182 @@
1
- import { jsxs as o, jsx as e } from "react/jsx-runtime";
2
- import { useState as h, useRef as f } from "react";
3
- import { Link as m } from "react-router-dom";
4
- import u from "react-hot-toast";
5
- function p({ disabled: t = !1 }) {
6
- const [r, a] = h(
7
- () => document.documentElement.getAttribute("data-theme") || "light"
8
- ), l = (n) => {
9
- a(n), document.documentElement.setAttribute("data-theme", n), localStorage.setItem("gx-theme", n);
1
+ import { jsxs as a, jsx as e } from "react/jsx-runtime";
2
+ import { useState as v, useRef as p } from "react";
3
+ import { Link as d } from "react-router-dom";
4
+ import g from "react-hot-toast";
5
+ function u({ disabled: n = !1 }) {
6
+ const [o, t] = v(
7
+ () => document.documentElement.getAttribute("data-theme") || "dark"
8
+ ), l = (r) => {
9
+ t(r), document.documentElement.setAttribute("data-theme", r), localStorage.setItem("gx-theme", r);
10
10
  };
11
- return /* @__PURE__ */ o(
12
- "div",
13
- {
14
- className: `flex items-center rounded-full border overflow-hidden text-xs font-medium ${t ? "opacity-40 pointer-events-none" : ""}`,
15
- style: { borderColor: "var(--gx-border)" },
16
- title: t ? "Theme switching disabled" : void 0,
17
- children: [
18
- /* @__PURE__ */ e(
19
- "button",
20
- {
21
- onClick: () => !t && l("dark"),
22
- className: "px-3 py-1.5 transition-colors",
23
- style: r === "dark" ? { background: "var(--gx-accent)", color: "var(--gx-text-inverted)" } : { color: "var(--gx-text-muted)" },
24
- "aria-label": "Dark theme",
25
- disabled: t,
26
- children: /* @__PURE__ */ e("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ e("path", { d: "M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" }) })
27
- }
28
- ),
29
- /* @__PURE__ */ e(
30
- "button",
31
- {
32
- onClick: () => !t && l("light"),
33
- className: "px-3 py-1.5 transition-colors",
34
- style: r === "light" ? { background: "var(--gx-accent)", color: "var(--gx-text-inverted)" } : { color: "var(--gx-text-muted)" },
35
- "aria-label": "Light theme",
36
- disabled: t,
37
- children: /* @__PURE__ */ e("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ e("path", { fillRule: "evenodd", d: "M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z", clipRule: "evenodd" }) })
38
- }
39
- )
40
- ]
41
- }
42
- );
11
+ return /* @__PURE__ */ a("div", { className: `gx-theme-toggle${n ? " disabled" : ""}`, title: n ? "Theme switching disabled" : void 0, children: [
12
+ /* @__PURE__ */ e(
13
+ "button",
14
+ {
15
+ onClick: () => !n && l("dark"),
16
+ className: `gx-theme-btn${o === "dark" ? " active" : ""}`,
17
+ "aria-label": "Dark theme",
18
+ disabled: n,
19
+ children: /* @__PURE__ */ e("svg", { className: "gx-theme-btn-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ e("path", { d: "M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" }) })
20
+ }
21
+ ),
22
+ /* @__PURE__ */ e(
23
+ "button",
24
+ {
25
+ onClick: () => !n && l("light"),
26
+ className: `gx-theme-btn${o === "light" ? " active" : ""}`,
27
+ "aria-label": "Light theme",
28
+ disabled: n,
29
+ children: /* @__PURE__ */ e("svg", { className: "gx-theme-btn-icon", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ e("path", { fillRule: "evenodd", d: "M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z", clipRule: "evenodd" }) })
30
+ }
31
+ )
32
+ ] });
43
33
  }
44
- function b({ appName: t, appSubtitle: r, version: a, actions: l, mobileActions: n }) {
45
- const [s, c] = h(!1);
46
- return /* @__PURE__ */ o("nav", { className: "sticky top-0 z-40", style: { background: "var(--gx-nav-bg)", backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)", borderBottom: "1px solid var(--gx-border)" }, children: [
47
- /* @__PURE__ */ e("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ o("div", { className: "flex items-center justify-between h-[60px]", children: [
48
- /* @__PURE__ */ o(m, { to: "/", className: "flex items-center gap-3 hover:opacity-90 transition-opacity", children: [
49
- /* @__PURE__ */ o("svg", { className: "w-7 h-7", viewBox: "0 0 24 24", fill: "none", stroke: "var(--gx-accent)", strokeWidth: "2", children: [
34
+ function f({ appName: n, appSubtitle: o, version: t, actions: l, mobileActions: r }) {
35
+ const [c, s] = v(!1);
36
+ return /* @__PURE__ */ a("nav", { className: "gx-nav", children: [
37
+ /* @__PURE__ */ e("div", { className: "gx-nav-inner", children: /* @__PURE__ */ a("div", { className: "gx-nav-row", children: [
38
+ /* @__PURE__ */ a(d, { to: "/", className: "gx-nav-logo", children: [
39
+ /* @__PURE__ */ a("svg", { className: "gx-nav-logo-icon", viewBox: "0 0 24 24", fill: "none", stroke: "var(--gx-accent)", strokeWidth: "2", children: [
50
40
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "10" }),
51
41
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "6" }),
52
42
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "2" })
53
43
  ] }),
54
- /* @__PURE__ */ o("div", { children: [
55
- /* @__PURE__ */ o("h1", { className: "text-lg font-bold", style: { color: "var(--gx-text)" }, children: [
56
- t,
57
- a && /* @__PURE__ */ o("span", { className: "text-xs font-normal ml-1", style: { color: "var(--gx-text-muted)" }, children: [
44
+ /* @__PURE__ */ a("div", { children: [
45
+ /* @__PURE__ */ a("h1", { className: "gx-nav-logo-name", children: [
46
+ n,
47
+ t && /* @__PURE__ */ a("span", { className: "gx-nav-logo-version", children: [
58
48
  "v",
59
- a
49
+ t
60
50
  ] })
61
51
  ] }),
62
- r && /* @__PURE__ */ e("p", { className: "text-xs", style: { color: "var(--gx-text-muted)" }, children: r })
52
+ o && /* @__PURE__ */ e("p", { className: "gx-nav-logo-sub", children: o })
63
53
  ] })
64
54
  ] }),
65
- /* @__PURE__ */ o("div", { className: "hidden md:flex items-center gap-6", children: [
55
+ /* @__PURE__ */ a("div", { className: "gx-nav-desktop", children: [
66
56
  l,
67
- /* @__PURE__ */ e(m, { to: "/about", className: "text-sm font-medium transition-colors", style: { color: "var(--gx-text-muted)" }, children: "About" }),
68
- /* @__PURE__ */ o(
69
- "a",
70
- {
71
- href: "https://github.com/happykhan",
72
- target: "_blank",
73
- rel: "noopener noreferrer",
74
- className: "text-sm font-medium transition-colors inline-flex items-center gap-1",
75
- style: { color: "var(--gx-text-muted)" },
76
- children: [
77
- "GitHub",
78
- /* @__PURE__ */ e("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
79
- ]
80
- }
81
- ),
82
- /* @__PURE__ */ e(p, {})
57
+ /* @__PURE__ */ e(d, { to: "/about", className: "gx-nav-link", children: "About" }),
58
+ /* @__PURE__ */ a("a", { href: "https://github.com/happykhan", target: "_blank", rel: "noopener noreferrer", className: "gx-nav-link", children: [
59
+ "GitHub",
60
+ /* @__PURE__ */ e("svg", { className: "gx-nav-link-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
61
+ ] }),
62
+ /* @__PURE__ */ e(u, {})
83
63
  ] }),
84
- /* @__PURE__ */ o("div", { className: "flex md:hidden items-center gap-3", children: [
85
- /* @__PURE__ */ e(p, {}),
86
- /* @__PURE__ */ e(
87
- "button",
88
- {
89
- onClick: () => c(!s),
90
- className: "p-2 rounded",
91
- style: { color: "var(--gx-text-muted)" },
92
- "aria-label": "Toggle menu",
93
- children: s ? /* @__PURE__ */ e("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) : /* @__PURE__ */ e("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) })
94
- }
95
- )
64
+ /* @__PURE__ */ a("div", { className: "gx-nav-mobile-toggle", children: [
65
+ /* @__PURE__ */ e(u, {}),
66
+ /* @__PURE__ */ e("button", { onClick: () => s(!c), className: "gx-nav-hamburger", "aria-label": "Toggle menu", children: c ? /* @__PURE__ */ e("svg", { className: "gx-nav-hamburger-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) : /* @__PURE__ */ e("svg", { className: "gx-nav-hamburger-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 6h16M4 12h16M4 18h16" }) }) })
96
67
  ] })
97
68
  ] }) }),
98
- s && /* @__PURE__ */ o("div", { className: "md:hidden px-4 pb-4 space-y-2", style: { borderTop: "1px solid var(--gx-border)", background: "var(--gx-nav-bg)" }, children: [
99
- n,
100
- /* @__PURE__ */ e(m, { to: "/about", onClick: () => c(!1), className: "block text-sm py-2 transition-colors", style: { color: "var(--gx-text-muted)" }, children: "About" }),
101
- /* @__PURE__ */ o(
102
- "a",
103
- {
104
- href: "https://github.com/happykhan",
105
- target: "_blank",
106
- rel: "noopener noreferrer",
107
- className: "inline-flex items-center gap-1 text-sm py-2 transition-colors",
108
- style: { color: "var(--gx-text-muted)" },
109
- children: [
110
- "GitHub",
111
- /* @__PURE__ */ e("svg", { className: "w-3.5 h-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" }) })
112
- ]
113
- }
114
- )
69
+ c && /* @__PURE__ */ a("div", { className: "gx-nav-dropdown", children: [
70
+ r,
71
+ /* @__PURE__ */ e(d, { to: "/about", onClick: () => s(!1), className: "gx-nav-dropdown-link", children: "About" }),
72
+ /* @__PURE__ */ e("a", { href: "https://github.com/happykhan", target: "_blank", rel: "noopener noreferrer", className: "gx-nav-dropdown-link", children: "GitHub ↗" })
115
73
  ] })
116
74
  ] });
117
75
  }
118
- function y({ appName: t = "GenomicX", onReportBug: r }) {
119
- return /* @__PURE__ */ e("footer", { className: "mt-auto py-6", style: { borderTop: "1px solid var(--gx-border)", background: "var(--gx-bg-alt)" }, children: /* @__PURE__ */ e("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ o("div", { className: "flex flex-col md:flex-row justify-between items-center", children: [
120
- /* @__PURE__ */ o("div", { className: "text-sm mb-4 md:mb-0", style: { color: "var(--gx-text-muted)" }, children: [
121
- /* @__PURE__ */ o("p", { className: "font-semibold", style: { color: "var(--gx-text)" }, children: [
122
- t,
123
- " — Powered by BLAST & WebAssembly"
76
+ function N({ appName: n = "GenomicX", onReportBug: o }) {
77
+ return /* @__PURE__ */ e("footer", { className: "gx-footer", children: /* @__PURE__ */ e("div", { className: "gx-footer-inner", children: /* @__PURE__ */ a("div", { className: "gx-footer-content", children: [
78
+ /* @__PURE__ */ a("div", { className: "gx-footer-text", children: [
79
+ /* @__PURE__ */ a("p", { className: "gx-footer-text-title", children: [
80
+ n,
81
+ " — Powered by WebAssembly"
124
82
  ] }),
125
- /* @__PURE__ */ e("p", { className: "mt-1", children: "All processing runs locally in your browser — no data leaves your computer" })
83
+ /* @__PURE__ */ e("p", { className: "gx-footer-text-sub", children: "All processing runs locally in your browser — no data leaves your computer" })
126
84
  ] }),
127
- /* @__PURE__ */ o("div", { className: "flex gap-6 text-sm", children: [
128
- /* @__PURE__ */ e("a", { href: "https://genomicx.org", target: "_blank", rel: "noopener noreferrer", className: "transition-colors hover:text-[var(--gx-accent)]", style: { color: "var(--gx-text-muted)" }, children: "genomicx.org" }),
129
- r && /* @__PURE__ */ e("button", { onClick: r, className: "transition-colors hover:text-[var(--gx-accent)]", style: { color: "var(--gx-text-muted)" }, children: "Report Bug" })
85
+ /* @__PURE__ */ a("div", { className: "gx-footer-links", children: [
86
+ /* @__PURE__ */ e("a", { href: "https://genomicx.org", target: "_blank", rel: "noopener noreferrer", className: "gx-footer-link", children: "genomicx.org" }),
87
+ o && /* @__PURE__ */ e("button", { onClick: o, className: "gx-footer-link", children: "Report Bug" })
130
88
  ] })
131
89
  ] }) }) });
132
90
  }
133
- function C({ children: t, onReportBug: r, ...a }) {
134
- return /* @__PURE__ */ o("div", { className: "min-h-screen flex flex-col", style: { background: "var(--gx-bg)" }, children: [
135
- /* @__PURE__ */ e(b, { ...a }),
136
- /* @__PURE__ */ e("main", { className: "flex-1", children: t }),
137
- /* @__PURE__ */ e(y, { appName: a.appName, onReportBug: r })
91
+ function B({ children: n, onReportBug: o, ...t }) {
92
+ return /* @__PURE__ */ a("div", { style: { minHeight: "100vh", display: "flex", flexDirection: "column", background: "var(--gx-bg)" }, children: [
93
+ /* @__PURE__ */ e(f, { ...t }),
94
+ /* @__PURE__ */ e("main", { style: { flex: 1 }, children: n }),
95
+ /* @__PURE__ */ e(N, { appName: t.appName, onReportBug: o })
138
96
  ] });
139
97
  }
140
- function j({ logs: t, progress: r, title: a = "Console" }) {
141
- const [l, n] = h(!0), s = f(null), c = () => {
142
- navigator.clipboard.writeText(t.join(`
98
+ function C({ logs: n, progress: o, title: t = "Console" }) {
99
+ const l = p(null), r = () => {
100
+ navigator.clipboard.writeText(n.join(`
143
101
  `)).then(() => {
144
- u.success("Logs copied to clipboard!");
102
+ g.success("Logs copied to clipboard!");
145
103
  }).catch(() => {
146
- u.error("Failed to copy logs");
104
+ g.error("Failed to copy logs");
147
105
  });
148
- }, i = r && r.step !== "idle" && r.step !== "Complete!";
149
- return /* @__PURE__ */ o("div", { className: "card mt-6", children: [
150
- i && /* @__PURE__ */ o("div", { className: "mb-4 pb-4", style: { borderBottom: "1px solid var(--gx-border)" }, children: [
151
- /* @__PURE__ */ o("div", { className: "flex items-center justify-between mb-2", children: [
152
- /* @__PURE__ */ e("span", { className: "text-sm font-medium", style: { color: "var(--gx-text)" }, children: r.step }),
153
- /* @__PURE__ */ o("span", { className: "text-sm", style: { color: "var(--gx-text-muted)" }, children: [
154
- r.percent,
106
+ }, c = o && o.step !== "idle" && o.step !== "Complete!";
107
+ return /* @__PURE__ */ a("div", { className: "gx-console", children: [
108
+ c && /* @__PURE__ */ a("div", { className: "gx-console-progress", children: [
109
+ /* @__PURE__ */ a("div", { className: "gx-console-progress-row", children: [
110
+ /* @__PURE__ */ e("span", { className: "gx-console-progress-step", children: o.step }),
111
+ /* @__PURE__ */ a("span", { className: "gx-console-progress-pct", children: [
112
+ o.percent,
155
113
  "%"
156
114
  ] })
157
115
  ] }),
158
- /* @__PURE__ */ e("div", { className: "progress-bg", children: /* @__PURE__ */ e("div", { className: "progress-bar", style: { width: `${r.percent}%` } }) }),
159
- r.message && /* @__PURE__ */ e("div", { className: "mt-2 text-xs", style: { color: "var(--gx-text-muted)" }, children: r.message })
116
+ /* @__PURE__ */ e("div", { className: "progress-bg", children: /* @__PURE__ */ e("div", { className: "progress-bar", style: { width: `${o.percent}%` } }) }),
117
+ o.message && /* @__PURE__ */ e("div", { className: "gx-console-progress-msg", children: o.message })
160
118
  ] }),
161
- /* @__PURE__ */ o("div", { className: "flex items-center justify-between mb-3", children: [
162
- /* @__PURE__ */ o("div", { className: "flex items-center gap-2", children: [
163
- /* @__PURE__ */ e("button", { onClick: () => n(!l), style: { color: "var(--gx-text-muted)" }, children: l ? "▼" : "▶" }),
164
- /* @__PURE__ */ e("h3", { className: "font-semibold", style: { color: "var(--gx-text)" }, children: a }),
165
- /* @__PURE__ */ o("span", { className: "text-xs", style: { color: "var(--gx-text-muted)" }, children: [
119
+ /* @__PURE__ */ a("div", { className: "gx-console-header", children: [
120
+ /* @__PURE__ */ a("div", { className: "gx-console-title-row", children: [
121
+ /* @__PURE__ */ e("h3", { className: "gx-console-title", children: t }),
122
+ /* @__PURE__ */ a("span", { className: "gx-console-count", children: [
166
123
  "(",
167
- t.length,
124
+ n.length,
168
125
  " messages)"
169
126
  ] })
170
127
  ] }),
171
- /* @__PURE__ */ o("button", { onClick: c, className: "btn-secondary text-xs px-3 py-1", disabled: t.length === 0, children: [
172
- /* @__PURE__ */ e("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
128
+ /* @__PURE__ */ a("button", { onClick: r, className: "gx-console-copy", disabled: n.length === 0, children: [
129
+ /* @__PURE__ */ e("svg", { className: "gx-console-copy-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ e("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
173
130
  "Copy"
174
131
  ] })
175
132
  ] }),
176
- l && /* @__PURE__ */ e(
177
- "div",
178
- {
179
- ref: s,
180
- className: "font-mono text-xs p-4 rounded max-h-96 overflow-y-auto",
181
- style: { background: "var(--gx-code-bg)", color: "var(--gx-accent)", border: "1px solid var(--gx-border)" },
182
- children: t.length === 0 ? /* @__PURE__ */ e("div", { style: { color: "var(--gx-text-muted)" }, children: "No logs yet..." }) : t.map((d, g) => /* @__PURE__ */ e("div", { className: "mb-1 whitespace-pre-wrap break-all", children: d }, g))
183
- }
184
- )
133
+ /* @__PURE__ */ e("div", { ref: l, className: "gx-console-body", children: n.length === 0 ? /* @__PURE__ */ e("div", { className: "gx-console-empty", children: "No logs yet..." }) : n.map((s, i) => /* @__PURE__ */ e("div", { className: "gx-console-line", children: s }, i)) })
185
134
  ] });
186
135
  }
187
- const k = "https://static.genomicx.org/wasm", x = /* @__PURE__ */ new Map();
188
- async function N(t, r = k) {
189
- const a = `${r}/${t}`;
190
- if (x.has(a)) return x.get(a);
191
- const [l, n] = await Promise.all([
192
- fetch(`${r}/${t}.js`),
193
- fetch(`${r}/${t}.wasm`)
136
+ const k = "https://static.genomicx.org/wasm", h = /* @__PURE__ */ new Map();
137
+ async function b(n, o = k) {
138
+ const t = `${o}/${n}`;
139
+ if (h.has(t)) return h.get(t);
140
+ const [l, r] = await Promise.all([
141
+ fetch(`${o}/${n}.js`),
142
+ fetch(`${o}/${n}.wasm`)
194
143
  ]);
195
- if (!l.ok) throw new Error(`Failed to fetch ${t}.js: ${l.status}`);
196
- if (!n.ok) throw new Error(`Failed to fetch ${t}.wasm: ${n.status}`);
197
- const [s, c] = await Promise.all([
144
+ if (!l.ok) throw new Error(`Failed to fetch ${n}.js: ${l.status}`);
145
+ if (!r.ok) throw new Error(`Failed to fetch ${n}.wasm: ${r.status}`);
146
+ const [c, s] = await Promise.all([
198
147
  l.text(),
199
- n.arrayBuffer()
200
- ]), d = { factory: new Function("Module", s + "; return Module;")({}), wasmBinary: c };
201
- return x.set(a, d), d;
148
+ r.arrayBuffer()
149
+ ]), m = { factory: new Function("Module", c + "; return Module;")({}), wasmBinary: s };
150
+ return h.set(t, m), m;
202
151
  }
203
- async function A(t, r) {
204
- const { factory: a, wasmBinary: l } = await N(t, r), n = [], s = [], c = await a({
152
+ async function $(n, o) {
153
+ const { factory: t, wasmBinary: l } = await b(n, o), r = [], c = [], s = await t({
205
154
  wasmBinary: l.slice(0),
206
- print: (i) => n.push(i),
207
- printErr: (i) => s.push(i),
155
+ print: (i) => r.push(i),
156
+ printErr: (i) => c.push(i),
208
157
  noInitialRun: !0
209
158
  });
210
- return c._stdout = n, c._stderr = s, c;
159
+ return s._stdout = r, s._stderr = c, s;
211
160
  }
212
- function v(t, r) {
213
- const a = URL.createObjectURL(t), l = document.createElement("a");
214
- l.href = a, l.download = r, l.click(), URL.revokeObjectURL(a);
161
+ function x(n, o) {
162
+ const t = URL.createObjectURL(n), l = document.createElement("a");
163
+ l.href = t, l.download = o, l.click(), URL.revokeObjectURL(t);
215
164
  }
216
- function T(t, r, a = "text/plain") {
217
- v(new Blob([t], { type: a }), r);
165
+ function j(n, o, t = "text/plain") {
166
+ x(new Blob([n], { type: t }), o);
218
167
  }
219
- function z(t, r) {
220
- v(new Blob([t]), r);
168
+ function A(n, o) {
169
+ x(new Blob([n]), o);
221
170
  }
222
171
  export {
223
- y as AppFooter,
224
- C as AppShell,
225
- j as LogConsole,
226
- b as NavBar,
227
- p as ThemeToggle,
228
- A as createModuleInstance,
229
- v as downloadBlob,
230
- z as downloadBuffer,
231
- T as downloadText,
232
- N as loadWasmModule
172
+ N as AppFooter,
173
+ B as AppShell,
174
+ C as LogConsole,
175
+ f as NavBar,
176
+ u as ThemeToggle,
177
+ $ as createModuleInstance,
178
+ x as downloadBlob,
179
+ A as downloadBuffer,
180
+ j as downloadText,
181
+ b as loadWasmModule
233
182
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genomicx/ui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Shared UI components, styles, and WASM loader for GenomicX tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,125 +1,400 @@
1
- /* GenomicX Tailwind component classesimport after @tailwind directives */
2
-
3
- @layer base {
4
- html {
5
- scroll-behavior: smooth;
6
- -webkit-font-smoothing: antialiased;
7
- -moz-osx-font-smoothing: grayscale;
8
- }
9
-
10
- body {
11
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
12
- background-color: var(--gx-bg);
13
- color: var(--gx-text);
14
- line-height: 1.7;
15
- transition: background-color var(--gx-transition), color var(--gx-transition);
16
- margin: 0;
17
- }
18
-
19
- * {
20
- transition: background-color var(--gx-transition), border-color var(--gx-transition), color var(--gx-transition);
21
- }
22
-
23
- code {
24
- font-family: 'JetBrains Mono', 'Fira Code', monospace;
25
- }
26
-
27
- ::-webkit-scrollbar { width: 10px; height: 10px; }
28
- ::-webkit-scrollbar-track { background: var(--gx-bg); }
29
- ::-webkit-scrollbar-thumb { background: var(--gx-border); border-radius: 999px; }
30
- ::-webkit-scrollbar-thumb:hover { background: var(--gx-text-muted); }
31
- }
32
-
33
- @layer components {
34
- .card {
35
- background: var(--gx-bg-alt);
36
- border: 1px solid var(--gx-border);
37
- border-radius: var(--gx-radius-lg);
38
- padding: 1.5rem;
39
- transition: border-color var(--gx-transition);
40
- }
41
-
42
- .card:hover {
43
- border-color: var(--gx-accent);
44
- }
45
-
46
- .btn-primary {
47
- display: inline-flex;
48
- align-items: center;
49
- justify-content: center;
50
- gap: 0.5rem;
51
- background: var(--gx-accent);
52
- color: var(--gx-text-inverted);
53
- font-weight: 600;
54
- font-size: 0.875rem;
55
- padding: 0.7rem 1.4rem;
56
- border-radius: 6px;
57
- border: none;
58
- cursor: pointer;
59
- transition: all var(--gx-transition);
60
- }
61
-
62
- .btn-primary:hover { background: var(--gx-accent-hover); }
63
- .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
64
-
65
- .btn-secondary {
66
- display: inline-flex;
67
- align-items: center;
68
- justify-content: center;
69
- gap: 0.5rem;
70
- background: transparent;
71
- color: var(--gx-text);
72
- font-weight: 600;
73
- font-size: 0.875rem;
74
- padding: 0.7rem 1.4rem;
75
- border-radius: 6px;
76
- border: 1px solid var(--gx-border);
77
- cursor: pointer;
78
- transition: all var(--gx-transition);
79
- }
80
-
81
- .btn-secondary:hover { border-color: var(--gx-accent); color: var(--gx-accent); }
82
-
83
- .input-field {
84
- background: var(--gx-bg);
85
- border: 1px solid var(--gx-border);
86
- color: var(--gx-text);
87
- border-radius: 6px;
88
- padding: 0.5rem 0.75rem;
89
- font-size: 0.875rem;
90
- transition: border-color var(--gx-transition);
91
- outline: none;
92
- }
93
-
94
- .input-field:focus { border-color: var(--gx-accent); }
95
-
96
- .label {
97
- display: block;
98
- font-size: 0.8125rem;
99
- font-weight: 500;
100
- color: var(--gx-text);
101
- margin-bottom: 0.5rem;
102
- }
103
-
104
- .section-title {
105
- font-size: 1.25rem;
106
- font-weight: 700;
107
- color: var(--gx-text);
108
- margin-bottom: 1rem;
109
- letter-spacing: -0.01em;
110
- }
111
-
112
- .progress-bg {
113
- background: var(--gx-bg);
114
- height: 6px;
115
- border-radius: 999px;
116
- overflow: hidden;
117
- }
118
-
119
- .progress-bar {
120
- background: var(--gx-accent);
121
- height: 6px;
122
- border-radius: 999px;
123
- transition: width 0.3s ease;
124
- }
1
+ /* GenomicX component stylesno Tailwind dependency */
2
+
3
+ /* ── Base resets ─────────────────────────────── */
4
+ html {
5
+ scroll-behavior: smooth;
6
+ -webkit-font-smoothing: antialiased;
7
+ -moz-osx-font-smoothing: grayscale;
8
+ }
9
+
10
+ body {
11
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
12
+ background-color: var(--gx-bg);
13
+ color: var(--gx-text);
14
+ line-height: 1.7;
15
+ transition: background-color var(--gx-transition), color var(--gx-transition);
16
+ margin: 0;
17
+ }
18
+
19
+ * {
20
+ transition: background-color var(--gx-transition), border-color var(--gx-transition), color var(--gx-transition);
21
+ }
22
+
23
+ code {
24
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
25
+ }
26
+
27
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
28
+ ::-webkit-scrollbar-track { background: var(--gx-bg); }
29
+ ::-webkit-scrollbar-thumb { background: var(--gx-border); border-radius: 999px; }
30
+ ::-webkit-scrollbar-thumb:hover { background: var(--gx-text-muted); }
31
+
32
+ /* ── NavBar ──────────────────────────────────── */
33
+ .gx-nav {
34
+ position: sticky;
35
+ top: 0;
36
+ z-index: 40;
37
+ background: var(--gx-nav-bg);
38
+ backdrop-filter: blur(12px);
39
+ -webkit-backdrop-filter: blur(12px);
40
+ border-bottom: 1px solid var(--gx-border);
41
+ }
42
+
43
+ .gx-nav-inner {
44
+ max-width: 80rem;
45
+ margin: 0 auto;
46
+ padding: 0 1rem;
47
+ }
48
+
49
+ @media (min-width: 640px) { .gx-nav-inner { padding: 0 1.5rem; } }
50
+ @media (min-width: 1024px) { .gx-nav-inner { padding: 0 2rem; } }
51
+
52
+ .gx-nav-row {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: space-between;
56
+ height: 60px;
57
+ }
58
+
59
+ .gx-nav-logo {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 0.75rem;
63
+ text-decoration: none;
64
+ opacity: 1;
65
+ transition: opacity var(--gx-transition);
66
+ }
67
+ .gx-nav-logo:hover { opacity: 0.85; }
68
+
69
+ .gx-nav-logo-icon { width: 28px; height: 28px; flex-shrink: 0; }
70
+
71
+ .gx-nav-logo-name {
72
+ font-size: 1.125rem;
73
+ font-weight: 700;
74
+ color: var(--gx-text);
75
+ margin: 0;
76
+ line-height: 1.3;
77
+ }
78
+
79
+ .gx-nav-logo-version {
80
+ font-size: 0.75rem;
81
+ font-weight: 400;
82
+ margin-left: 0.25rem;
83
+ color: var(--gx-text-muted);
84
+ }
85
+
86
+ .gx-nav-logo-sub {
87
+ font-size: 0.75rem;
88
+ color: var(--gx-text-muted);
89
+ margin: 0;
90
+ line-height: 1.2;
91
+ }
92
+
93
+ .gx-nav-desktop {
94
+ display: none;
95
+ align-items: center;
96
+ gap: 1.5rem;
97
+ }
98
+ @media (min-width: 768px) { .gx-nav-desktop { display: flex; } }
99
+
100
+ .gx-nav-link {
101
+ font-size: 0.875rem;
102
+ font-weight: 500;
103
+ color: var(--gx-text-muted);
104
+ text-decoration: none;
105
+ transition: color var(--gx-transition);
106
+ display: inline-flex;
107
+ align-items: center;
108
+ gap: 0.25rem;
109
+ }
110
+ .gx-nav-link:hover { color: var(--gx-text); }
111
+
112
+ .gx-nav-link-icon { width: 14px; height: 14px; }
113
+
114
+ .gx-nav-mobile-toggle {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 0.75rem;
118
+ }
119
+ @media (min-width: 768px) { .gx-nav-mobile-toggle { display: none; } }
120
+
121
+ .gx-nav-hamburger {
122
+ background: none;
123
+ border: none;
124
+ cursor: pointer;
125
+ padding: 0.5rem;
126
+ border-radius: 4px;
127
+ color: var(--gx-text-muted);
128
+ display: flex;
129
+ align-items: center;
130
+ }
131
+ .gx-nav-hamburger:hover { color: var(--gx-text); }
132
+
133
+ .gx-nav-hamburger-icon { width: 20px; height: 20px; }
134
+
135
+ .gx-nav-dropdown {
136
+ display: block;
137
+ padding: 0 1rem 1rem;
138
+ border-top: 1px solid var(--gx-border);
139
+ background: var(--gx-nav-bg);
140
+ }
141
+ @media (min-width: 768px) { .gx-nav-dropdown { display: none; } }
142
+
143
+ .gx-nav-dropdown-link {
144
+ display: block;
145
+ font-size: 0.875rem;
146
+ padding: 0.5rem 0;
147
+ color: var(--gx-text-muted);
148
+ text-decoration: none;
149
+ transition: color var(--gx-transition);
150
+ }
151
+ .gx-nav-dropdown-link:hover { color: var(--gx-text); }
152
+
153
+ /* ── Footer ──────────────────────────────────── */
154
+ .gx-footer {
155
+ margin-top: auto;
156
+ padding: 1.5rem 0;
157
+ border-top: 1px solid var(--gx-border);
158
+ background: var(--gx-bg-alt);
159
+ }
160
+
161
+ .gx-footer-inner {
162
+ max-width: 80rem;
163
+ margin: 0 auto;
164
+ padding: 0 1rem;
165
+ }
166
+ @media (min-width: 640px) { .gx-footer-inner { padding: 0 1.5rem; } }
167
+ @media (min-width: 1024px) { .gx-footer-inner { padding: 0 2rem; } }
168
+
169
+ .gx-footer-content {
170
+ display: flex;
171
+ flex-direction: column;
172
+ align-items: center;
173
+ gap: 1rem;
174
+ }
175
+ @media (min-width: 768px) {
176
+ .gx-footer-content { flex-direction: row; justify-content: space-between; }
177
+ }
178
+
179
+ .gx-footer-text { font-size: 0.875rem; color: var(--gx-text-muted); }
180
+ .gx-footer-text-title { font-weight: 600; color: var(--gx-text); margin: 0 0 0.25rem; }
181
+ .gx-footer-text-sub { margin: 0; }
182
+
183
+ .gx-footer-links {
184
+ display: flex;
185
+ gap: 1.5rem;
186
+ font-size: 0.875rem;
187
+ }
188
+
189
+ .gx-footer-link {
190
+ color: var(--gx-text-muted);
191
+ text-decoration: none;
192
+ background: none;
193
+ border: none;
194
+ cursor: pointer;
195
+ padding: 0;
196
+ font-size: 0.875rem;
197
+ transition: color var(--gx-transition);
198
+ }
199
+ .gx-footer-link:hover { color: var(--gx-accent); }
200
+
201
+ /* ── ThemeToggle ─────────────────────────────── */
202
+ .gx-theme-toggle {
203
+ display: flex;
204
+ align-items: center;
205
+ border-radius: 999px;
206
+ border: 1px solid var(--gx-border);
207
+ overflow: hidden;
208
+ font-size: 0.75rem;
209
+ font-weight: 500;
210
+ }
211
+ .gx-theme-toggle.disabled { opacity: 0.4; pointer-events: none; }
212
+
213
+ .gx-theme-btn {
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ padding: 0.375rem 0.75rem;
218
+ background: none;
219
+ border: none;
220
+ cursor: pointer;
221
+ transition: background var(--gx-transition), color var(--gx-transition);
222
+ color: var(--gx-text-muted);
223
+ }
224
+ .gx-theme-btn:hover { color: var(--gx-text); }
225
+ .gx-theme-btn-icon { width: 14px; height: 14px; }
226
+ .gx-theme-btn.active {
227
+ background: var(--gx-accent);
228
+ color: var(--gx-text-inverted);
229
+ }
230
+
231
+ /* ── LogConsole ──────────────────────────────── */
232
+ .gx-console {
233
+ background: var(--gx-bg-alt);
234
+ border: 1px solid var(--gx-border);
235
+ border-radius: var(--gx-radius-lg);
236
+ padding: 1.5rem;
237
+ margin-top: 1.5rem;
238
+ }
239
+
240
+ .gx-console-progress {
241
+ margin-bottom: 1rem;
242
+ padding-bottom: 1rem;
243
+ border-bottom: 1px solid var(--gx-border);
244
+ }
245
+
246
+ .gx-console-progress-row {
247
+ display: flex;
248
+ align-items: center;
249
+ justify-content: space-between;
250
+ margin-bottom: 0.5rem;
251
+ }
252
+
253
+ .gx-console-progress-step { font-size: 0.875rem; font-weight: 500; color: var(--gx-text); }
254
+ .gx-console-progress-pct { font-size: 0.875rem; color: var(--gx-text-muted); }
255
+ .gx-console-progress-msg { margin-top: 0.5rem; font-size: 0.75rem; color: var(--gx-text-muted); }
256
+
257
+ .gx-console-header {
258
+ display: flex;
259
+ align-items: center;
260
+ justify-content: space-between;
261
+ margin-bottom: 0.75rem;
262
+ }
263
+
264
+ .gx-console-title-row {
265
+ display: flex;
266
+ align-items: center;
267
+ gap: 0.5rem;
268
+ }
269
+
270
+ .gx-console-toggle {
271
+ background: none;
272
+ border: none;
273
+ cursor: pointer;
274
+ color: var(--gx-text-muted);
275
+ padding: 0;
276
+ font-size: 0.75rem;
277
+ }
278
+
279
+ .gx-console-title { font-weight: 600; color: var(--gx-text); margin: 0; font-size: 0.875rem; }
280
+ .gx-console-count { font-size: 0.75rem; color: var(--gx-text-muted); }
281
+
282
+ .gx-console-copy {
283
+ display: inline-flex;
284
+ align-items: center;
285
+ gap: 0.25rem;
286
+ font-size: 0.75rem;
287
+ padding: 0.25rem 0.75rem;
288
+ background: transparent;
289
+ color: var(--gx-text);
290
+ border: 1px solid var(--gx-border);
291
+ border-radius: 6px;
292
+ cursor: pointer;
293
+ transition: all var(--gx-transition);
294
+ font-weight: 600;
295
+ }
296
+ .gx-console-copy:hover { border-color: var(--gx-accent); color: var(--gx-accent); }
297
+ .gx-console-copy:disabled { opacity: 0.5; cursor: not-allowed; }
298
+ .gx-console-copy-icon { width: 16px; height: 16px; }
299
+
300
+ .gx-console-body {
301
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
302
+ font-size: 0.75rem;
303
+ padding: 1rem;
304
+ border-radius: 6px;
305
+ max-height: 24rem;
306
+ overflow-y: auto;
307
+ background: var(--gx-code-bg);
308
+ color: var(--gx-accent);
309
+ border: 1px solid var(--gx-border);
310
+ }
311
+
312
+ .gx-console-empty { color: var(--gx-text-muted); }
313
+ .gx-console-line { margin-bottom: 0.25rem; white-space: pre-wrap; word-break: break-all; }
314
+
315
+ /* ── Shared utility classes ──────────────────── */
316
+ .card {
317
+ background: var(--gx-bg-alt);
318
+ border: 1px solid var(--gx-border);
319
+ border-radius: var(--gx-radius-lg);
320
+ padding: 1.5rem;
321
+ transition: border-color var(--gx-transition);
322
+ }
323
+ .card:hover { border-color: var(--gx-accent); }
324
+
325
+ .btn-primary {
326
+ display: inline-flex;
327
+ align-items: center;
328
+ justify-content: center;
329
+ gap: 0.5rem;
330
+ background: var(--gx-accent);
331
+ color: var(--gx-text-inverted);
332
+ font-weight: 600;
333
+ font-size: 0.875rem;
334
+ padding: 0.7rem 1.4rem;
335
+ border-radius: 6px;
336
+ border: none;
337
+ cursor: pointer;
338
+ transition: all var(--gx-transition);
339
+ }
340
+ .btn-primary:hover { background: var(--gx-accent-hover); }
341
+ .btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
342
+
343
+ .btn-secondary {
344
+ display: inline-flex;
345
+ align-items: center;
346
+ justify-content: center;
347
+ gap: 0.5rem;
348
+ background: transparent;
349
+ color: var(--gx-text);
350
+ font-weight: 600;
351
+ font-size: 0.875rem;
352
+ padding: 0.7rem 1.4rem;
353
+ border-radius: 6px;
354
+ border: 1px solid var(--gx-border);
355
+ cursor: pointer;
356
+ transition: all var(--gx-transition);
357
+ }
358
+ .btn-secondary:hover { border-color: var(--gx-accent); color: var(--gx-accent); }
359
+
360
+ .input-field {
361
+ background: var(--gx-bg);
362
+ border: 1px solid var(--gx-border);
363
+ color: var(--gx-text);
364
+ border-radius: 6px;
365
+ padding: 0.5rem 0.75rem;
366
+ font-size: 0.875rem;
367
+ transition: border-color var(--gx-transition);
368
+ outline: none;
369
+ }
370
+ .input-field:focus { border-color: var(--gx-accent); }
371
+
372
+ .label {
373
+ display: block;
374
+ font-size: 0.8125rem;
375
+ font-weight: 500;
376
+ color: var(--gx-text);
377
+ margin-bottom: 0.5rem;
378
+ }
379
+
380
+ .section-title {
381
+ font-size: 1.25rem;
382
+ font-weight: 700;
383
+ color: var(--gx-text);
384
+ margin-bottom: 1rem;
385
+ letter-spacing: -0.01em;
386
+ }
387
+
388
+ .progress-bg {
389
+ background: var(--gx-bg);
390
+ height: 6px;
391
+ border-radius: 999px;
392
+ overflow: hidden;
393
+ }
394
+
395
+ .progress-bar {
396
+ background: var(--gx-accent);
397
+ height: 6px;
398
+ border-radius: 999px;
399
+ transition: width 0.3s ease;
125
400
  }