@tapizlabs/ui 0.1.5 → 0.1.6
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.d.ts +2 -1
- package/dist/index.js +199 -81
- package/dist/index.js.map +1 -1
- package/dist/theme.css +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -408,9 +408,10 @@ interface PageHeaderProps {
|
|
|
408
408
|
subtitle?: string;
|
|
409
409
|
action?: ReactNode;
|
|
410
410
|
icon?: ReactNode;
|
|
411
|
+
banner?: ReactNode;
|
|
411
412
|
className?: string;
|
|
412
413
|
}
|
|
413
|
-
declare function PageHeader({ title, subtitle, action, icon, className }: PageHeaderProps): react.JSX.Element;
|
|
414
|
+
declare function PageHeader({ title, subtitle, action, icon, banner, className }: PageHeaderProps): react.JSX.Element;
|
|
414
415
|
|
|
415
416
|
interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> {
|
|
416
417
|
value: string;
|
package/dist/index.js
CHANGED
|
@@ -992,7 +992,7 @@ function Toast({ message, ok, durationMs = 5e3 }) {
|
|
|
992
992
|
const borderColor = ok ? "var(--color-good)" : "var(--color-warn)";
|
|
993
993
|
const accentColor = ok ? "var(--color-good)" : "var(--color-warn)";
|
|
994
994
|
return createPortal(
|
|
995
|
-
/* @__PURE__ */ jsx20("div", { className: "pointer-events-none fixed bottom-20 left-4 right-4 z-
|
|
995
|
+
/* @__PURE__ */ jsx20("div", { className: "pointer-events-none fixed bottom-20 left-4 right-4 z-9999 flex justify-center min-[600px]:bottom-auto min-[600px]:left-auto min-[600px]:right-5 min-[600px]:top-5 min-[600px]:justify-end", children: /* @__PURE__ */ jsxs13(
|
|
996
996
|
"div",
|
|
997
997
|
{
|
|
998
998
|
className: `${transform} pointer-events-auto relative flex w-full max-w-sm items-center gap-2.5 overflow-hidden px-4 py-3 text-sm font-medium transition-all duration-300 sm:w-auto sm:max-w-xs`,
|
|
@@ -1095,33 +1095,82 @@ function DefaultErrorFallback({
|
|
|
1095
1095
|
label = "Tapiz UI \xB7 Runtime Error",
|
|
1096
1096
|
reloadLabel = "Reload page"
|
|
1097
1097
|
}) {
|
|
1098
|
-
return /* @__PURE__ */ jsxs16(
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
/* @__PURE__ */ jsx23(
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1098
|
+
return /* @__PURE__ */ jsxs16(
|
|
1099
|
+
"div",
|
|
1100
|
+
{
|
|
1101
|
+
className: "fixed inset-0 flex flex-col items-center justify-center overflow-hidden px-6",
|
|
1102
|
+
style: { background: "var(--color-ink-100)" },
|
|
1103
|
+
children: [
|
|
1104
|
+
/* @__PURE__ */ jsx23(GridBg, {}),
|
|
1105
|
+
/* @__PURE__ */ jsx23(Spotlight, { color: "rgba(255,100,100,0.06)" }),
|
|
1106
|
+
/* @__PURE__ */ jsxs16(
|
|
1107
|
+
"div",
|
|
1108
|
+
{
|
|
1109
|
+
className: "relative z-10 flex w-full max-w-sm flex-col items-center gap-6 text-center",
|
|
1110
|
+
style: { animation: "var(--animate-fade-in-up)" },
|
|
1111
|
+
children: [
|
|
1112
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
1113
|
+
/* @__PURE__ */ jsx23(
|
|
1114
|
+
"div",
|
|
1115
|
+
{
|
|
1116
|
+
className: "font-mono font-bold leading-none",
|
|
1117
|
+
style: { fontSize: "clamp(72px,16vw,120px)", color: "var(--color-border-hi)", letterSpacing: "-0.04em" },
|
|
1118
|
+
children: "500"
|
|
1119
|
+
}
|
|
1120
|
+
),
|
|
1121
|
+
/* @__PURE__ */ jsx23(
|
|
1122
|
+
"div",
|
|
1123
|
+
{
|
|
1124
|
+
className: "mt-1 h-0.5 w-full",
|
|
1125
|
+
style: { background: "linear-gradient(90deg,transparent,rgba(255,80,80,0.7),transparent)", opacity: 0.5 }
|
|
1126
|
+
}
|
|
1127
|
+
)
|
|
1128
|
+
] }),
|
|
1129
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1.5", children: [
|
|
1130
|
+
/* @__PURE__ */ jsx23("p", { className: "text-base font-semibold", style: { color: "var(--color-txt-1)" }, children: title }),
|
|
1131
|
+
/* @__PURE__ */ jsx23("p", { className: "font-mono text-[11px] leading-relaxed", style: { color: "var(--color-txt-3)" }, children: description })
|
|
1132
|
+
] }),
|
|
1133
|
+
/* @__PURE__ */ jsx23(
|
|
1134
|
+
"div",
|
|
1135
|
+
{
|
|
1136
|
+
className: "font-mono text-[9px] uppercase px-2 py-1",
|
|
1137
|
+
style: {
|
|
1138
|
+
letterSpacing: ".2em",
|
|
1139
|
+
color: "rgba(255,80,80,0.9)",
|
|
1140
|
+
border: "1px solid rgba(255,80,80,0.25)",
|
|
1141
|
+
background: "rgba(255,80,80,0.05)"
|
|
1142
|
+
},
|
|
1143
|
+
children: label
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
/* @__PURE__ */ jsx23("div", { className: "w-full", children: /* @__PURE__ */ jsxs16(
|
|
1147
|
+
"button",
|
|
1148
|
+
{
|
|
1149
|
+
type: "button",
|
|
1150
|
+
onClick: () => window.location.reload(),
|
|
1151
|
+
style: {
|
|
1152
|
+
width: "100%",
|
|
1153
|
+
padding: "10px",
|
|
1154
|
+
fontSize: "12px",
|
|
1155
|
+
background: "var(--color-primary-300)",
|
|
1156
|
+
color: "var(--color-ink-100)",
|
|
1157
|
+
border: "none",
|
|
1158
|
+
cursor: "pointer",
|
|
1159
|
+
fontFamily: "var(--font-mono)",
|
|
1160
|
+
letterSpacing: "0.05em"
|
|
1161
|
+
},
|
|
1162
|
+
children: [
|
|
1163
|
+
reloadLabel,
|
|
1164
|
+
" \u2192"
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
) })
|
|
1168
|
+
]
|
|
1169
|
+
}
|
|
1170
|
+
)
|
|
1171
|
+
]
|
|
1172
|
+
}
|
|
1173
|
+
);
|
|
1125
1174
|
}
|
|
1126
1175
|
function GridBg() {
|
|
1127
1176
|
return /* @__PURE__ */ jsx23("div", { className: "pointer-events-none absolute inset-0 opacity-50 bg-[linear-gradient(var(--color-border)_1px,transparent_1px),linear-gradient(90deg,var(--color-border)_1px,transparent_1px)] bg-size-[32px_32px]" });
|
|
@@ -1312,11 +1361,12 @@ function Tooltip({ text, children, position = "top", align = "center", width = "
|
|
|
1312
1361
|
/* @__PURE__ */ jsxs19(
|
|
1313
1362
|
"span",
|
|
1314
1363
|
{
|
|
1315
|
-
className: `pointer-events-none absolute ${alignClass}
|
|
1364
|
+
className: `pointer-events-none absolute ${alignClass} ${width} w-max px-2.5 py-1.5
|
|
1316
1365
|
text-center text-[11px] leading-snug
|
|
1317
1366
|
opacity-0 group-hover:opacity-100 transition-opacity duration-150
|
|
1318
1367
|
${position === "top" ? "bottom-full mb-2" : "top-full mt-2"}`,
|
|
1319
1368
|
style: {
|
|
1369
|
+
zIndex: 60,
|
|
1320
1370
|
background: "var(--color-ink-300)",
|
|
1321
1371
|
border: "1px solid var(--color-border-hi)",
|
|
1322
1372
|
color: "var(--color-txt-2)",
|
|
@@ -1477,7 +1527,7 @@ function InfoBanner(props) {
|
|
|
1477
1527
|
const { text, variant = "info", className: className2 = "" } = props;
|
|
1478
1528
|
const styles = variant === "warn" ? "bg-warn/8 border-warn/25 text-warn" : variant === "lock" ? "bg-warn/8 border-warn/30 text-warn" : "bg-primary-500/10 border-primary-100 text-primary-500";
|
|
1479
1529
|
const icon = variant === "lock" ? /* @__PURE__ */ jsx32(LockIcon, { size: 14, className: "mt-1 shrink-0" }) : /* @__PURE__ */ jsx32(Info, { size: 14, className: "mt-1 shrink-0" });
|
|
1480
|
-
return /* @__PURE__ */ jsxs22("div", { className: `flex items-start gap-2 border px-3 py-2.5 text-[13px] ${styles} ${className2}`, children: [
|
|
1530
|
+
return /* @__PURE__ */ jsxs22("div", { className: `app-info-banner flex items-start gap-2 border px-3 py-2.5 text-[13px] ${styles} ${className2}`, children: [
|
|
1481
1531
|
icon,
|
|
1482
1532
|
/* @__PURE__ */ jsx32("p", { style: { fontFamily: "var(--font-mono)" }, children: text })
|
|
1483
1533
|
] });
|
|
@@ -1486,7 +1536,7 @@ function InfoBanner(props) {
|
|
|
1486
1536
|
return /* @__PURE__ */ jsxs22(
|
|
1487
1537
|
"div",
|
|
1488
1538
|
{
|
|
1489
|
-
className: `px-4 py-3 ${className}`,
|
|
1539
|
+
className: `app-info-banner px-4 py-3 ${className}`,
|
|
1490
1540
|
style: {
|
|
1491
1541
|
background: "rgba(94,231,255,0.04)",
|
|
1492
1542
|
border: "1px solid rgba(94,231,255,0.12)",
|
|
@@ -1509,20 +1559,23 @@ function InfoBanner(props) {
|
|
|
1509
1559
|
|
|
1510
1560
|
// src/components/shared/PageHeader.tsx
|
|
1511
1561
|
import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1512
|
-
function PageHeader({ title, subtitle, action, icon, className = "" }) {
|
|
1562
|
+
function PageHeader({ title, subtitle, action, icon, banner, className = "" }) {
|
|
1513
1563
|
return /* @__PURE__ */ jsxs23(
|
|
1514
1564
|
"div",
|
|
1515
1565
|
{
|
|
1516
|
-
className: `mb-5 flex flex-col gap-3 border-b border-border pb-4 animate-fade-in-up
|
|
1566
|
+
className: `page-header mb-5 flex flex-col gap-3 border-b border-border pb-4 animate-fade-in-up ${className}`.trim(),
|
|
1517
1567
|
children: [
|
|
1518
|
-
/* @__PURE__ */ jsxs23("div", { children: [
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1568
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
1569
|
+
/* @__PURE__ */ jsxs23("div", { children: [
|
|
1570
|
+
subtitle ? /* @__PURE__ */ jsx33("div", { className: "kicker mb-1.5", children: subtitle }) : null,
|
|
1571
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2.5", children: [
|
|
1572
|
+
icon ? /* @__PURE__ */ jsx33("span", { className: "text-primary-300", children: icon }) : null,
|
|
1573
|
+
/* @__PURE__ */ jsx33("h2", { className: "font-(--font-display) text-[22px] tracking-[-0.03em] text-txt-1", children: title })
|
|
1574
|
+
] })
|
|
1575
|
+
] }),
|
|
1576
|
+
action ? /* @__PURE__ */ jsx33("div", { children: action }) : null
|
|
1524
1577
|
] }),
|
|
1525
|
-
|
|
1578
|
+
banner ? banner : null
|
|
1526
1579
|
]
|
|
1527
1580
|
}
|
|
1528
1581
|
);
|
|
@@ -1663,7 +1716,8 @@ function StatusBadge({ label, variant = "default", className = "" }) {
|
|
|
1663
1716
|
}
|
|
1664
1717
|
|
|
1665
1718
|
// src/components/shared/ActionMenu.tsx
|
|
1666
|
-
import { useEffect as useEffect2, useRef as useRef2, useState as useState5 } from "react";
|
|
1719
|
+
import { useEffect as useEffect2, useLayoutEffect, useRef as useRef2, useState as useState5 } from "react";
|
|
1720
|
+
import { createPortal as createPortal4 } from "react-dom";
|
|
1667
1721
|
import { Fragment, jsx as jsx38, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1668
1722
|
var defaultMenuStyle = {
|
|
1669
1723
|
background: "var(--color-ink-200)",
|
|
@@ -1680,23 +1734,117 @@ function ActionMenu({
|
|
|
1680
1734
|
buttonSize = "sm",
|
|
1681
1735
|
buttonVariant = "secondary",
|
|
1682
1736
|
buttonClassName = "",
|
|
1683
|
-
menuClassName
|
|
1737
|
+
menuClassName,
|
|
1684
1738
|
menuStyle,
|
|
1685
1739
|
fullWidth = false,
|
|
1686
1740
|
closeLabel
|
|
1687
1741
|
}) {
|
|
1688
1742
|
const [open, setOpen] = useState5(false);
|
|
1689
|
-
const
|
|
1743
|
+
const [pos, setPos] = useState5(null);
|
|
1744
|
+
const btnRef = useRef2(null);
|
|
1745
|
+
const menuRef = useRef2(null);
|
|
1746
|
+
useLayoutEffect(() => {
|
|
1747
|
+
if (!open || !btnRef.current) return;
|
|
1748
|
+
const updatePosition = () => {
|
|
1749
|
+
const buttonElement = btnRef.current;
|
|
1750
|
+
if (!buttonElement) return;
|
|
1751
|
+
const rect = buttonElement.getBoundingClientRect();
|
|
1752
|
+
const viewportPadding = 8;
|
|
1753
|
+
const menuOffset = 4;
|
|
1754
|
+
const menuW = Math.min(320, window.innerWidth - viewportPadding * 2);
|
|
1755
|
+
const left = Math.max(
|
|
1756
|
+
viewportPadding,
|
|
1757
|
+
Math.min(rect.right - menuW, window.innerWidth - menuW - viewportPadding)
|
|
1758
|
+
);
|
|
1759
|
+
const estimatedMenuHeight = Math.min(320, items.length * 44 + 16);
|
|
1760
|
+
const spaceAbove = Math.max(0, rect.top - viewportPadding - menuOffset);
|
|
1761
|
+
const spaceBelow = Math.max(0, window.innerHeight - rect.bottom - viewportPadding - menuOffset);
|
|
1762
|
+
const preferBelow = spaceBelow >= estimatedMenuHeight || spaceBelow >= spaceAbove;
|
|
1763
|
+
if (preferBelow) {
|
|
1764
|
+
setPos({
|
|
1765
|
+
top: Math.min(rect.bottom + menuOffset, window.innerHeight - viewportPadding),
|
|
1766
|
+
left,
|
|
1767
|
+
width: menuW,
|
|
1768
|
+
maxHeight: Math.max(120, spaceBelow)
|
|
1769
|
+
});
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
setPos({
|
|
1773
|
+
bottom: Math.max(window.innerHeight - rect.top + menuOffset, viewportPadding),
|
|
1774
|
+
left,
|
|
1775
|
+
width: menuW,
|
|
1776
|
+
maxHeight: Math.max(120, spaceAbove)
|
|
1777
|
+
});
|
|
1778
|
+
};
|
|
1779
|
+
updatePosition();
|
|
1780
|
+
window.addEventListener("resize", updatePosition);
|
|
1781
|
+
document.addEventListener("scroll", updatePosition, true);
|
|
1782
|
+
return () => {
|
|
1783
|
+
window.removeEventListener("resize", updatePosition);
|
|
1784
|
+
document.removeEventListener("scroll", updatePosition, true);
|
|
1785
|
+
};
|
|
1786
|
+
}, [items.length, open]);
|
|
1690
1787
|
useEffect2(() => {
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1788
|
+
if (!open) return;
|
|
1789
|
+
function handle(e) {
|
|
1790
|
+
if (e instanceof KeyboardEvent) {
|
|
1791
|
+
if (e.key === "Escape") setOpen(false);
|
|
1792
|
+
return;
|
|
1694
1793
|
}
|
|
1794
|
+
const target = e.target;
|
|
1795
|
+
if (btnRef.current?.contains(target) || menuRef.current?.contains(target)) return;
|
|
1796
|
+
setOpen(false);
|
|
1695
1797
|
}
|
|
1696
|
-
document.addEventListener("mousedown",
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1798
|
+
document.addEventListener("mousedown", handle);
|
|
1799
|
+
document.addEventListener("keydown", handle);
|
|
1800
|
+
return () => {
|
|
1801
|
+
document.removeEventListener("mousedown", handle);
|
|
1802
|
+
document.removeEventListener("keydown", handle);
|
|
1803
|
+
};
|
|
1804
|
+
}, [open]);
|
|
1805
|
+
const menuNode = open && pos ? /* @__PURE__ */ jsxs26(Fragment, { children: [
|
|
1806
|
+
/* @__PURE__ */ jsx38("div", { className: "fixed inset-0 z-9998", onClick: () => setOpen(false) }),
|
|
1807
|
+
/* @__PURE__ */ jsx38(
|
|
1808
|
+
"div",
|
|
1809
|
+
{
|
|
1810
|
+
ref: menuRef,
|
|
1811
|
+
className: menuClassName ?? "overflow-auto",
|
|
1812
|
+
style: {
|
|
1813
|
+
position: "fixed",
|
|
1814
|
+
top: pos.top !== void 0 ? pos.top : void 0,
|
|
1815
|
+
bottom: pos.bottom !== void 0 ? pos.bottom : void 0,
|
|
1816
|
+
left: pos.left,
|
|
1817
|
+
width: pos.width,
|
|
1818
|
+
maxWidth: "calc(100vw - 16px)",
|
|
1819
|
+
zIndex: 9999,
|
|
1820
|
+
...defaultMenuStyle,
|
|
1821
|
+
maxHeight: pos.maxHeight ?? defaultMenuStyle.maxHeight,
|
|
1822
|
+
...menuStyle
|
|
1823
|
+
},
|
|
1824
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxs26("div", { children: [
|
|
1825
|
+
index > 0 && item.danger ? /* @__PURE__ */ jsx38("div", { style: { borderTop: "1px solid var(--color-border)" } }) : null,
|
|
1826
|
+
/* @__PURE__ */ jsxs26(
|
|
1827
|
+
"button",
|
|
1828
|
+
{
|
|
1829
|
+
type: "button",
|
|
1830
|
+
className: itemBaseClass,
|
|
1831
|
+
style: { color: item.danger ? "var(--color-warn)" : "var(--color-txt-2)" },
|
|
1832
|
+
disabled: item.disabled || item.loading,
|
|
1833
|
+
onClick: () => {
|
|
1834
|
+
setOpen(false);
|
|
1835
|
+
item.onSelect();
|
|
1836
|
+
},
|
|
1837
|
+
children: [
|
|
1838
|
+
item.loading ? /* @__PURE__ */ jsx38(Spinner, { color: "text-[var(--color-txt-3)]" }) : /* @__PURE__ */ jsx38("span", { className: item.danger ? "shrink-0 text-warn" : "shrink-0 text-primary-300", children: item.icon }),
|
|
1839
|
+
/* @__PURE__ */ jsx38("span", { children: item.label })
|
|
1840
|
+
]
|
|
1841
|
+
}
|
|
1842
|
+
)
|
|
1843
|
+
] }, item.key))
|
|
1844
|
+
}
|
|
1845
|
+
)
|
|
1846
|
+
] }) : null;
|
|
1847
|
+
return /* @__PURE__ */ jsxs26("div", { ref: btnRef, className: fullWidth ? "relative w-full" : "relative inline-block max-w-full", children: [
|
|
1700
1848
|
/* @__PURE__ */ jsx38(
|
|
1701
1849
|
Button,
|
|
1702
1850
|
{
|
|
@@ -1710,37 +1858,7 @@ function ActionMenu({
|
|
|
1710
1858
|
children: label
|
|
1711
1859
|
}
|
|
1712
1860
|
),
|
|
1713
|
-
|
|
1714
|
-
/* @__PURE__ */ jsx38(
|
|
1715
|
-
"button",
|
|
1716
|
-
{
|
|
1717
|
-
type: "button",
|
|
1718
|
-
className: "fixed inset-0 z-40 bg-black/10 backdrop-blur-[3px]",
|
|
1719
|
-
"aria-label": closeLabel ?? label,
|
|
1720
|
-
onClick: () => setOpen(false)
|
|
1721
|
-
}
|
|
1722
|
-
),
|
|
1723
|
-
/* @__PURE__ */ jsx38("div", { className: menuClassName, style: { ...defaultMenuStyle, ...menuStyle }, children: items.map((item, index) => /* @__PURE__ */ jsxs26("div", { children: [
|
|
1724
|
-
index > 0 && item.danger ? /* @__PURE__ */ jsx38("div", { style: { borderTop: "1px solid var(--color-border)" } }) : null,
|
|
1725
|
-
/* @__PURE__ */ jsxs26(
|
|
1726
|
-
"button",
|
|
1727
|
-
{
|
|
1728
|
-
type: "button",
|
|
1729
|
-
className: itemBaseClass,
|
|
1730
|
-
style: { color: item.danger ? "var(--color-warn)" : "var(--color-txt-2)" },
|
|
1731
|
-
disabled: item.disabled || item.loading,
|
|
1732
|
-
onClick: () => {
|
|
1733
|
-
setOpen(false);
|
|
1734
|
-
item.onSelect();
|
|
1735
|
-
},
|
|
1736
|
-
children: [
|
|
1737
|
-
item.loading ? /* @__PURE__ */ jsx38(Spinner, { color: "text-[var(--color-txt-3)]" }) : /* @__PURE__ */ jsx38("span", { className: item.danger ? "shrink-0 text-warn" : "shrink-0 text-primary-300", children: item.icon }),
|
|
1738
|
-
/* @__PURE__ */ jsx38("span", { children: item.label })
|
|
1739
|
-
]
|
|
1740
|
-
}
|
|
1741
|
-
)
|
|
1742
|
-
] }, item.key)) })
|
|
1743
|
-
] }) : null
|
|
1861
|
+
typeof document !== "undefined" ? createPortal4(menuNode, document.body) : null
|
|
1744
1862
|
] });
|
|
1745
1863
|
}
|
|
1746
1864
|
|