@underverse-ui/underverse 0.1.11 → 0.1.12
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 +201 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -71,6 +71,8 @@ __export(index_exports, {
|
|
|
71
71
|
Input: () => Input_default,
|
|
72
72
|
InteractiveBadge: () => InteractiveBadge,
|
|
73
73
|
Label: () => Label,
|
|
74
|
+
LanguageSwitcher: () => LanguageSwitcherHeadless,
|
|
75
|
+
LanguageSwitcherHeadless: () => LanguageSwitcherHeadless,
|
|
74
76
|
LoadingBar: () => LoadingBar,
|
|
75
77
|
LoadingDots: () => LoadingDots,
|
|
76
78
|
LoadingSpinner: () => LoadingSpinner,
|
|
@@ -111,6 +113,8 @@ __export(index_exports, {
|
|
|
111
113
|
Tabs: () => Tabs,
|
|
112
114
|
TagBadge: () => TagBadge,
|
|
113
115
|
Textarea: () => Textarea_default,
|
|
116
|
+
ThemeToggle: () => ThemeToggleHeadless,
|
|
117
|
+
ThemeToggleHeadless: () => ThemeToggleHeadless,
|
|
114
118
|
ToastProvider: () => Toast_default,
|
|
115
119
|
Tooltip: () => Tooltip,
|
|
116
120
|
VARIANT_STYLES_ALERT: () => VARIANT_STYLES_ALERT,
|
|
@@ -8605,6 +8609,199 @@ function AccessDenied({
|
|
|
8605
8609
|
] }) });
|
|
8606
8610
|
}
|
|
8607
8611
|
|
|
8612
|
+
// ../../components/ui/ThemeToggleHeadless.tsx
|
|
8613
|
+
var import_lucide_react24 = require("lucide-react");
|
|
8614
|
+
var import_react24 = require("react");
|
|
8615
|
+
var import_react_dom9 = require("react-dom");
|
|
8616
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
8617
|
+
function ThemeToggleHeadless({
|
|
8618
|
+
theme,
|
|
8619
|
+
onChange,
|
|
8620
|
+
labels,
|
|
8621
|
+
className
|
|
8622
|
+
}) {
|
|
8623
|
+
const [isOpen, setIsOpen] = (0, import_react24.useState)(false);
|
|
8624
|
+
const [mounted, setMounted] = (0, import_react24.useState)(false);
|
|
8625
|
+
const triggerRef = (0, import_react24.useRef)(null);
|
|
8626
|
+
const [dropdownPosition, setDropdownPosition] = (0, import_react24.useState)(null);
|
|
8627
|
+
(0, import_react24.useEffect)(() => setMounted(true), []);
|
|
8628
|
+
const themes = [
|
|
8629
|
+
{ value: "light", label: labels?.light ?? "Light", icon: import_lucide_react24.Sun },
|
|
8630
|
+
{ value: "dark", label: labels?.dark ?? "Dark", icon: import_lucide_react24.Moon },
|
|
8631
|
+
{ value: "system", label: labels?.system ?? "System", icon: import_lucide_react24.Monitor }
|
|
8632
|
+
];
|
|
8633
|
+
const current = mounted ? themes.find((t) => t.value === theme) || themes[2] : themes[2];
|
|
8634
|
+
const CurrentIcon = current.icon;
|
|
8635
|
+
const calculatePosition = () => {
|
|
8636
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
8637
|
+
if (!rect) return null;
|
|
8638
|
+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
8639
|
+
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
8640
|
+
const width = 192;
|
|
8641
|
+
const left = rect.right + scrollLeft - width;
|
|
8642
|
+
const top = rect.bottom + scrollTop + 8;
|
|
8643
|
+
return { top, left, width };
|
|
8644
|
+
};
|
|
8645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: cn("relative", className), children: [
|
|
8646
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8647
|
+
Button_default,
|
|
8648
|
+
{
|
|
8649
|
+
variant: "ghost",
|
|
8650
|
+
size: "icon",
|
|
8651
|
+
ref: triggerRef,
|
|
8652
|
+
onClick: () => {
|
|
8653
|
+
const next = !isOpen;
|
|
8654
|
+
if (next) {
|
|
8655
|
+
const pos = calculatePosition();
|
|
8656
|
+
if (pos) setDropdownPosition(pos);
|
|
8657
|
+
}
|
|
8658
|
+
setIsOpen(next);
|
|
8659
|
+
},
|
|
8660
|
+
className: "bg-muted hover:bg-accent",
|
|
8661
|
+
"aria-haspopup": "menu",
|
|
8662
|
+
"aria-expanded": isOpen,
|
|
8663
|
+
"aria-label": labels?.heading ?? "Theme",
|
|
8664
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(CurrentIcon, { className: "h-5 w-5" })
|
|
8665
|
+
}
|
|
8666
|
+
),
|
|
8667
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
8668
|
+
typeof window !== "undefined" && (0, import_react_dom9.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
|
|
8669
|
+
typeof window !== "undefined" && dropdownPosition && (0, import_react_dom9.createPortal)(
|
|
8670
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
8671
|
+
"div",
|
|
8672
|
+
{
|
|
8673
|
+
className: "z-[9999] bg-card border border-border rounded-lg shadow-lg overflow-hidden",
|
|
8674
|
+
style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
|
|
8675
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
8676
|
+
role: "menu",
|
|
8677
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "p-2", children: [
|
|
8678
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Theme" }),
|
|
8679
|
+
themes.map((opt) => {
|
|
8680
|
+
const Icon = opt.icon;
|
|
8681
|
+
const active = theme === opt.value;
|
|
8682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
8683
|
+
Button_default,
|
|
8684
|
+
{
|
|
8685
|
+
variant: "ghost",
|
|
8686
|
+
size: "sm",
|
|
8687
|
+
onClick: () => {
|
|
8688
|
+
onChange(opt.value);
|
|
8689
|
+
setIsOpen(false);
|
|
8690
|
+
},
|
|
8691
|
+
className: cn(
|
|
8692
|
+
"w-full justify-start gap-3 h-auto py-2 px-3",
|
|
8693
|
+
active && "bg-primary/10 text-primary"
|
|
8694
|
+
),
|
|
8695
|
+
role: "menuitemradio",
|
|
8696
|
+
"aria-checked": active,
|
|
8697
|
+
children: [
|
|
8698
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Icon, { className: "h-4 w-4" }),
|
|
8699
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex-1 text-left", children: opt.label }),
|
|
8700
|
+
active && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "w-2 h-2 rounded-full bg-primary" })
|
|
8701
|
+
]
|
|
8702
|
+
},
|
|
8703
|
+
opt.value
|
|
8704
|
+
);
|
|
8705
|
+
})
|
|
8706
|
+
] })
|
|
8707
|
+
}
|
|
8708
|
+
),
|
|
8709
|
+
document.body
|
|
8710
|
+
)
|
|
8711
|
+
] })
|
|
8712
|
+
] });
|
|
8713
|
+
}
|
|
8714
|
+
|
|
8715
|
+
// ../../components/ui/LanguageSwitcherHeadless.tsx
|
|
8716
|
+
var import_react25 = require("react");
|
|
8717
|
+
var import_react_dom10 = require("react-dom");
|
|
8718
|
+
var import_lucide_react25 = require("lucide-react");
|
|
8719
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
8720
|
+
function LanguageSwitcherHeadless({
|
|
8721
|
+
locales,
|
|
8722
|
+
currentLocale,
|
|
8723
|
+
onSwitch,
|
|
8724
|
+
labels,
|
|
8725
|
+
className
|
|
8726
|
+
}) {
|
|
8727
|
+
const [isOpen, setIsOpen] = (0, import_react25.useState)(false);
|
|
8728
|
+
const [dropdownPosition, setDropdownPosition] = (0, import_react25.useState)(null);
|
|
8729
|
+
const triggerButtonRef = (0, import_react25.useRef)(null);
|
|
8730
|
+
const currentLanguage = locales.find((l) => l.code === currentLocale) || locales[0];
|
|
8731
|
+
const calculatePosition = () => {
|
|
8732
|
+
const rect = triggerButtonRef.current?.getBoundingClientRect();
|
|
8733
|
+
if (!rect) return null;
|
|
8734
|
+
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
8735
|
+
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
|
|
8736
|
+
const width = 192;
|
|
8737
|
+
const left = rect.right + scrollLeft - width;
|
|
8738
|
+
const top = rect.bottom + scrollTop + 8;
|
|
8739
|
+
return { top, left, width };
|
|
8740
|
+
};
|
|
8741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cn("relative", className), children: [
|
|
8742
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8743
|
+
Button_default,
|
|
8744
|
+
{
|
|
8745
|
+
variant: "ghost",
|
|
8746
|
+
size: "icon",
|
|
8747
|
+
ref: triggerButtonRef,
|
|
8748
|
+
onClick: () => {
|
|
8749
|
+
const next = !isOpen;
|
|
8750
|
+
if (next) {
|
|
8751
|
+
const pos = calculatePosition();
|
|
8752
|
+
if (pos) setDropdownPosition(pos);
|
|
8753
|
+
}
|
|
8754
|
+
setIsOpen(next);
|
|
8755
|
+
},
|
|
8756
|
+
className: "bg-muted hover:bg-accent",
|
|
8757
|
+
"aria-haspopup": "menu",
|
|
8758
|
+
"aria-expanded": isOpen,
|
|
8759
|
+
"aria-label": labels?.heading ?? "Language",
|
|
8760
|
+
title: labels?.heading ?? "Language",
|
|
8761
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react25.Globe, { className: "h-5 w-5" })
|
|
8762
|
+
}
|
|
8763
|
+
),
|
|
8764
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
8765
|
+
typeof window !== "undefined" && (0, import_react_dom10.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fixed inset-0 z-[9998]", onClick: () => setIsOpen(false) }), document.body),
|
|
8766
|
+
typeof window !== "undefined" && dropdownPosition && (0, import_react_dom10.createPortal)(
|
|
8767
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
8768
|
+
"div",
|
|
8769
|
+
{
|
|
8770
|
+
className: "z-[9999] bg-card border border-border rounded-lg shadow-lg overflow-hidden",
|
|
8771
|
+
style: { position: "absolute", top: dropdownPosition.top, left: dropdownPosition.left, width: dropdownPosition.width },
|
|
8772
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
8773
|
+
role: "menu",
|
|
8774
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "p-2", children: [
|
|
8775
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "px-3 py-2 text-sm font-medium text-muted-foreground border-b border-border mb-2", children: labels?.heading ?? "Language" }),
|
|
8776
|
+
locales.map((language) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
8777
|
+
Button_default,
|
|
8778
|
+
{
|
|
8779
|
+
variant: "ghost",
|
|
8780
|
+
size: "sm",
|
|
8781
|
+
onClick: () => {
|
|
8782
|
+
onSwitch(language.code);
|
|
8783
|
+
setIsOpen(false);
|
|
8784
|
+
},
|
|
8785
|
+
className: cn("w-full justify-start gap-3 h-auto py-2 px-3", currentLocale === language.code && "bg-primary/10 text-primary"),
|
|
8786
|
+
role: "menuitemradio",
|
|
8787
|
+
"aria-checked": currentLocale === language.code,
|
|
8788
|
+
children: [
|
|
8789
|
+
language.flag && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-lg", children: language.flag }),
|
|
8790
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex-1 text-left", children: language.name }),
|
|
8791
|
+
currentLocale === language.code && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "w-2 h-2 rounded-full bg-primary" })
|
|
8792
|
+
]
|
|
8793
|
+
},
|
|
8794
|
+
language.code
|
|
8795
|
+
))
|
|
8796
|
+
] })
|
|
8797
|
+
}
|
|
8798
|
+
),
|
|
8799
|
+
document.body
|
|
8800
|
+
)
|
|
8801
|
+
] })
|
|
8802
|
+
] });
|
|
8803
|
+
}
|
|
8804
|
+
|
|
8608
8805
|
// locales/en.json
|
|
8609
8806
|
var en_default = {
|
|
8610
8807
|
Common: {
|
|
@@ -8779,6 +8976,8 @@ function getUnderverseMessages(locale = "en") {
|
|
|
8779
8976
|
Input,
|
|
8780
8977
|
InteractiveBadge,
|
|
8781
8978
|
Label,
|
|
8979
|
+
LanguageSwitcher,
|
|
8980
|
+
LanguageSwitcherHeadless,
|
|
8782
8981
|
LoadingBar,
|
|
8783
8982
|
LoadingDots,
|
|
8784
8983
|
LoadingSpinner,
|
|
@@ -8819,6 +9018,8 @@ function getUnderverseMessages(locale = "en") {
|
|
|
8819
9018
|
Tabs,
|
|
8820
9019
|
TagBadge,
|
|
8821
9020
|
Textarea,
|
|
9021
|
+
ThemeToggle,
|
|
9022
|
+
ThemeToggleHeadless,
|
|
8822
9023
|
ToastProvider,
|
|
8823
9024
|
Tooltip,
|
|
8824
9025
|
VARIANT_STYLES_ALERT,
|