@vespera-ui/vue 0.5.0 → 0.6.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.cjs CHANGED
@@ -22,10 +22,12 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  Accordion: () => Accordion,
24
24
  Alert: () => Alert,
25
+ AreaChart: () => AreaChart,
25
26
  Avatar: () => Avatar,
26
27
  AvatarGroup: () => AvatarGroup,
27
28
  Badge: () => Badge,
28
29
  Banner: () => Banner,
30
+ BarChart: () => BarChart,
29
31
  Breadcrumb: () => Breadcrumb,
30
32
  Button: () => Button,
31
33
  Card: () => Card,
@@ -44,6 +46,7 @@ __export(index_exports, {
44
46
  Kbd: () => Kbd,
45
47
  NativeSelect: () => NativeSelect,
46
48
  NumberStepper: () => NumberStepper,
49
+ OTPInput: () => OTPInput,
47
50
  Pagination: () => Pagination,
48
51
  Progress: () => Progress,
49
52
  Radio: () => Radio,
@@ -61,6 +64,8 @@ __export(index_exports, {
61
64
  Tag: () => Tag,
62
65
  Textarea: () => Textarea,
63
66
  Timeline: () => Timeline,
67
+ Tree: () => Tree,
68
+ niceNum: () => niceNum,
64
69
  smoothPath: () => smoothPath
65
70
  });
66
71
  module.exports = __toCommonJS(index_exports);
@@ -1404,14 +1409,338 @@ var InlineEdit = (0, import_vue.defineComponent)({
1404
1409
  );
1405
1410
  }
1406
1411
  });
1412
+ var svgIconClass = (d, size, cls) => (0, import_vue.h)(
1413
+ "svg",
1414
+ {
1415
+ class: cls,
1416
+ viewBox: "0 0 24 24",
1417
+ width: size,
1418
+ height: size,
1419
+ fill: "none",
1420
+ stroke: "currentColor",
1421
+ "stroke-width": 2,
1422
+ "stroke-linecap": "round",
1423
+ "stroke-linejoin": "round"
1424
+ },
1425
+ [(0, import_vue.h)("path", { d })]
1426
+ );
1427
+ var ICON_LAYERS = "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5";
1428
+ var treeNodeId = (n) => n.id ?? n.label;
1429
+ var VspTreeNode = (0, import_vue.defineComponent)({
1430
+ name: "VspTreeNode",
1431
+ props: {
1432
+ node: { type: Object, required: true },
1433
+ expanded: { type: Object, required: true },
1434
+ selected: { type: String, default: null },
1435
+ toggle: { type: Function, required: true },
1436
+ select: { type: Function, required: true }
1437
+ },
1438
+ setup(props) {
1439
+ return () => {
1440
+ const node = props.node;
1441
+ const id = treeNodeId(node);
1442
+ const kids = node.children ?? [];
1443
+ const hasKids = kids.length > 0;
1444
+ const open = props.expanded.has(id);
1445
+ return (0, import_vue.h)("div", null, [
1446
+ (0, import_vue.h)(
1447
+ "div",
1448
+ {
1449
+ class: cx("ui-tree-row", open && "open", props.selected === id && "sel"),
1450
+ onClick: () => {
1451
+ if (hasKids) props.toggle(id);
1452
+ props.select(id);
1453
+ }
1454
+ },
1455
+ [
1456
+ hasKids ? svgIconClass(ICON_PATHS.chevR, 16, "tw-chev") : (0, import_vue.h)("span", { style: { width: "16px", flexShrink: 0 } }),
1457
+ svgIconClass(hasKids ? ICON_LAYERS : ICON_DOC, 16, "tw-icon"),
1458
+ (0, import_vue.h)(
1459
+ "span",
1460
+ {
1461
+ style: {
1462
+ flex: 1,
1463
+ minWidth: 0,
1464
+ overflow: "hidden",
1465
+ textOverflow: "ellipsis",
1466
+ whiteSpace: "nowrap"
1467
+ }
1468
+ },
1469
+ node.label
1470
+ ),
1471
+ node.badge != null ? (0, import_vue.h)(
1472
+ "span",
1473
+ { class: "mono", style: { fontSize: "11px", color: "var(--text-faint)" } },
1474
+ node.badge
1475
+ ) : null
1476
+ ]
1477
+ ),
1478
+ hasKids && open ? (0, import_vue.h)(
1479
+ "div",
1480
+ { class: "ui-tree-children" },
1481
+ kids.map(
1482
+ (c, i) => (0, import_vue.h)(VspTreeNode, {
1483
+ key: i,
1484
+ node: c,
1485
+ expanded: props.expanded,
1486
+ selected: props.selected,
1487
+ toggle: props.toggle,
1488
+ select: props.select
1489
+ })
1490
+ )
1491
+ ) : null
1492
+ ]);
1493
+ };
1494
+ }
1495
+ });
1496
+ var Tree = (0, import_vue.defineComponent)({
1497
+ name: "VspTree",
1498
+ props: {
1499
+ data: { type: Array, default: () => [] },
1500
+ defaultExpanded: { type: Array, default: () => [] }
1501
+ },
1502
+ setup(props) {
1503
+ const expanded = (0, import_vue.ref)(new Set(props.defaultExpanded));
1504
+ const selected = (0, import_vue.ref)(null);
1505
+ const toggle = (id) => {
1506
+ const n = new Set(expanded.value);
1507
+ if (n.has(id)) n.delete(id);
1508
+ else n.add(id);
1509
+ expanded.value = n;
1510
+ };
1511
+ return () => (0, import_vue.h)(
1512
+ "div",
1513
+ { class: "ui-tree" },
1514
+ props.data.map(
1515
+ (n, i) => (0, import_vue.h)(VspTreeNode, {
1516
+ key: i,
1517
+ node: n,
1518
+ expanded: expanded.value,
1519
+ selected: selected.value,
1520
+ toggle,
1521
+ select: (id) => selected.value = id
1522
+ })
1523
+ )
1524
+ );
1525
+ }
1526
+ });
1527
+ var OTPInput = (0, import_vue.defineComponent)({
1528
+ name: "VspOTPInput",
1529
+ props: {
1530
+ length: { type: Number, default: 6 },
1531
+ modelValue: { type: String, default: "" }
1532
+ },
1533
+ emits: ["update:modelValue"],
1534
+ setup(props, { emit }) {
1535
+ const refs = [];
1536
+ const set = (i, ch) => {
1537
+ const chars = Array.from({ length: props.length }, (_, k) => props.modelValue[k] ?? "");
1538
+ chars[i] = ch.slice(-1);
1539
+ emit("update:modelValue", chars.join(""));
1540
+ if (ch && i < props.length - 1) refs[i + 1]?.focus();
1541
+ };
1542
+ const onKey = (i, e) => {
1543
+ if (e.key === "Backspace" && !props.modelValue[i] && i > 0) refs[i - 1]?.focus();
1544
+ };
1545
+ return () => (0, import_vue.h)(
1546
+ "div",
1547
+ { class: "ui-otp" },
1548
+ Array.from(
1549
+ { length: props.length },
1550
+ (_, i) => (0, import_vue.h)("input", {
1551
+ key: i,
1552
+ ref: (el) => {
1553
+ refs[i] = el;
1554
+ },
1555
+ inputmode: "numeric",
1556
+ maxlength: 1,
1557
+ value: props.modelValue[i] ?? "",
1558
+ onInput: (e) => set(i, e.target.value.replace(/\D/g, "")),
1559
+ onKeydown: (e) => onKey(i, e)
1560
+ })
1561
+ )
1562
+ );
1563
+ }
1564
+ });
1565
+ function niceNum(n) {
1566
+ if (Math.abs(n) >= 1e6) return (n / 1e6).toFixed(n % 1e6 === 0 ? 0 : 1) + "M";
1567
+ if (Math.abs(n) >= 1e3) return (n / 1e3).toFixed(n % 1e3 === 0 ? 0 : 1) + "k";
1568
+ return String(n);
1569
+ }
1570
+ var AreaChart = (0, import_vue.defineComponent)({
1571
+ name: "VspAreaChart",
1572
+ props: {
1573
+ series: { type: Array, default: () => [] },
1574
+ labels: { type: Array, default: void 0 },
1575
+ width: { type: Number, default: 760 },
1576
+ height: { type: Number, default: 260 },
1577
+ color: { type: String, default: "var(--accent)" },
1578
+ color2: { type: String, default: "var(--accent-2)" },
1579
+ dual: Boolean
1580
+ },
1581
+ setup(props) {
1582
+ const gid = "ac" + (0, import_vue.useId)().replace(/[^a-zA-Z0-9]/g, "");
1583
+ const txt = (x, y, anchor, val) => (0, import_vue.h)(
1584
+ "text",
1585
+ {
1586
+ x,
1587
+ y,
1588
+ "text-anchor": anchor,
1589
+ "font-size": "10",
1590
+ fill: "var(--text-faint)",
1591
+ "font-family": "var(--font-mono)"
1592
+ },
1593
+ val
1594
+ );
1595
+ return () => {
1596
+ const w = props.width;
1597
+ const height = props.height;
1598
+ const padL = 38;
1599
+ const padB = 26;
1600
+ const padT = 12;
1601
+ const padR = 8;
1602
+ const innerW = Math.max(10, w - padL - padR);
1603
+ const innerH = height - padB - padT;
1604
+ const s0 = props.series[0] ?? [];
1605
+ const s1 = props.series[1];
1606
+ const all = props.dual && s1 ? [...s0, ...s1] : s0;
1607
+ const max = Math.max(...all, 0) * 1.12;
1608
+ const rng = max || 1;
1609
+ const sx = (i, len) => padL + i / Math.max(1, len - 1) * innerW;
1610
+ const sy = (v) => padT + innerH - v / rng * innerH;
1611
+ const mkPts = (arr) => arr.map((v, i) => [sx(i, arr.length), sy(v)]);
1612
+ const lines = (props.dual && s1 ? [s0, s1] : [s0]).map(mkPts);
1613
+ const yTicks = 4;
1614
+ const grid = Array.from({ length: yTicks + 1 }, (_, i) => {
1615
+ const y = sy(max / yTicks * i);
1616
+ return (0, import_vue.h)("g", { key: "g" + i }, [
1617
+ (0, import_vue.h)("line", {
1618
+ x1: padL,
1619
+ x2: w - padR,
1620
+ y1: y,
1621
+ y2: y,
1622
+ stroke: "var(--grid-line)",
1623
+ "stroke-width": "1"
1624
+ }),
1625
+ txt(padL - 8, y + 3.5, "end", niceNum(Math.round(max / yTicks * i)))
1626
+ ]);
1627
+ });
1628
+ const lbls = props.labels ? props.labels.map(
1629
+ (lb, i) => i % Math.ceil(props.labels.length / 7) === 0 ? txt(sx(i, props.labels.length), height - 8, "middle", lb) : null
1630
+ ) : [];
1631
+ const lineEls = lines.map((pts, li) => {
1632
+ const stroke = li === 0 ? props.color : props.color2;
1633
+ const lastPt = pts[pts.length - 1];
1634
+ const firstPt = pts[0];
1635
+ return (0, import_vue.h)("g", { key: "ln" + li }, [
1636
+ li === 0 && firstPt && lastPt ? (0, import_vue.h)("path", {
1637
+ d: `${smoothPath(pts)} L ${lastPt[0]} ${padT + innerH} L ${firstPt[0]} ${padT + innerH} Z`,
1638
+ fill: `url(#${gid})`
1639
+ }) : null,
1640
+ (0, import_vue.h)("path", {
1641
+ d: smoothPath(pts),
1642
+ fill: "none",
1643
+ stroke,
1644
+ "stroke-width": "2.4",
1645
+ "stroke-linecap": "round",
1646
+ "stroke-dasharray": li === 1 ? "5 5" : void 0,
1647
+ style: { opacity: li === 1 ? 0.7 : 1 }
1648
+ })
1649
+ ]);
1650
+ });
1651
+ return (0, import_vue.h)("svg", { width: w, height, style: { display: "block" } }, [
1652
+ (0, import_vue.h)("defs", null, [
1653
+ (0, import_vue.h)("linearGradient", { id: gid, x1: "0", x2: "0", y1: "0", y2: "1" }, [
1654
+ (0, import_vue.h)("stop", { offset: "0", "stop-color": props.color, "stop-opacity": "0.22" }),
1655
+ (0, import_vue.h)("stop", { offset: "1", "stop-color": props.color, "stop-opacity": "0" })
1656
+ ])
1657
+ ]),
1658
+ ...grid,
1659
+ ...lbls,
1660
+ ...lineEls
1661
+ ]);
1662
+ };
1663
+ }
1664
+ });
1665
+ var BarChart = (0, import_vue.defineComponent)({
1666
+ name: "VspBarChart",
1667
+ props: {
1668
+ data: { type: Array, default: () => [] },
1669
+ labels: { type: Array, default: void 0 },
1670
+ width: { type: Number, default: 620 },
1671
+ height: { type: Number, default: 240 },
1672
+ color: { type: String, default: "var(--accent)" }
1673
+ },
1674
+ setup(props) {
1675
+ return () => {
1676
+ const w = props.width;
1677
+ const height = props.height;
1678
+ const padL = 34;
1679
+ const padB = 26;
1680
+ const padT = 10;
1681
+ const innerW = Math.max(10, w - padL - 8);
1682
+ const innerH = height - padB - padT;
1683
+ const max = Math.max(...props.data, 0) * 1.15 || 1;
1684
+ const bw = innerW / (props.data.length || 1);
1685
+ const grid = [0, 0.5, 1].map((f, i) => {
1686
+ const y = padT + innerH - f * innerH;
1687
+ return (0, import_vue.h)("g", { key: "g" + i }, [
1688
+ (0, import_vue.h)("line", { x1: padL, x2: w - 8, y1: y, y2: y, stroke: "var(--grid-line)" }),
1689
+ (0, import_vue.h)(
1690
+ "text",
1691
+ {
1692
+ x: padL - 8,
1693
+ y: y + 3.5,
1694
+ "text-anchor": "end",
1695
+ "font-size": "10",
1696
+ fill: "var(--text-faint)",
1697
+ "font-family": "var(--font-mono)"
1698
+ },
1699
+ niceNum(Math.round(max * f))
1700
+ )
1701
+ ]);
1702
+ });
1703
+ const bars = props.data.map((v, i) => {
1704
+ const bh = v / max * innerH;
1705
+ const x = padL + i * bw + bw * 0.18;
1706
+ const bwi = bw * 0.64;
1707
+ return (0, import_vue.h)("g", { key: "b" + i }, [
1708
+ (0, import_vue.h)("rect", {
1709
+ x,
1710
+ y: padT + innerH - bh,
1711
+ width: bwi,
1712
+ height: bh,
1713
+ rx: "4",
1714
+ fill: `color-mix(in oklab, ${props.color} 78%, transparent)`
1715
+ }),
1716
+ props.labels?.[i] != null ? (0, import_vue.h)(
1717
+ "text",
1718
+ {
1719
+ x: x + bwi / 2,
1720
+ y: height - 8,
1721
+ "text-anchor": "middle",
1722
+ "font-size": "10",
1723
+ fill: "var(--text-faint)",
1724
+ "font-family": "var(--font-mono)"
1725
+ },
1726
+ props.labels[i]
1727
+ ) : null
1728
+ ]);
1729
+ });
1730
+ return (0, import_vue.h)("svg", { width: w, height, style: { display: "block" } }, [...grid, ...bars]);
1731
+ };
1732
+ }
1733
+ });
1407
1734
  // Annotate the CommonJS export names for ESM import in node:
1408
1735
  0 && (module.exports = {
1409
1736
  Accordion,
1410
1737
  Alert,
1738
+ AreaChart,
1411
1739
  Avatar,
1412
1740
  AvatarGroup,
1413
1741
  Badge,
1414
1742
  Banner,
1743
+ BarChart,
1415
1744
  Breadcrumb,
1416
1745
  Button,
1417
1746
  Card,
@@ -1430,6 +1759,7 @@ var InlineEdit = (0, import_vue.defineComponent)({
1430
1759
  Kbd,
1431
1760
  NativeSelect,
1432
1761
  NumberStepper,
1762
+ OTPInput,
1433
1763
  Pagination,
1434
1764
  Progress,
1435
1765
  Radio,
@@ -1447,6 +1777,8 @@ var InlineEdit = (0, import_vue.defineComponent)({
1447
1777
  Tag,
1448
1778
  Textarea,
1449
1779
  Timeline,
1780
+ Tree,
1781
+ niceNum,
1450
1782
  smoothPath
1451
1783
  });
1452
1784
  //# sourceMappingURL=index.cjs.map