@tonyarbor/components 0.2.1 → 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/Avatar.d.mts +42 -0
- package/dist/Avatar.d.ts +42 -0
- package/dist/Avatar.js +158 -0
- package/dist/Avatar.js.map +1 -0
- package/dist/Avatar.mjs +7 -0
- package/dist/Avatar.mjs.map +1 -0
- package/dist/Breadcrumbs.d.mts +51 -0
- package/dist/Breadcrumbs.d.ts +51 -0
- package/dist/Breadcrumbs.js +276 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.mjs +7 -0
- package/dist/Breadcrumbs.mjs.map +1 -0
- package/dist/ButtonSegmented.d.mts +61 -0
- package/dist/ButtonSegmented.d.ts +61 -0
- package/dist/ButtonSegmented.js +167 -0
- package/dist/ButtonSegmented.js.map +1 -0
- package/dist/ButtonSegmented.mjs +7 -0
- package/dist/ButtonSegmented.mjs.map +1 -0
- package/dist/ListRow.d.mts +72 -0
- package/dist/ListRow.d.ts +72 -0
- package/dist/ListRow.js +194 -0
- package/dist/ListRow.js.map +1 -0
- package/dist/ListRow.mjs +7 -0
- package/dist/ListRow.mjs.map +1 -0
- package/dist/ListRowMultiLine.d.mts +56 -0
- package/dist/ListRowMultiLine.d.ts +56 -0
- package/dist/ListRowMultiLine.js +182 -0
- package/dist/ListRowMultiLine.js.map +1 -0
- package/dist/ListRowMultiLine.mjs +7 -0
- package/dist/ListRowMultiLine.mjs.map +1 -0
- package/dist/Logo.d.mts +39 -0
- package/dist/Logo.d.ts +39 -0
- package/dist/Logo.js +119 -0
- package/dist/Logo.js.map +1 -0
- package/dist/Logo.mjs +7 -0
- package/dist/Logo.mjs.map +1 -0
- package/dist/SearchGlobal.d.mts +45 -0
- package/dist/SearchGlobal.d.ts +45 -0
- package/dist/SearchGlobal.js +209 -0
- package/dist/SearchGlobal.js.map +1 -0
- package/dist/SearchGlobal.mjs +7 -0
- package/dist/SearchGlobal.mjs.map +1 -0
- package/dist/SearchOnPage.d.mts +45 -0
- package/dist/SearchOnPage.d.ts +45 -0
- package/dist/SearchOnPage.js +171 -0
- package/dist/SearchOnPage.js.map +1 -0
- package/dist/SearchOnPage.mjs +7 -0
- package/dist/SearchOnPage.mjs.map +1 -0
- package/dist/Section.d.mts +57 -0
- package/dist/Section.d.ts +57 -0
- package/dist/Section.js +72 -0
- package/dist/Section.js.map +1 -0
- package/dist/Section.mjs +7 -0
- package/dist/Section.mjs.map +1 -0
- package/dist/SectionHeading.d.mts +111 -0
- package/dist/SectionHeading.d.ts +111 -0
- package/dist/SectionHeading.js +385 -0
- package/dist/SectionHeading.js.map +1 -0
- package/dist/SectionHeading.mjs +8 -0
- package/dist/SectionHeading.mjs.map +1 -0
- package/dist/SectionHeadingInteractive.d.mts +67 -0
- package/dist/SectionHeadingInteractive.d.ts +67 -0
- package/dist/SectionHeadingInteractive.js +225 -0
- package/dist/SectionHeadingInteractive.js.map +1 -0
- package/dist/SectionHeadingInteractive.mjs +7 -0
- package/dist/SectionHeadingInteractive.mjs.map +1 -0
- package/dist/SectionIcon.d.mts +35 -0
- package/dist/SectionIcon.d.ts +35 -0
- package/dist/SectionIcon.js +142 -0
- package/dist/SectionIcon.js.map +1 -0
- package/dist/SectionIcon.mjs +7 -0
- package/dist/SectionIcon.mjs.map +1 -0
- package/dist/SubSectionHeading.d.mts +75 -0
- package/dist/SubSectionHeading.d.ts +75 -0
- package/dist/SubSectionHeading.js +225 -0
- package/dist/SubSectionHeading.js.map +1 -0
- package/dist/SubSectionHeading.mjs +7 -0
- package/dist/SubSectionHeading.mjs.map +1 -0
- package/dist/SubSectionInteractive.d.mts +65 -0
- package/dist/SubSectionInteractive.d.ts +65 -0
- package/dist/SubSectionInteractive.js +211 -0
- package/dist/SubSectionInteractive.js.map +1 -0
- package/dist/SubSectionInteractive.mjs +7 -0
- package/dist/SubSectionInteractive.mjs.map +1 -0
- package/dist/chunk-7NYBJKJS.mjs +106 -0
- package/dist/chunk-7NYBJKJS.mjs.map +1 -0
- package/dist/chunk-ALLCJATI.mjs +189 -0
- package/dist/chunk-ALLCJATI.mjs.map +1 -0
- package/dist/chunk-B7RX3TPX.mjs +135 -0
- package/dist/chunk-B7RX3TPX.mjs.map +1 -0
- package/dist/chunk-F6JVEIWC.mjs +158 -0
- package/dist/chunk-F6JVEIWC.mjs.map +1 -0
- package/dist/chunk-GHATS25Y.mjs +249 -0
- package/dist/chunk-GHATS25Y.mjs.map +1 -0
- package/dist/chunk-ILLGBZ6R.mjs +131 -0
- package/dist/chunk-ILLGBZ6R.mjs.map +1 -0
- package/dist/chunk-JSG27ZZS.mjs +122 -0
- package/dist/chunk-JSG27ZZS.mjs.map +1 -0
- package/dist/chunk-NNYU4DPD.mjs +83 -0
- package/dist/chunk-NNYU4DPD.mjs.map +1 -0
- package/dist/chunk-ODKT7LGV.mjs +146 -0
- package/dist/chunk-ODKT7LGV.mjs.map +1 -0
- package/dist/chunk-RL4G7MR3.mjs +189 -0
- package/dist/chunk-RL4G7MR3.mjs.map +1 -0
- package/dist/chunk-RQP6ZGD7.mjs +240 -0
- package/dist/chunk-RQP6ZGD7.mjs.map +1 -0
- package/dist/chunk-UPBHDBAK.mjs +173 -0
- package/dist/chunk-UPBHDBAK.mjs.map +1 -0
- package/dist/chunk-X2CW5GF3.mjs +175 -0
- package/dist/chunk-X2CW5GF3.mjs.map +1 -0
- package/dist/chunk-YJ36ZZJQ.mjs +36 -0
- package/dist/chunk-YJ36ZZJQ.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +2102 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +56 -0
- package/package.json +71 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
// src/Breadcrumbs/Breadcrumbs.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Link, ChevronDown, MoreHorizontal } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var Breadcrumbs = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
items,
|
|
8
|
+
onCopy,
|
|
9
|
+
className,
|
|
10
|
+
style,
|
|
11
|
+
"data-testid": dataTestId
|
|
12
|
+
}, ref) => {
|
|
13
|
+
const [hoveredIndex, setHoveredIndex] = React.useState(null);
|
|
14
|
+
const [focusedIndex, setFocusedIndex] = React.useState(null);
|
|
15
|
+
const [showCopyTooltip, setShowCopyTooltip] = React.useState(false);
|
|
16
|
+
const [ellipsisFocused, setEllipsisFocused] = React.useState(false);
|
|
17
|
+
const [ellipsisHovered, setEllipsisHovered] = React.useState(false);
|
|
18
|
+
const displayItems = React.useMemo(() => {
|
|
19
|
+
if (items.length > 6) {
|
|
20
|
+
return [items[0], { label: "...", isEllipsis: true }, items[items.length - 1]];
|
|
21
|
+
}
|
|
22
|
+
return items;
|
|
23
|
+
}, [items]);
|
|
24
|
+
const handleCopy = () => {
|
|
25
|
+
onCopy?.();
|
|
26
|
+
const trail = items.map((item) => item.label).join(" / ");
|
|
27
|
+
navigator.clipboard.writeText(trail);
|
|
28
|
+
};
|
|
29
|
+
const containerStyles = {
|
|
30
|
+
display: "flex",
|
|
31
|
+
alignItems: "center",
|
|
32
|
+
gap: "8px",
|
|
33
|
+
...style
|
|
34
|
+
};
|
|
35
|
+
const breadcrumbItemStyles = (index, isActive, isEllipsis) => {
|
|
36
|
+
const isFocused = focusedIndex === index;
|
|
37
|
+
if (isEllipsis) {
|
|
38
|
+
return {
|
|
39
|
+
display: "flex",
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
gap: "4px",
|
|
42
|
+
height: "24px",
|
|
43
|
+
overflow: "hidden"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
display: "flex",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
gap: "4px",
|
|
50
|
+
height: "24px",
|
|
51
|
+
overflow: "hidden",
|
|
52
|
+
backgroundColor: isFocused ? "rgba(255, 255, 255, 0.01)" : "transparent",
|
|
53
|
+
borderRadius: "99px",
|
|
54
|
+
boxShadow: isFocused ? "0px 0px 0px 3px #3cad51" : "none",
|
|
55
|
+
padding: isFocused ? "0 6px" : "0 2px",
|
|
56
|
+
margin: isFocused ? "0" : "0 4px",
|
|
57
|
+
cursor: isActive ? "default" : "pointer",
|
|
58
|
+
textDecoration: "none"
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const linkStyles = (isActive, isHovered) => ({
|
|
62
|
+
fontFamily: isActive ? "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" : "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
63
|
+
fontSize: "13px",
|
|
64
|
+
fontWeight: isActive ? 600 : 400,
|
|
65
|
+
color: isActive ? isHovered ? "#0e8a0e" : "#2f2f2f" : isHovered ? "#0e8a0e" : "#595959",
|
|
66
|
+
lineHeight: "1.5",
|
|
67
|
+
whiteSpace: "nowrap"
|
|
68
|
+
});
|
|
69
|
+
const dividerStyles = {
|
|
70
|
+
fontFamily: "'PT Sans', sans-serif",
|
|
71
|
+
fontSize: "14px",
|
|
72
|
+
color: "#595959",
|
|
73
|
+
lineHeight: "normal",
|
|
74
|
+
whiteSpace: "nowrap"
|
|
75
|
+
};
|
|
76
|
+
const ellipsisButtonStyles = {
|
|
77
|
+
display: "flex",
|
|
78
|
+
alignItems: "center",
|
|
79
|
+
justifyContent: "center",
|
|
80
|
+
width: "24px",
|
|
81
|
+
height: "24px",
|
|
82
|
+
borderRadius: "99px",
|
|
83
|
+
border: "none",
|
|
84
|
+
background: "transparent",
|
|
85
|
+
cursor: "pointer",
|
|
86
|
+
backgroundColor: ellipsisFocused ? "rgba(255, 255, 255, 0.01)" : ellipsisHovered ? "#efefef" : "transparent",
|
|
87
|
+
boxShadow: ellipsisFocused ? "0px 0px 0px 3px #3cad51" : "none"
|
|
88
|
+
};
|
|
89
|
+
const copyButtonStyles = {
|
|
90
|
+
display: "flex",
|
|
91
|
+
alignItems: "center",
|
|
92
|
+
justifyContent: "center",
|
|
93
|
+
width: "24px",
|
|
94
|
+
height: "24px",
|
|
95
|
+
borderRadius: "99px",
|
|
96
|
+
border: "none",
|
|
97
|
+
background: showCopyTooltip ? "#efefef" : "transparent",
|
|
98
|
+
cursor: "pointer",
|
|
99
|
+
position: "relative"
|
|
100
|
+
};
|
|
101
|
+
const tooltipStyles = {
|
|
102
|
+
position: "absolute",
|
|
103
|
+
top: "100%",
|
|
104
|
+
left: "50%",
|
|
105
|
+
transform: "translateX(-50%)",
|
|
106
|
+
marginTop: "8px",
|
|
107
|
+
backgroundColor: "#2f2f2f",
|
|
108
|
+
color: "white",
|
|
109
|
+
padding: "12px",
|
|
110
|
+
borderRadius: "8px",
|
|
111
|
+
fontSize: "13px",
|
|
112
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
113
|
+
fontWeight: 400,
|
|
114
|
+
lineHeight: "1.5",
|
|
115
|
+
whiteSpace: "nowrap",
|
|
116
|
+
boxShadow: "0px 4px 12px rgba(32, 32, 32, 0.08)",
|
|
117
|
+
zIndex: 1e3
|
|
118
|
+
};
|
|
119
|
+
return /* @__PURE__ */ jsx(
|
|
120
|
+
"div",
|
|
121
|
+
{
|
|
122
|
+
ref,
|
|
123
|
+
className,
|
|
124
|
+
style: containerStyles,
|
|
125
|
+
"data-testid": dataTestId,
|
|
126
|
+
children: displayItems.map((item, index) => {
|
|
127
|
+
const isActive = index === displayItems.length - 1;
|
|
128
|
+
const isEllipsis = "isEllipsis" in item && item.isEllipsis;
|
|
129
|
+
if (isEllipsis) {
|
|
130
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
131
|
+
/* @__PURE__ */ jsx(
|
|
132
|
+
"button",
|
|
133
|
+
{
|
|
134
|
+
style: ellipsisButtonStyles,
|
|
135
|
+
onFocus: () => setEllipsisFocused(true),
|
|
136
|
+
onBlur: () => setEllipsisFocused(false),
|
|
137
|
+
onMouseEnter: () => setEllipsisHovered(true),
|
|
138
|
+
onMouseLeave: () => setEllipsisHovered(false),
|
|
139
|
+
"aria-label": "More breadcrumbs",
|
|
140
|
+
children: /* @__PURE__ */ jsx(
|
|
141
|
+
MoreHorizontal,
|
|
142
|
+
{
|
|
143
|
+
size: 12,
|
|
144
|
+
color: "#2f2f2f",
|
|
145
|
+
strokeWidth: 2,
|
|
146
|
+
style: { display: "block", flexShrink: 0 }
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
/* @__PURE__ */ jsx("span", { style: dividerStyles, children: " /" })
|
|
152
|
+
] }, `ellipsis-${index}`);
|
|
153
|
+
}
|
|
154
|
+
const breadcrumbItem = item;
|
|
155
|
+
if (isActive) {
|
|
156
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
157
|
+
/* @__PURE__ */ jsx(
|
|
158
|
+
"div",
|
|
159
|
+
{
|
|
160
|
+
style: breadcrumbItemStyles(index, true),
|
|
161
|
+
onMouseEnter: () => setHoveredIndex(index),
|
|
162
|
+
onMouseLeave: () => setHoveredIndex(null),
|
|
163
|
+
onFocus: () => setFocusedIndex(index),
|
|
164
|
+
onBlur: () => setFocusedIndex(null),
|
|
165
|
+
tabIndex: 0,
|
|
166
|
+
children: /* @__PURE__ */ jsx("span", { style: linkStyles(true, hoveredIndex === index), children: breadcrumbItem.label })
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
onCopy && /* @__PURE__ */ jsxs(
|
|
170
|
+
"button",
|
|
171
|
+
{
|
|
172
|
+
style: copyButtonStyles,
|
|
173
|
+
onClick: handleCopy,
|
|
174
|
+
onMouseEnter: () => setShowCopyTooltip(true),
|
|
175
|
+
onMouseLeave: () => setShowCopyTooltip(false),
|
|
176
|
+
"aria-label": "Copy breadcrumb trail",
|
|
177
|
+
children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
Link,
|
|
180
|
+
{
|
|
181
|
+
size: 12,
|
|
182
|
+
color: "#2f2f2f",
|
|
183
|
+
strokeWidth: 2,
|
|
184
|
+
style: { display: "block", flexShrink: 0 }
|
|
185
|
+
}
|
|
186
|
+
),
|
|
187
|
+
showCopyTooltip && /* @__PURE__ */ jsx("div", { style: tooltipStyles, children: "Copy breadcrumb trail" })
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
] }, index);
|
|
192
|
+
}
|
|
193
|
+
const Element = breadcrumbItem.href ? "a" : "button";
|
|
194
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
195
|
+
/* @__PURE__ */ jsxs(
|
|
196
|
+
Element,
|
|
197
|
+
{
|
|
198
|
+
...breadcrumbItem.href ? { href: breadcrumbItem.href } : {},
|
|
199
|
+
style: {
|
|
200
|
+
...breadcrumbItemStyles(index, false),
|
|
201
|
+
border: "none",
|
|
202
|
+
background: "transparent"
|
|
203
|
+
},
|
|
204
|
+
onClick: (e) => {
|
|
205
|
+
if (!breadcrumbItem.href && breadcrumbItem.onClick) {
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
breadcrumbItem.onClick();
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
onMouseEnter: () => setHoveredIndex(index),
|
|
211
|
+
onMouseLeave: () => setHoveredIndex(null),
|
|
212
|
+
onFocus: () => setFocusedIndex(index),
|
|
213
|
+
onBlur: () => setFocusedIndex(null),
|
|
214
|
+
children: [
|
|
215
|
+
/* @__PURE__ */ jsx("span", { style: linkStyles(false, hoveredIndex === index), children: breadcrumbItem.label }),
|
|
216
|
+
breadcrumbItem.hasDropdown && /* @__PURE__ */ jsx(
|
|
217
|
+
ChevronDown,
|
|
218
|
+
{
|
|
219
|
+
size: 12,
|
|
220
|
+
color: hoveredIndex === index ? "#0e8a0e" : "#595959",
|
|
221
|
+
strokeWidth: 2,
|
|
222
|
+
style: { marginLeft: "2px", display: "inline-block", flexShrink: 0 }
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
),
|
|
228
|
+
/* @__PURE__ */ jsx("span", { style: dividerStyles, children: " /" })
|
|
229
|
+
] }, index);
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
Breadcrumbs.displayName = "Breadcrumbs";
|
|
236
|
+
|
|
237
|
+
export {
|
|
238
|
+
Breadcrumbs
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=chunk-RQP6ZGD7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Breadcrumbs/Breadcrumbs.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Link, ChevronDown, MoreHorizontal } from 'lucide-react';\n\nexport interface BreadcrumbItem {\n /**\n * The label to display for this breadcrumb\n */\n label: string;\n /**\n * Optional href for the breadcrumb link\n */\n href?: string;\n /**\n * Optional click handler\n */\n onClick?: () => void;\n /**\n * Whether this breadcrumb has a dropdown menu\n */\n hasDropdown?: boolean;\n}\n\nexport interface BreadcrumbsProps {\n /**\n * Array of breadcrumb items\n */\n items: BreadcrumbItem[];\n /**\n * Callback when copy button is clicked\n */\n onCopy?: () => void;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n}\n\n/**\n * Breadcrumbs component - Arbor Design System\n *\n * Navigation component showing the current page's location in the site hierarchy.\n * Automatically truncates to show first and last breadcrumb with ellipsis when more than 6 items.\n */\nexport const Breadcrumbs = React.forwardRef<HTMLDivElement, BreadcrumbsProps>(\n (\n {\n items,\n onCopy,\n className,\n style,\n 'data-testid': dataTestId,\n },\n ref\n ) => {\n const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n const [focusedIndex, setFocusedIndex] = React.useState<number | null>(null);\n const [showCopyTooltip, setShowCopyTooltip] = React.useState(false);\n const [ellipsisFocused, setEllipsisFocused] = React.useState(false);\n const [ellipsisHovered, setEllipsisHovered] = React.useState(false);\n\n // Truncate breadcrumbs if more than 6 items\n const displayItems = React.useMemo(() => {\n if (items.length > 6) {\n // Show first item, ellipsis, and last item\n return [items[0], { label: '...', isEllipsis: true }, items[items.length - 1]];\n }\n return items;\n }, [items]);\n\n const handleCopy = () => {\n onCopy?.();\n // Copy the breadcrumb trail to clipboard\n const trail = items.map(item => item.label).join(' / ');\n navigator.clipboard.writeText(trail);\n };\n\n const containerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n ...style,\n };\n\n const breadcrumbItemStyles = (index: number, isActive: boolean, isEllipsis?: boolean): React.CSSProperties => {\n const isFocused = focusedIndex === index;\n\n if (isEllipsis) {\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n height: '24px',\n overflow: 'hidden',\n };\n }\n\n return {\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n height: '24px',\n overflow: 'hidden',\n backgroundColor: isFocused ? 'rgba(255, 255, 255, 0.01)' : 'transparent',\n borderRadius: '99px',\n boxShadow: isFocused ? '0px 0px 0px 3px #3cad51' : 'none',\n padding: isFocused ? '0 6px' : '0 2px',\n margin: isFocused ? '0' : '0 4px',\n cursor: isActive ? 'default' : 'pointer',\n textDecoration: 'none',\n };\n };\n\n const linkStyles = (isActive: boolean, isHovered: boolean): React.CSSProperties => ({\n fontFamily: isActive\n ? \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\"\n : \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: '13px',\n fontWeight: isActive ? 600 : 400,\n color: isActive\n ? isHovered\n ? '#0e8a0e'\n : '#2f2f2f'\n : isHovered\n ? '#0e8a0e'\n : '#595959',\n lineHeight: '1.5',\n whiteSpace: 'nowrap',\n });\n\n const dividerStyles: React.CSSProperties = {\n fontFamily: \"'PT Sans', sans-serif\",\n fontSize: '14px',\n color: '#595959',\n lineHeight: 'normal',\n whiteSpace: 'nowrap',\n };\n\n const ellipsisButtonStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n borderRadius: '99px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n backgroundColor: ellipsisFocused ? 'rgba(255, 255, 255, 0.01)' : ellipsisHovered ? '#efefef' : 'transparent',\n boxShadow: ellipsisFocused ? '0px 0px 0px 3px #3cad51' : 'none',\n };\n\n const copyButtonStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '24px',\n height: '24px',\n borderRadius: '99px',\n border: 'none',\n background: showCopyTooltip ? '#efefef' : 'transparent',\n cursor: 'pointer',\n position: 'relative',\n };\n\n const tooltipStyles: React.CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: '50%',\n transform: 'translateX(-50%)',\n marginTop: '8px',\n backgroundColor: '#2f2f2f',\n color: 'white',\n padding: '12px',\n borderRadius: '8px',\n fontSize: '13px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontWeight: 400,\n lineHeight: '1.5',\n whiteSpace: 'nowrap',\n boxShadow: '0px 4px 12px rgba(32, 32, 32, 0.08)',\n zIndex: 1000,\n };\n\n return (\n <div\n ref={ref}\n className={className}\n style={containerStyles}\n data-testid={dataTestId}\n >\n {displayItems.map((item, index) => {\n const isActive = index === displayItems.length - 1;\n const isEllipsis = 'isEllipsis' in item && item.isEllipsis;\n\n if (isEllipsis) {\n return (\n <React.Fragment key={`ellipsis-${index}`}>\n <button\n style={ellipsisButtonStyles}\n onFocus={() => setEllipsisFocused(true)}\n onBlur={() => setEllipsisFocused(false)}\n onMouseEnter={() => setEllipsisHovered(true)}\n onMouseLeave={() => setEllipsisHovered(false)}\n aria-label=\"More breadcrumbs\"\n >\n <MoreHorizontal\n size={12}\n color=\"#2f2f2f\"\n strokeWidth={2}\n style={{ display: 'block', flexShrink: 0 }}\n />\n </button>\n <span style={dividerStyles}> /</span>\n </React.Fragment>\n );\n }\n\n const breadcrumbItem = item as BreadcrumbItem;\n\n if (isActive) {\n // Active breadcrumb (last item) - not clickable\n return (\n <React.Fragment key={index}>\n <div\n style={breadcrumbItemStyles(index, true)}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onFocus={() => setFocusedIndex(index)}\n onBlur={() => setFocusedIndex(null)}\n tabIndex={0}\n >\n <span style={linkStyles(true, hoveredIndex === index)}>\n {breadcrumbItem.label}\n </span>\n </div>\n {/* Copy button - appears immediately after active breadcrumb */}\n {onCopy && (\n <button\n style={copyButtonStyles}\n onClick={handleCopy}\n onMouseEnter={() => setShowCopyTooltip(true)}\n onMouseLeave={() => setShowCopyTooltip(false)}\n aria-label=\"Copy breadcrumb trail\"\n >\n <Link\n size={12}\n color=\"#2f2f2f\"\n strokeWidth={2}\n style={{ display: 'block', flexShrink: 0 }}\n />\n {showCopyTooltip && (\n <div style={tooltipStyles}>Copy breadcrumb trail</div>\n )}\n </button>\n )}\n </React.Fragment>\n );\n }\n\n // Regular breadcrumb link\n const Element = breadcrumbItem.href ? 'a' : 'button';\n return (\n <React.Fragment key={index}>\n <Element\n {...(breadcrumbItem.href ? { href: breadcrumbItem.href } : {})}\n style={{\n ...breadcrumbItemStyles(index, false),\n border: 'none',\n background: 'transparent',\n }}\n onClick={(e) => {\n if (!breadcrumbItem.href && breadcrumbItem.onClick) {\n e.preventDefault();\n breadcrumbItem.onClick();\n }\n }}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n onFocus={() => setFocusedIndex(index)}\n onBlur={() => setFocusedIndex(null)}\n >\n <span style={linkStyles(false, hoveredIndex === index)}>\n {breadcrumbItem.label}\n </span>\n {breadcrumbItem.hasDropdown && (\n <ChevronDown\n size={12}\n color={hoveredIndex === index ? '#0e8a0e' : '#595959'}\n strokeWidth={2}\n style={{ marginLeft: '2px', display: 'inline-block', flexShrink: 0 }}\n />\n )}\n </Element>\n <span style={dividerStyles}> /</span>\n </React.Fragment>\n );\n })}\n </div>\n );\n }\n);\n\nBreadcrumbs.displayName = 'Breadcrumbs';\n"],"mappings":";AAAA,YAAY,WAAW;AACvB,SAAS,MAAM,aAAa,sBAAsB;AA2MpC,SASI,KATJ;AAzJP,IAAM,cAAoB;AAAA,EAC/B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,EACjB,GACA,QACG;AACH,UAAM,CAAC,cAAc,eAAe,IAAU,eAAwB,IAAI;AAC1E,UAAM,CAAC,cAAc,eAAe,IAAU,eAAwB,IAAI;AAC1E,UAAM,CAAC,iBAAiB,kBAAkB,IAAU,eAAS,KAAK;AAClE,UAAM,CAAC,iBAAiB,kBAAkB,IAAU,eAAS,KAAK;AAClE,UAAM,CAAC,iBAAiB,kBAAkB,IAAU,eAAS,KAAK;AAGlE,UAAM,eAAqB,cAAQ,MAAM;AACvC,UAAI,MAAM,SAAS,GAAG;AAEpB,eAAO,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,OAAO,YAAY,KAAK,GAAG,MAAM,MAAM,SAAS,CAAC,CAAC;AAAA,MAC/E;AACA,aAAO;AAAA,IACT,GAAG,CAAC,KAAK,CAAC;AAEV,UAAM,aAAa,MAAM;AACvB,eAAS;AAET,YAAM,QAAQ,MAAM,IAAI,UAAQ,KAAK,KAAK,EAAE,KAAK,KAAK;AACtD,gBAAU,UAAU,UAAU,KAAK;AAAA,IACrC;AAEA,UAAM,kBAAuC;AAAA,MAC3C,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,KAAK;AAAA,MACL,GAAG;AAAA,IACL;AAEA,UAAM,uBAAuB,CAAC,OAAe,UAAmB,eAA8C;AAC5G,YAAM,YAAY,iBAAiB;AAEnC,UAAI,YAAY;AACd,eAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,QAAQ;AAAA,UACR,UAAU;AAAA,QACZ;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,iBAAiB,YAAY,8BAA8B;AAAA,QAC3D,cAAc;AAAA,QACd,WAAW,YAAY,4BAA4B;AAAA,QACnD,SAAS,YAAY,UAAU;AAAA,QAC/B,QAAQ,YAAY,MAAM;AAAA,QAC1B,QAAQ,WAAW,YAAY;AAAA,QAC/B,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,aAAa,CAAC,UAAmB,eAA6C;AAAA,MAClF,YAAY,WACR,uEACA;AAAA,MACJ,UAAU;AAAA,MACV,YAAY,WAAW,MAAM;AAAA,MAC7B,OAAO,WACH,YACE,YACA,YACF,YACA,YACA;AAAA,MACJ,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAEA,UAAM,gBAAqC;AAAA,MACzC,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAEA,UAAM,uBAA4C;AAAA,MAChD,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,iBAAiB,kBAAkB,8BAA8B,kBAAkB,YAAY;AAAA,MAC/F,WAAW,kBAAkB,4BAA4B;AAAA,IAC3D;AAEA,UAAM,mBAAwC;AAAA,MAC5C,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,YAAY,kBAAkB,YAAY;AAAA,MAC1C,QAAQ;AAAA,MACR,UAAU;AAAA,IACZ;AAEA,UAAM,gBAAqC;AAAA,MACzC,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA,IACV;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,eAAa;AAAA,QAEZ,uBAAa,IAAI,CAAC,MAAM,UAAU;AACjC,gBAAM,WAAW,UAAU,aAAa,SAAS;AACjD,gBAAM,aAAa,gBAAgB,QAAQ,KAAK;AAEhD,cAAI,YAAY;AACd,mBACE,qBAAO,gBAAN,EACC;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,kBACP,SAAS,MAAM,mBAAmB,IAAI;AAAA,kBACtC,QAAQ,MAAM,mBAAmB,KAAK;AAAA,kBACtC,cAAc,MAAM,mBAAmB,IAAI;AAAA,kBAC3C,cAAc,MAAM,mBAAmB,KAAK;AAAA,kBAC5C,cAAW;AAAA,kBAEX;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM;AAAA,sBACN,OAAM;AAAA,sBACN,aAAa;AAAA,sBACb,OAAO,EAAE,SAAS,SAAS,YAAY,EAAE;AAAA;AAAA,kBAC3C;AAAA;AAAA,cACF;AAAA,cACA,oBAAC,UAAK,OAAO,eAAe,gBAAE;AAAA,iBAhBX,YAAY,KAAK,EAiBtC;AAAA,UAEJ;AAEA,gBAAM,iBAAiB;AAEvB,cAAI,UAAU;AAEZ,mBACE,qBAAO,gBAAN,EACC;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,qBAAqB,OAAO,IAAI;AAAA,kBACvC,cAAc,MAAM,gBAAgB,KAAK;AAAA,kBACzC,cAAc,MAAM,gBAAgB,IAAI;AAAA,kBACxC,SAAS,MAAM,gBAAgB,KAAK;AAAA,kBACpC,QAAQ,MAAM,gBAAgB,IAAI;AAAA,kBAClC,UAAU;AAAA,kBAEV,8BAAC,UAAK,OAAO,WAAW,MAAM,iBAAiB,KAAK,GACjD,yBAAe,OAClB;AAAA;AAAA,cACF;AAAA,cAEC,UACC;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,kBACP,SAAS;AAAA,kBACT,cAAc,MAAM,mBAAmB,IAAI;AAAA,kBAC3C,cAAc,MAAM,mBAAmB,KAAK;AAAA,kBAC5C,cAAW;AAAA,kBAEX;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAM;AAAA,wBACN,OAAM;AAAA,wBACN,aAAa;AAAA,wBACb,OAAO,EAAE,SAAS,SAAS,YAAY,EAAE;AAAA;AAAA,oBAC3C;AAAA,oBACC,mBACC,oBAAC,SAAI,OAAO,eAAe,mCAAqB;AAAA;AAAA;AAAA,cAEpD;AAAA,iBA/BiB,KAiCrB;AAAA,UAEJ;AAGA,gBAAM,UAAU,eAAe,OAAO,MAAM;AAC5C,iBACE,qBAAO,gBAAN,EACC;AAAA;AAAA,cAAC;AAAA;AAAA,gBACE,GAAI,eAAe,OAAO,EAAE,MAAM,eAAe,KAAK,IAAI,CAAC;AAAA,gBAC5D,OAAO;AAAA,kBACL,GAAG,qBAAqB,OAAO,KAAK;AAAA,kBACpC,QAAQ;AAAA,kBACR,YAAY;AAAA,gBACd;AAAA,gBACA,SAAS,CAAC,MAAM;AACd,sBAAI,CAAC,eAAe,QAAQ,eAAe,SAAS;AAClD,sBAAE,eAAe;AACjB,mCAAe,QAAQ;AAAA,kBACzB;AAAA,gBACF;AAAA,gBACA,cAAc,MAAM,gBAAgB,KAAK;AAAA,gBACzC,cAAc,MAAM,gBAAgB,IAAI;AAAA,gBACxC,SAAS,MAAM,gBAAgB,KAAK;AAAA,gBACpC,QAAQ,MAAM,gBAAgB,IAAI;AAAA,gBAElC;AAAA,sCAAC,UAAK,OAAO,WAAW,OAAO,iBAAiB,KAAK,GAClD,yBAAe,OAClB;AAAA,kBACC,eAAe,eACd;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAM;AAAA,sBACN,OAAO,iBAAiB,QAAQ,YAAY;AAAA,sBAC5C,aAAa;AAAA,sBACb,OAAO,EAAE,YAAY,OAAO,SAAS,gBAAgB,YAAY,EAAE;AAAA;AAAA,kBACrE;AAAA;AAAA;AAAA,YAEJ;AAAA,YACA,oBAAC,UAAK,OAAO,eAAe,gBAAE;AAAA,eA/BX,KAgCrB;AAAA,QAEJ,CAAC;AAAA;AAAA,IACH;AAAA,EAEJ;AACF;AAEA,YAAY,cAAc;","names":[]}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
// src/SearchGlobal/SearchGlobal.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Search, X } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var SearchGlobal = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
value = "",
|
|
8
|
+
onChange,
|
|
9
|
+
onSubmit,
|
|
10
|
+
onClear,
|
|
11
|
+
placeholder = "Search",
|
|
12
|
+
className,
|
|
13
|
+
style,
|
|
14
|
+
"data-testid": dataTestId
|
|
15
|
+
}, ref) => {
|
|
16
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
17
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
18
|
+
const inputRef = React.useRef(null);
|
|
19
|
+
React.useImperativeHandle(ref, () => inputRef.current);
|
|
20
|
+
const handleFocus = () => {
|
|
21
|
+
setIsFocused(true);
|
|
22
|
+
};
|
|
23
|
+
const handleBlur = () => {
|
|
24
|
+
setIsFocused(false);
|
|
25
|
+
};
|
|
26
|
+
const handleChange = (e) => {
|
|
27
|
+
onChange?.(e.target.value);
|
|
28
|
+
};
|
|
29
|
+
const handleKeyDown = (e) => {
|
|
30
|
+
if (e.key === "Enter") {
|
|
31
|
+
onSubmit?.(value);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const handleClear = () => {
|
|
35
|
+
onChange?.("");
|
|
36
|
+
onClear?.();
|
|
37
|
+
inputRef.current?.focus();
|
|
38
|
+
};
|
|
39
|
+
const containerStyles = {
|
|
40
|
+
position: "relative",
|
|
41
|
+
width: isFocused ? "300px" : "160px",
|
|
42
|
+
height: "32px",
|
|
43
|
+
backgroundColor: isFocused ? "#ffffff" : isHovered ? "#efefef" : "#f8f8f8",
|
|
44
|
+
borderRadius: "16px",
|
|
45
|
+
padding: "8px 16px",
|
|
46
|
+
display: "flex",
|
|
47
|
+
alignItems: "center",
|
|
48
|
+
gap: isFocused ? "8px" : "8px",
|
|
49
|
+
cursor: "text",
|
|
50
|
+
transition: "all 0.2s ease-in-out",
|
|
51
|
+
boxSizing: "border-box",
|
|
52
|
+
border: isFocused ? "1px solid #efefef" : "none",
|
|
53
|
+
boxShadow: isFocused ? "0px 0px 0px 3px #3cad51" : "none",
|
|
54
|
+
marginLeft: isFocused ? "-140px" : "0",
|
|
55
|
+
// Expand to the left
|
|
56
|
+
...style
|
|
57
|
+
};
|
|
58
|
+
const iconContainerStyles = {
|
|
59
|
+
display: "flex",
|
|
60
|
+
alignItems: "center",
|
|
61
|
+
justifyContent: "center",
|
|
62
|
+
flexShrink: 0,
|
|
63
|
+
padding: "2px"
|
|
64
|
+
};
|
|
65
|
+
const inputStyles = {
|
|
66
|
+
border: "none",
|
|
67
|
+
outline: "none",
|
|
68
|
+
backgroundColor: "transparent",
|
|
69
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
70
|
+
fontSize: "13px",
|
|
71
|
+
fontWeight: 400,
|
|
72
|
+
color: "#2f2f2f",
|
|
73
|
+
lineHeight: "1.5",
|
|
74
|
+
flex: 1,
|
|
75
|
+
width: "100%",
|
|
76
|
+
minWidth: 0
|
|
77
|
+
};
|
|
78
|
+
const keyboardShortcutStyles = {
|
|
79
|
+
display: "flex",
|
|
80
|
+
alignItems: "center",
|
|
81
|
+
gap: "0px",
|
|
82
|
+
flexShrink: 0
|
|
83
|
+
};
|
|
84
|
+
const keyStyles = {
|
|
85
|
+
border: "1px solid #2f2f2f",
|
|
86
|
+
borderRadius: "5px",
|
|
87
|
+
padding: "0px 3px",
|
|
88
|
+
height: "16px",
|
|
89
|
+
display: "flex",
|
|
90
|
+
alignItems: "center",
|
|
91
|
+
justifyContent: "center",
|
|
92
|
+
fontFamily: "'Work Sans', sans-serif",
|
|
93
|
+
fontSize: "8px",
|
|
94
|
+
fontWeight: 400,
|
|
95
|
+
color: "#2f2f2f",
|
|
96
|
+
letterSpacing: "-0.08px",
|
|
97
|
+
lineHeight: "1.5",
|
|
98
|
+
minWidth: "16px"
|
|
99
|
+
};
|
|
100
|
+
const plusStyles = {
|
|
101
|
+
fontFamily: "'Work Sans', sans-serif",
|
|
102
|
+
fontSize: "8px",
|
|
103
|
+
fontWeight: 400,
|
|
104
|
+
color: "#2f2f2f",
|
|
105
|
+
letterSpacing: "-0.08px",
|
|
106
|
+
lineHeight: "1.5",
|
|
107
|
+
padding: "0 2px"
|
|
108
|
+
};
|
|
109
|
+
const clearButtonStyles = {
|
|
110
|
+
display: "flex",
|
|
111
|
+
alignItems: "center",
|
|
112
|
+
justifyContent: "center",
|
|
113
|
+
flexShrink: 0,
|
|
114
|
+
width: "16px",
|
|
115
|
+
height: "16px",
|
|
116
|
+
cursor: "pointer",
|
|
117
|
+
border: "none",
|
|
118
|
+
background: "none",
|
|
119
|
+
padding: 0
|
|
120
|
+
};
|
|
121
|
+
const showKeyboardShortcut = isHovered && !isFocused;
|
|
122
|
+
const showClearButton = isFocused;
|
|
123
|
+
return /* @__PURE__ */ jsxs(
|
|
124
|
+
"div",
|
|
125
|
+
{
|
|
126
|
+
className,
|
|
127
|
+
style: containerStyles,
|
|
128
|
+
onMouseEnter: () => setIsHovered(true),
|
|
129
|
+
onMouseLeave: () => setIsHovered(false),
|
|
130
|
+
onClick: () => inputRef.current?.focus(),
|
|
131
|
+
"data-testid": dataTestId,
|
|
132
|
+
children: [
|
|
133
|
+
/* @__PURE__ */ jsx("div", { style: iconContainerStyles, children: /* @__PURE__ */ jsx(Search, { size: 12, color: "#2f2f2f", strokeWidth: 2 }) }),
|
|
134
|
+
/* @__PURE__ */ jsx(
|
|
135
|
+
"input",
|
|
136
|
+
{
|
|
137
|
+
ref: inputRef,
|
|
138
|
+
type: "text",
|
|
139
|
+
value,
|
|
140
|
+
onChange: handleChange,
|
|
141
|
+
onFocus: handleFocus,
|
|
142
|
+
onBlur: handleBlur,
|
|
143
|
+
onKeyDown: handleKeyDown,
|
|
144
|
+
placeholder: isFocused ? "" : placeholder,
|
|
145
|
+
style: inputStyles
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
showKeyboardShortcut && /* @__PURE__ */ jsxs("div", { style: keyboardShortcutStyles, children: [
|
|
149
|
+
/* @__PURE__ */ jsx("div", { style: keyStyles, children: "\u2318" }),
|
|
150
|
+
/* @__PURE__ */ jsx("span", { style: plusStyles, children: "+" }),
|
|
151
|
+
/* @__PURE__ */ jsx("div", { style: keyStyles, children: "K" })
|
|
152
|
+
] }),
|
|
153
|
+
showClearButton && /* @__PURE__ */ jsx(
|
|
154
|
+
"button",
|
|
155
|
+
{
|
|
156
|
+
type: "button",
|
|
157
|
+
onClick: handleClear,
|
|
158
|
+
style: clearButtonStyles,
|
|
159
|
+
"aria-label": "Clear search",
|
|
160
|
+
children: /* @__PURE__ */ jsx(X, { size: 13.333, color: "#2f2f2f", strokeWidth: 2 })
|
|
161
|
+
}
|
|
162
|
+
)
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
SearchGlobal.displayName = "SearchGlobal";
|
|
169
|
+
|
|
170
|
+
export {
|
|
171
|
+
SearchGlobal
|
|
172
|
+
};
|
|
173
|
+
//# sourceMappingURL=chunk-UPBHDBAK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SearchGlobal/SearchGlobal.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Search, X } from 'lucide-react';\n\nexport interface SearchGlobalProps {\n /**\n * Value of the search input\n */\n value?: string;\n /**\n * Callback when value changes\n */\n onChange?: (value: string) => void;\n /**\n * Callback when search is submitted\n */\n onSubmit?: (value: string) => void;\n /**\n * Callback when clear button is clicked\n */\n onClear?: () => void;\n /**\n * Placeholder text\n */\n placeholder?: string;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n}\n\n/**\n * SearchGlobal component - Arbor Design System\n *\n * A search input that expands from 160px to 300px when focused.\n * Shows keyboard shortcut (⌘ K) on hover and X button when focused.\n */\nexport const SearchGlobal = React.forwardRef<HTMLInputElement, SearchGlobalProps>(\n (\n {\n value = '',\n onChange,\n onSubmit,\n onClear,\n placeholder = 'Search',\n className,\n style,\n 'data-testid': dataTestId,\n },\n ref\n ) => {\n const [isFocused, setIsFocused] = React.useState(false);\n const [isHovered, setIsHovered] = React.useState(false);\n const inputRef = React.useRef<HTMLInputElement>(null);\n\n // Merge refs\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);\n\n const handleFocus = () => {\n setIsFocused(true);\n };\n\n const handleBlur = () => {\n setIsFocused(false);\n };\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange?.(e.target.value);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n onSubmit?.(value);\n }\n };\n\n const handleClear = () => {\n onChange?.('');\n onClear?.();\n inputRef.current?.focus();\n };\n\n const containerStyles: React.CSSProperties = {\n position: 'relative',\n width: isFocused ? '300px' : '160px',\n height: '32px',\n backgroundColor: isFocused ? '#ffffff' : isHovered ? '#efefef' : '#f8f8f8',\n borderRadius: '16px',\n padding: '8px 16px',\n display: 'flex',\n alignItems: 'center',\n gap: isFocused ? '8px' : '8px',\n cursor: 'text',\n transition: 'all 0.2s ease-in-out',\n boxSizing: 'border-box',\n border: isFocused ? '1px solid #efefef' : 'none',\n boxShadow: isFocused ? '0px 0px 0px 3px #3cad51' : 'none',\n marginLeft: isFocused ? '-140px' : '0', // Expand to the left\n ...style,\n };\n\n const iconContainerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n padding: '2px',\n };\n\n const inputStyles: React.CSSProperties = {\n border: 'none',\n outline: 'none',\n backgroundColor: 'transparent',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: '13px',\n fontWeight: 400,\n color: '#2f2f2f',\n lineHeight: '1.5',\n flex: 1,\n width: '100%',\n minWidth: 0,\n };\n\n const keyboardShortcutStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '0px',\n flexShrink: 0,\n };\n\n const keyStyles: React.CSSProperties = {\n border: '1px solid #2f2f2f',\n borderRadius: '5px',\n padding: '0px 3px',\n height: '16px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontFamily: \"'Work Sans', sans-serif\",\n fontSize: '8px',\n fontWeight: 400,\n color: '#2f2f2f',\n letterSpacing: '-0.08px',\n lineHeight: '1.5',\n minWidth: '16px',\n };\n\n const plusStyles: React.CSSProperties = {\n fontFamily: \"'Work Sans', sans-serif\",\n fontSize: '8px',\n fontWeight: 400,\n color: '#2f2f2f',\n letterSpacing: '-0.08px',\n lineHeight: '1.5',\n padding: '0 2px',\n };\n\n const clearButtonStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '16px',\n height: '16px',\n cursor: 'pointer',\n border: 'none',\n background: 'none',\n padding: 0,\n };\n\n const showKeyboardShortcut = isHovered && !isFocused;\n const showClearButton = isFocused;\n\n return (\n <div\n className={className}\n style={containerStyles}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onClick={() => inputRef.current?.focus()}\n data-testid={dataTestId}\n >\n <div style={iconContainerStyles}>\n <Search size={12} color=\"#2f2f2f\" strokeWidth={2} />\n </div>\n\n <input\n ref={inputRef}\n type=\"text\"\n value={value}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder={isFocused ? '' : placeholder}\n style={inputStyles}\n />\n\n {showKeyboardShortcut && (\n <div style={keyboardShortcutStyles}>\n <div style={keyStyles}>⌘</div>\n <span style={plusStyles}>+</span>\n <div style={keyStyles}>K</div>\n </div>\n )}\n\n {showClearButton && (\n <button\n type=\"button\"\n onClick={handleClear}\n style={clearButtonStyles}\n aria-label=\"Clear search\"\n >\n <X size={13.333} color=\"#2f2f2f\" strokeWidth={2} />\n </button>\n )}\n </div>\n );\n }\n);\n\nSearchGlobal.displayName = 'SearchGlobal';\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// src/SubSectionInteractive/SubSectionInteractive.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { clsx } from "clsx";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var ChevronIcon = ({ expanded }) => /* @__PURE__ */ jsx(
|
|
6
|
+
"svg",
|
|
7
|
+
{
|
|
8
|
+
width: "16",
|
|
9
|
+
height: "16",
|
|
10
|
+
viewBox: "0 0 16 16",
|
|
11
|
+
fill: "none",
|
|
12
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
13
|
+
style: {
|
|
14
|
+
transform: expanded ? "rotate(0deg)" : "rotate(180deg)",
|
|
15
|
+
transition: "transform 0.2s ease-in-out"
|
|
16
|
+
},
|
|
17
|
+
children: /* @__PURE__ */ jsx(
|
|
18
|
+
"path",
|
|
19
|
+
{
|
|
20
|
+
d: "M4 6L8 10L12 6",
|
|
21
|
+
stroke: "#2f2f2f",
|
|
22
|
+
strokeWidth: "1.2",
|
|
23
|
+
strokeLinecap: "round",
|
|
24
|
+
strokeLinejoin: "round"
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
var subSectionInteractiveStyles = {
|
|
30
|
+
container: {
|
|
31
|
+
display: "flex",
|
|
32
|
+
flexDirection: "column",
|
|
33
|
+
width: "100%",
|
|
34
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
35
|
+
boxSizing: "border-box"
|
|
36
|
+
},
|
|
37
|
+
header: {
|
|
38
|
+
display: "flex",
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
width: "100%",
|
|
41
|
+
cursor: "pointer",
|
|
42
|
+
border: "none",
|
|
43
|
+
background: "transparent",
|
|
44
|
+
padding: 0,
|
|
45
|
+
margin: 0,
|
|
46
|
+
textAlign: "left",
|
|
47
|
+
outline: "none"
|
|
48
|
+
},
|
|
49
|
+
headerContent: {
|
|
50
|
+
display: "flex",
|
|
51
|
+
alignItems: "center",
|
|
52
|
+
justifyContent: "space-between",
|
|
53
|
+
width: "100%",
|
|
54
|
+
padding: "12px 8px",
|
|
55
|
+
borderRadius: "8px",
|
|
56
|
+
transition: "background-color 0.15s ease-in-out",
|
|
57
|
+
minHeight: "16px",
|
|
58
|
+
gap: "12px"
|
|
59
|
+
},
|
|
60
|
+
headerContentHover: {
|
|
61
|
+
backgroundColor: "#f8f8f8"
|
|
62
|
+
},
|
|
63
|
+
headerContentFocus: {
|
|
64
|
+
outline: "3px solid #3cad51",
|
|
65
|
+
outlineOffset: "-3px"
|
|
66
|
+
},
|
|
67
|
+
title: {
|
|
68
|
+
fontSize: "18px",
|
|
69
|
+
fontWeight: "600",
|
|
70
|
+
color: "#2f2f2f",
|
|
71
|
+
lineHeight: "1.25",
|
|
72
|
+
margin: 0,
|
|
73
|
+
flex: 1,
|
|
74
|
+
whiteSpace: "nowrap"
|
|
75
|
+
},
|
|
76
|
+
iconWrapper: {
|
|
77
|
+
display: "flex",
|
|
78
|
+
alignItems: "center",
|
|
79
|
+
justifyContent: "center",
|
|
80
|
+
width: "16px",
|
|
81
|
+
height: "16px",
|
|
82
|
+
flexShrink: 0
|
|
83
|
+
},
|
|
84
|
+
content: {
|
|
85
|
+
overflow: "hidden",
|
|
86
|
+
transition: "max-height 0.3s ease-in-out, opacity 0.2s ease-in-out"
|
|
87
|
+
},
|
|
88
|
+
contentExpanded: {
|
|
89
|
+
maxHeight: "2000px",
|
|
90
|
+
opacity: 1
|
|
91
|
+
},
|
|
92
|
+
contentCollapsed: {
|
|
93
|
+
maxHeight: "0px",
|
|
94
|
+
opacity: 0
|
|
95
|
+
},
|
|
96
|
+
contentInner: {
|
|
97
|
+
borderBottom: "1px solid #f8f8f8"
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var SubSectionInteractive = React.forwardRef(
|
|
101
|
+
({
|
|
102
|
+
title,
|
|
103
|
+
children,
|
|
104
|
+
expanded: controlledExpanded,
|
|
105
|
+
defaultExpanded = true,
|
|
106
|
+
onExpandedChange,
|
|
107
|
+
className,
|
|
108
|
+
style,
|
|
109
|
+
...props
|
|
110
|
+
}, ref) => {
|
|
111
|
+
const [internalExpanded, setInternalExpanded] = React.useState(defaultExpanded);
|
|
112
|
+
const isControlled = controlledExpanded !== void 0;
|
|
113
|
+
const isExpanded = isControlled ? controlledExpanded : internalExpanded;
|
|
114
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
115
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
116
|
+
const handleToggle = () => {
|
|
117
|
+
const newExpanded = !isExpanded;
|
|
118
|
+
if (!isControlled) {
|
|
119
|
+
setInternalExpanded(newExpanded);
|
|
120
|
+
}
|
|
121
|
+
onExpandedChange?.(newExpanded);
|
|
122
|
+
};
|
|
123
|
+
const handleKeyDown = (event) => {
|
|
124
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
handleToggle();
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const headerContentStyle = {
|
|
130
|
+
...subSectionInteractiveStyles.headerContent,
|
|
131
|
+
...isHovered && subSectionInteractiveStyles.headerContentHover,
|
|
132
|
+
...isFocused && subSectionInteractiveStyles.headerContentFocus
|
|
133
|
+
};
|
|
134
|
+
const contentStyle = {
|
|
135
|
+
...subSectionInteractiveStyles.content,
|
|
136
|
+
...isExpanded ? subSectionInteractiveStyles.contentExpanded : subSectionInteractiveStyles.contentCollapsed
|
|
137
|
+
};
|
|
138
|
+
return /* @__PURE__ */ jsxs(
|
|
139
|
+
"div",
|
|
140
|
+
{
|
|
141
|
+
ref,
|
|
142
|
+
className: clsx("arbor-sub-section-interactive", className),
|
|
143
|
+
style: { ...subSectionInteractiveStyles.container, ...style },
|
|
144
|
+
...props,
|
|
145
|
+
children: [
|
|
146
|
+
/* @__PURE__ */ jsx(
|
|
147
|
+
"button",
|
|
148
|
+
{
|
|
149
|
+
type: "button",
|
|
150
|
+
style: subSectionInteractiveStyles.header,
|
|
151
|
+
onClick: handleToggle,
|
|
152
|
+
onMouseEnter: () => setIsHovered(true),
|
|
153
|
+
onMouseLeave: () => setIsHovered(false),
|
|
154
|
+
onFocus: () => setIsFocused(true),
|
|
155
|
+
onBlur: () => setIsFocused(false),
|
|
156
|
+
onKeyDown: handleKeyDown,
|
|
157
|
+
"aria-expanded": isExpanded,
|
|
158
|
+
children: /* @__PURE__ */ jsxs("div", { style: headerContentStyle, children: [
|
|
159
|
+
/* @__PURE__ */ jsx("h3", { style: subSectionInteractiveStyles.title, children: title }),
|
|
160
|
+
/* @__PURE__ */ jsx("span", { style: subSectionInteractiveStyles.iconWrapper, children: /* @__PURE__ */ jsx(ChevronIcon, { expanded: isExpanded }) })
|
|
161
|
+
] })
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ jsx("div", { style: contentStyle, "aria-hidden": !isExpanded, children: children && /* @__PURE__ */ jsx("div", { style: subSectionInteractiveStyles.contentInner, children }) })
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
SubSectionInteractive.displayName = "SubSectionInteractive";
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
SubSectionInteractive
|
|
174
|
+
};
|
|
175
|
+
//# sourceMappingURL=chunk-X2CW5GF3.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/SubSectionInteractive/SubSectionInteractive.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface SubSectionInteractiveProps {\n /**\n * The heading text (required)\n */\n title: string;\n /**\n * Content to display when expanded (list rows, etc.)\n */\n children?: React.ReactNode;\n /**\n * Whether the section is expanded (controlled mode)\n */\n expanded?: boolean;\n /**\n * Default expanded state (uncontrolled mode)\n * @default true\n */\n defaultExpanded?: boolean;\n /**\n * Callback when expanded state changes\n */\n onExpandedChange?: (expanded: boolean) => void;\n /**\n * Additional CSS class name\n */\n className?: string;\n /**\n * Additional inline styles\n */\n style?: React.CSSProperties;\n}\n\n// Chevron icon - rotates based on expanded state\nconst ChevronIcon = ({ expanded }: { expanded: boolean }) => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n transform: expanded ? 'rotate(0deg)' : 'rotate(180deg)',\n transition: 'transform 0.2s ease-in-out',\n }}\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"#2f2f2f\"\n strokeWidth=\"1.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n);\n\n// Arbor Design System sub-section interactive styles\nconst subSectionInteractiveStyles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n width: '100%',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n boxSizing: 'border-box' as const,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n cursor: 'pointer',\n border: 'none',\n background: 'transparent',\n padding: 0,\n margin: 0,\n textAlign: 'left' as const,\n outline: 'none',\n },\n headerContent: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n padding: '12px 8px',\n borderRadius: '8px',\n transition: 'background-color 0.15s ease-in-out',\n minHeight: '16px',\n gap: '12px',\n },\n headerContentHover: {\n backgroundColor: '#f8f8f8',\n },\n headerContentFocus: {\n outline: '3px solid #3cad51',\n outlineOffset: '-3px',\n },\n title: {\n fontSize: '18px',\n fontWeight: '600',\n color: '#2f2f2f',\n lineHeight: '1.25',\n margin: 0,\n flex: 1,\n whiteSpace: 'nowrap' as const,\n },\n iconWrapper: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '16px',\n height: '16px',\n flexShrink: 0,\n },\n content: {\n overflow: 'hidden',\n transition: 'max-height 0.3s ease-in-out, opacity 0.2s ease-in-out',\n },\n contentExpanded: {\n maxHeight: '2000px',\n opacity: 1,\n },\n contentCollapsed: {\n maxHeight: '0px',\n opacity: 0,\n },\n contentInner: {\n borderBottom: '1px solid #f8f8f8',\n },\n};\n\n/**\n * SubSectionInteractive component - Arbor Design System\n *\n * A collapsible sub-section component that can contain list rows and other content.\n * Click the header to expand/collapse the content area.\n *\n * @example\n * ```tsx\n * // Basic collapsible section\n * <SubSectionInteractive title=\"Personal Details\">\n * <ListRow label=\"Name\" value=\"John Smith\" />\n * <ListRow label=\"Email\" value=\"john@example.com\" />\n * </SubSectionInteractive>\n *\n * // Initially collapsed\n * <SubSectionInteractive title=\"Additional Info\" defaultExpanded={false}>\n * <ListRow label=\"Notes\" value=\"Some notes here\" />\n * </SubSectionInteractive>\n *\n * // Controlled mode\n * <SubSectionInteractive\n * title=\"Settings\"\n * expanded={isExpanded}\n * onExpandedChange={setIsExpanded}\n * >\n * <ListRow label=\"Theme\" value=\"Dark\" />\n * </SubSectionInteractive>\n * ```\n */\nexport const SubSectionInteractive = React.forwardRef<HTMLDivElement, SubSectionInteractiveProps>(\n (\n {\n title,\n children,\n expanded: controlledExpanded,\n defaultExpanded = true,\n onExpandedChange,\n className,\n style,\n ...props\n },\n ref\n ) => {\n // Support both controlled and uncontrolled modes\n const [internalExpanded, setInternalExpanded] = React.useState(defaultExpanded);\n const isControlled = controlledExpanded !== undefined;\n const isExpanded = isControlled ? controlledExpanded : internalExpanded;\n\n const [isHovered, setIsHovered] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n\n const handleToggle = () => {\n const newExpanded = !isExpanded;\n if (!isControlled) {\n setInternalExpanded(newExpanded);\n }\n onExpandedChange?.(newExpanded);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n handleToggle();\n }\n };\n\n const headerContentStyle: React.CSSProperties = {\n ...subSectionInteractiveStyles.headerContent,\n ...(isHovered && subSectionInteractiveStyles.headerContentHover),\n ...(isFocused && subSectionInteractiveStyles.headerContentFocus),\n };\n\n const contentStyle: React.CSSProperties = {\n ...subSectionInteractiveStyles.content,\n ...(isExpanded\n ? subSectionInteractiveStyles.contentExpanded\n : subSectionInteractiveStyles.contentCollapsed),\n };\n\n return (\n <div\n ref={ref}\n className={clsx('arbor-sub-section-interactive', className)}\n style={{ ...subSectionInteractiveStyles.container, ...style }}\n {...props}\n >\n <button\n type=\"button\"\n style={subSectionInteractiveStyles.header}\n onClick={handleToggle}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n aria-expanded={isExpanded}\n >\n <div style={headerContentStyle}>\n <h3 style={subSectionInteractiveStyles.title}>{title}</h3>\n <span style={subSectionInteractiveStyles.iconWrapper}>\n <ChevronIcon expanded={isExpanded} />\n </span>\n </div>\n </button>\n <div style={contentStyle} aria-hidden={!isExpanded}>\n {children && (\n <div style={subSectionInteractiveStyles.contentInner}>{children}</div>\n )}\n </div>\n </div>\n );\n }\n);\n\nSubSectionInteractive.displayName = 'SubSectionInteractive';\n"],"mappings":"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","names":[]}
|