@dust-tt/sparkle 0.2.214 → 0.2.215

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dust-tt/sparkle",
3
- "version": "0.2.214",
3
+ "version": "0.2.215",
4
4
  "scripts": {
5
5
  "build": "rm -rf dist && rollup -c",
6
6
  "build:with-tw-base": "rollup -c --environment INCLUDE_TW_BASE:true",
@@ -1,56 +1,117 @@
1
1
  import type { ComponentType } from "react";
2
2
  import React from "react";
3
3
 
4
- import { SparkleContextLinkType } from "@sparkle/context";
5
- import { ChevronRightIcon, Icon, SparkleContext } from "@sparkle/index";
4
+ import { noHrefLink, SparkleContextLinkType } from "@sparkle/context";
5
+ import {
6
+ ChevronRightIcon,
7
+ DropdownMenu,
8
+ Icon,
9
+ SparkleContext,
10
+ Tooltip,
11
+ } from "@sparkle/index";
12
+
13
+ const LABEL_TRUNCATE_LENGTH_MIDDLE = 15;
14
+ const LABEL_TRUNCATE_LENGTH_END = 30;
15
+ const ELLIPSIS_STRING = "...";
16
+
17
+ type BreadcrumbItem = {
18
+ label: string;
19
+ icon?: ComponentType<{ className?: string }>;
20
+ href?: string;
21
+ };
6
22
 
7
23
  type BreadcrumbProps = {
8
- items: {
9
- label: string;
10
- icon?: ComponentType<{ className?: string }>;
11
- href?: string;
12
- }[];
24
+ items: BreadcrumbItem[];
25
+ };
26
+
27
+ type BreadcrumbsAccumulator = {
28
+ itemsShown: BreadcrumbItem[];
29
+ itemsHidden: BreadcrumbItem[];
13
30
  };
14
31
 
15
32
  export function Breadcrumbs({ items }: BreadcrumbProps) {
16
33
  const { components } = React.useContext(SparkleContext);
17
34
 
18
- const Link: SparkleContextLinkType = components.link;
35
+ const { itemsShown, itemsHidden } = items.reduce(
36
+ (acc: BreadcrumbsAccumulator, item, index) => {
37
+ if (items.length <= 5 || index < 2 || index >= items.length - 2) {
38
+ acc.itemsShown.push(item);
39
+ } else if (index === 2) {
40
+ acc.itemsShown.push({ label: ELLIPSIS_STRING });
41
+ } else {
42
+ acc.itemsHidden.push(item);
43
+ }
44
+ return acc;
45
+ },
46
+ { itemsShown: [], itemsHidden: [] }
47
+ );
19
48
 
20
49
  return (
21
50
  <div className="gap-2 s-flex s-flex-row s-items-center">
22
- {items.map((item, index) => (
23
- <div key={index} className="s-flex s-flex-row s-items-center s-gap-1">
24
- <Icon visual={item.icon} className="s-text-brand" />
25
- <div>
26
- {item.href ? (
27
- <Link
28
- href={item.href}
29
- className={
30
- index === items.length - 1
31
- ? "s-text-element-900"
32
- : "s-text-element-700"
33
- }
34
- >
35
- {item.label}
36
- </Link>
51
+ {itemsShown.map((item, index) => {
52
+ return (
53
+ <div
54
+ key={`breadcrumbs-${index}`}
55
+ className="s-flex s-flex-row s-items-center s-gap-1"
56
+ >
57
+ <Icon visual={item.icon} className="s-text-brand" />
58
+ {item.label === ELLIPSIS_STRING ? (
59
+ <DropdownMenu>
60
+ <DropdownMenu.Button>${ELLIPSIS_STRING}</DropdownMenu.Button>
61
+ <DropdownMenu.Items origin="topLeft">
62
+ {itemsHidden.map((item, index) => (
63
+ <DropdownMenu.Item
64
+ key={`breadcrumbs-hidden-${index}`}
65
+ icon={item.icon}
66
+ label={item.label}
67
+ >
68
+ {getLinkForItem(item, false, components.link)}
69
+ </DropdownMenu.Item>
70
+ ))}
71
+ </DropdownMenu.Items>
72
+ </DropdownMenu>
37
73
  ) : (
38
- <span
39
- className={
40
- index === items.length - 1
41
- ? "s-text-element-900"
42
- : "s-text-element-700"
43
- }
44
- >
45
- {item.label}
46
- </span>
74
+ <div>
75
+ {getLinkForItem(
76
+ item,
77
+ index === itemsShown.length - 1,
78
+ components.link
79
+ )}
80
+ </div>
81
+ )}
82
+ {index === itemsShown.length - 1 ? null : (
83
+ <ChevronRightIcon className="s-text-element-500" />
47
84
  )}
48
85
  </div>
49
- {index === items.length - 1 ? null : (
50
- <ChevronRightIcon className="s-text-element-500" />
51
- )}
52
- </div>
53
- ))}
86
+ );
87
+ })}
54
88
  </div>
55
89
  );
56
90
  }
91
+
92
+ function getLinkForItem(
93
+ item: BreadcrumbItem,
94
+ isLast: boolean,
95
+ link: SparkleContextLinkType
96
+ ) {
97
+ const Link: SparkleContextLinkType = item.href ? link : noHrefLink;
98
+
99
+ return (
100
+ <Link
101
+ href={item.href || "#"}
102
+ className={isLast ? "s-text-element-900" : "s-text-element-700"}
103
+ >
104
+ {isLast
105
+ ? truncateWithTooltip(item.label, LABEL_TRUNCATE_LENGTH_END)
106
+ : truncateWithTooltip(item.label, LABEL_TRUNCATE_LENGTH_MIDDLE)}
107
+ </Link>
108
+ );
109
+ }
110
+
111
+ function truncateWithTooltip(text: string, length: number) {
112
+ return text.length > length ? (
113
+ <Tooltip label={text}>{`${text.substring(0, length - 1)}…`}</Tooltip>
114
+ ) : (
115
+ text
116
+ );
117
+ }
@@ -1,7 +1,12 @@
1
1
  import type { Meta } from "@storybook/react";
2
2
  import React from "react";
3
3
 
4
- import { Breadcrumbs, CompanyIcon, HomeIcon } from "../index_with_tw_base";
4
+ import {
5
+ Breadcrumbs,
6
+ CompanyIcon,
7
+ FolderIcon,
8
+ HomeIcon,
9
+ } from "../index_with_tw_base";
5
10
 
6
11
  const meta = {
7
12
  title: "Components/Breadcrumbs",
@@ -20,12 +25,55 @@ export const BreadcrumbsExample = () => {
20
25
  { label: "Home", href: "#", icon: HomeIcon },
21
26
  { label: "Vaults", href: "#", icon: CompanyIcon },
22
27
  { label: "My Vault", href: "#" },
28
+ { label: "loooong name in the end, like very very long long" },
29
+ ];
30
+
31
+ const items3 = [
32
+ { label: "Home", href: "#", icon: HomeIcon },
33
+ {
34
+ label: "Middle long name, oh very looong folder name in the middle",
35
+ href: "#",
36
+ icon: CompanyIcon,
37
+ },
38
+ { label: "My Vault", href: "#" },
23
39
  { label: "Data Sources" },
40
+ { label: "Folder1", href: "#", icon: FolderIcon },
41
+ { label: "With ellipsis", href: "#" },
24
42
  ];
43
+
44
+ const items4 = [
45
+ { label: "Home", href: "#", icon: HomeIcon },
46
+ {
47
+ label: "Middle long name, oh very looong folder name in the middle",
48
+ href: "#",
49
+ icon: CompanyIcon,
50
+ },
51
+ { label: "My Vault", href: "#" },
52
+ { label: "Data Sources" },
53
+ { label: "Folder1", href: "#", icon: FolderIcon },
54
+ { label: "Folder2", href: "#", icon: FolderIcon },
55
+ { label: "Folder3", href: "#", icon: FolderIcon },
56
+ { label: "With ellipsis", href: "#" },
57
+ ];
58
+
59
+ const items5 = [
60
+ { label: "Home", href: "#", icon: HomeIcon },
61
+ {
62
+ label: "Long, oh very looong folder name in the middle",
63
+ href: "#",
64
+ icon: CompanyIcon,
65
+ },
66
+ { label: "My Vault", href: "#" },
67
+ { label: "Data Sources" },
68
+ ];
69
+
25
70
  return (
26
- <div className="s-flex s-flex-col s-gap-4">
71
+ <div className="s-flex s-flex-col s-gap-4 s-pb-8">
27
72
  <Breadcrumbs items={items1} />
28
73
  <Breadcrumbs items={items2} />
74
+ <Breadcrumbs items={items4} />
75
+ <Breadcrumbs items={items3} />
76
+ <Breadcrumbs items={items5} />
29
77
  </div>
30
78
  );
31
79
  };