@tonyarbor/components 0.4.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/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/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-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-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-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 +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1440 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -0
- package/package.json +51 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ButtonSegmentedItem {
|
|
4
|
+
/**
|
|
5
|
+
* The label text for the button
|
|
6
|
+
*/
|
|
7
|
+
label: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional icon to display before the label
|
|
10
|
+
*/
|
|
11
|
+
icon?: React.ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Optional value identifier for the button
|
|
14
|
+
*/
|
|
15
|
+
value?: string;
|
|
16
|
+
}
|
|
17
|
+
interface ButtonSegmentedProps {
|
|
18
|
+
/**
|
|
19
|
+
* Array of button items (minimum 2, maximum 4)
|
|
20
|
+
*/
|
|
21
|
+
items: ButtonSegmentedItem[];
|
|
22
|
+
/**
|
|
23
|
+
* The index of the currently active button
|
|
24
|
+
* @default 0
|
|
25
|
+
*/
|
|
26
|
+
activeIndex?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback when a button is clicked
|
|
29
|
+
*/
|
|
30
|
+
onChange?: (index: number, item: ButtonSegmentedItem) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Additional CSS class name
|
|
33
|
+
*/
|
|
34
|
+
className?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Additional inline styles
|
|
37
|
+
*/
|
|
38
|
+
style?: React.CSSProperties;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* ButtonSegmented component - Arbor Design System
|
|
42
|
+
*
|
|
43
|
+
* A segmented button group where one button is always active.
|
|
44
|
+
* Supports 2-4 buttons with optional icons.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <ButtonSegmented
|
|
49
|
+
* items={[
|
|
50
|
+
* { label: 'Day' },
|
|
51
|
+
* { label: 'Week' },
|
|
52
|
+
* { label: 'Month' },
|
|
53
|
+
* ]}
|
|
54
|
+
* activeIndex={0}
|
|
55
|
+
* onChange={(index, item) => console.log(index, item)}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare const ButtonSegmented: React.ForwardRefExoticComponent<ButtonSegmentedProps & React.RefAttributes<HTMLDivElement>>;
|
|
60
|
+
|
|
61
|
+
export { ButtonSegmented, type ButtonSegmentedItem, type ButtonSegmentedProps };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ButtonSegmentedItem {
|
|
4
|
+
/**
|
|
5
|
+
* The label text for the button
|
|
6
|
+
*/
|
|
7
|
+
label: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional icon to display before the label
|
|
10
|
+
*/
|
|
11
|
+
icon?: React.ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Optional value identifier for the button
|
|
14
|
+
*/
|
|
15
|
+
value?: string;
|
|
16
|
+
}
|
|
17
|
+
interface ButtonSegmentedProps {
|
|
18
|
+
/**
|
|
19
|
+
* Array of button items (minimum 2, maximum 4)
|
|
20
|
+
*/
|
|
21
|
+
items: ButtonSegmentedItem[];
|
|
22
|
+
/**
|
|
23
|
+
* The index of the currently active button
|
|
24
|
+
* @default 0
|
|
25
|
+
*/
|
|
26
|
+
activeIndex?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback when a button is clicked
|
|
29
|
+
*/
|
|
30
|
+
onChange?: (index: number, item: ButtonSegmentedItem) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Additional CSS class name
|
|
33
|
+
*/
|
|
34
|
+
className?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Additional inline styles
|
|
37
|
+
*/
|
|
38
|
+
style?: React.CSSProperties;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* ButtonSegmented component - Arbor Design System
|
|
42
|
+
*
|
|
43
|
+
* A segmented button group where one button is always active.
|
|
44
|
+
* Supports 2-4 buttons with optional icons.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* <ButtonSegmented
|
|
49
|
+
* items={[
|
|
50
|
+
* { label: 'Day' },
|
|
51
|
+
* { label: 'Week' },
|
|
52
|
+
* { label: 'Month' },
|
|
53
|
+
* ]}
|
|
54
|
+
* activeIndex={0}
|
|
55
|
+
* onChange={(index, item) => console.log(index, item)}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
declare const ButtonSegmented: React.ForwardRefExoticComponent<ButtonSegmentedProps & React.RefAttributes<HTMLDivElement>>;
|
|
60
|
+
|
|
61
|
+
export { ButtonSegmented, type ButtonSegmentedItem, type ButtonSegmentedProps };
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/ButtonSegmented/index.ts
|
|
31
|
+
var ButtonSegmented_exports = {};
|
|
32
|
+
__export(ButtonSegmented_exports, {
|
|
33
|
+
ButtonSegmented: () => ButtonSegmented
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(ButtonSegmented_exports);
|
|
36
|
+
|
|
37
|
+
// src/ButtonSegmented/ButtonSegmented.tsx
|
|
38
|
+
var React = __toESM(require("react"));
|
|
39
|
+
var import_clsx = require("clsx");
|
|
40
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
|
+
var segmentedStyles = {
|
|
42
|
+
container: {
|
|
43
|
+
display: "inline-flex",
|
|
44
|
+
alignItems: "center",
|
|
45
|
+
gap: "8px",
|
|
46
|
+
padding: "8px",
|
|
47
|
+
backgroundColor: "#ffffff",
|
|
48
|
+
border: "1px solid #efefef",
|
|
49
|
+
borderRadius: "99px",
|
|
50
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
|
|
51
|
+
},
|
|
52
|
+
button: {
|
|
53
|
+
base: {
|
|
54
|
+
display: "inline-flex",
|
|
55
|
+
alignItems: "center",
|
|
56
|
+
justifyContent: "center",
|
|
57
|
+
gap: "8px",
|
|
58
|
+
padding: "8px 16px",
|
|
59
|
+
borderRadius: "99px",
|
|
60
|
+
border: "none",
|
|
61
|
+
cursor: "pointer",
|
|
62
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
63
|
+
fontSize: "13px",
|
|
64
|
+
fontWeight: "600",
|
|
65
|
+
lineHeight: "1.5",
|
|
66
|
+
transition: "all 0.15s ease-in-out",
|
|
67
|
+
outline: "none",
|
|
68
|
+
whiteSpace: "nowrap"
|
|
69
|
+
},
|
|
70
|
+
default: {
|
|
71
|
+
backgroundColor: "transparent",
|
|
72
|
+
color: "#595959"
|
|
73
|
+
},
|
|
74
|
+
hover: {
|
|
75
|
+
backgroundColor: "#f8f8f8",
|
|
76
|
+
color: "#2f2f2f"
|
|
77
|
+
},
|
|
78
|
+
active: {
|
|
79
|
+
backgroundColor: "#0e8a0e",
|
|
80
|
+
color: "#ffffff"
|
|
81
|
+
},
|
|
82
|
+
activeHover: {
|
|
83
|
+
backgroundColor: "#005700",
|
|
84
|
+
color: "#ffffff"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var ButtonSegmented = React.forwardRef(
|
|
89
|
+
({ items, activeIndex = 0, onChange, className, style, ...props }, ref) => {
|
|
90
|
+
const [hoveredIndex, setHoveredIndex] = React.useState(null);
|
|
91
|
+
const validItems = items.slice(0, 4);
|
|
92
|
+
if (validItems.length < 2) {
|
|
93
|
+
console.warn("ButtonSegmented requires at least 2 items");
|
|
94
|
+
}
|
|
95
|
+
const hasIcons = validItems.some((item) => item.icon);
|
|
96
|
+
const handleClick = (index) => {
|
|
97
|
+
if (index !== activeIndex && onChange) {
|
|
98
|
+
onChange(index, validItems[index]);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
102
|
+
"div",
|
|
103
|
+
{
|
|
104
|
+
ref,
|
|
105
|
+
className: (0, import_clsx.clsx)("arbor-button-segmented", className),
|
|
106
|
+
style: { ...segmentedStyles.container, ...style },
|
|
107
|
+
role: "group",
|
|
108
|
+
"aria-label": "Segmented button group",
|
|
109
|
+
...props,
|
|
110
|
+
children: validItems.map((item, index) => {
|
|
111
|
+
const isActive = index === activeIndex;
|
|
112
|
+
const isHovered = hoveredIndex === index;
|
|
113
|
+
let buttonStyle = {
|
|
114
|
+
...segmentedStyles.button.base
|
|
115
|
+
};
|
|
116
|
+
if (isActive) {
|
|
117
|
+
buttonStyle = {
|
|
118
|
+
...buttonStyle,
|
|
119
|
+
...segmentedStyles.button.active,
|
|
120
|
+
...isHovered && segmentedStyles.button.activeHover
|
|
121
|
+
};
|
|
122
|
+
} else {
|
|
123
|
+
buttonStyle = {
|
|
124
|
+
...buttonStyle,
|
|
125
|
+
...segmentedStyles.button.default,
|
|
126
|
+
...isHovered && segmentedStyles.button.hover
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
130
|
+
"button",
|
|
131
|
+
{
|
|
132
|
+
type: "button",
|
|
133
|
+
style: buttonStyle,
|
|
134
|
+
onClick: () => handleClick(index),
|
|
135
|
+
onMouseEnter: () => setHoveredIndex(index),
|
|
136
|
+
onMouseLeave: () => setHoveredIndex(null),
|
|
137
|
+
"aria-pressed": isActive,
|
|
138
|
+
children: [
|
|
139
|
+
hasIcons && item.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
140
|
+
"span",
|
|
141
|
+
{
|
|
142
|
+
style: {
|
|
143
|
+
display: "flex",
|
|
144
|
+
alignItems: "center",
|
|
145
|
+
justifyContent: "center",
|
|
146
|
+
width: "16px",
|
|
147
|
+
height: "16px"
|
|
148
|
+
},
|
|
149
|
+
children: item.icon
|
|
150
|
+
}
|
|
151
|
+
),
|
|
152
|
+
item.label
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
item.value || index
|
|
156
|
+
);
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
ButtonSegmented.displayName = "ButtonSegmented";
|
|
163
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
164
|
+
0 && (module.exports = {
|
|
165
|
+
ButtonSegmented
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=ButtonSegmented.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ButtonSegmented/index.ts","../src/ButtonSegmented/ButtonSegmented.tsx"],"sourcesContent":["export { ButtonSegmented } from './ButtonSegmented';\nexport type { ButtonSegmentedProps, ButtonSegmentedItem } from './ButtonSegmented';\n","import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface ButtonSegmentedItem {\n /**\n * The label text for the button\n */\n label: string;\n /**\n * Optional icon to display before the label\n */\n icon?: React.ReactNode;\n /**\n * Optional value identifier for the button\n */\n value?: string;\n}\n\nexport interface ButtonSegmentedProps {\n /**\n * Array of button items (minimum 2, maximum 4)\n */\n items: ButtonSegmentedItem[];\n /**\n * The index of the currently active button\n * @default 0\n */\n activeIndex?: number;\n /**\n * Callback when a button is clicked\n */\n onChange?: (index: number, item: ButtonSegmentedItem) => void;\n /**\n * Additional CSS class name\n */\n className?: string;\n /**\n * Additional inline styles\n */\n style?: React.CSSProperties;\n}\n\n// Arbor Design System segmented button styles\nconst segmentedStyles = {\n container: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: '8px',\n padding: '8px',\n backgroundColor: '#ffffff',\n border: '1px solid #efefef',\n borderRadius: '99px',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n },\n button: {\n base: {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '8px',\n padding: '8px 16px',\n borderRadius: '99px',\n border: 'none',\n cursor: 'pointer',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: '13px',\n fontWeight: '600',\n lineHeight: '1.5',\n transition: 'all 0.15s ease-in-out',\n outline: 'none',\n whiteSpace: 'nowrap' as const,\n },\n default: {\n backgroundColor: 'transparent',\n color: '#595959',\n },\n hover: {\n backgroundColor: '#f8f8f8',\n color: '#2f2f2f',\n },\n active: {\n backgroundColor: '#0e8a0e',\n color: '#ffffff',\n },\n activeHover: {\n backgroundColor: '#005700',\n color: '#ffffff',\n },\n },\n};\n\n/**\n * ButtonSegmented component - Arbor Design System\n *\n * A segmented button group where one button is always active.\n * Supports 2-4 buttons with optional icons.\n *\n * @example\n * ```tsx\n * <ButtonSegmented\n * items={[\n * { label: 'Day' },\n * { label: 'Week' },\n * { label: 'Month' },\n * ]}\n * activeIndex={0}\n * onChange={(index, item) => console.log(index, item)}\n * />\n * ```\n */\nexport const ButtonSegmented = React.forwardRef<HTMLDivElement, ButtonSegmentedProps>(\n ({ items, activeIndex = 0, onChange, className, style, ...props }, ref) => {\n const [hoveredIndex, setHoveredIndex] = React.useState<number | null>(null);\n\n // Validate items count (2-4)\n const validItems = items.slice(0, 4);\n if (validItems.length < 2) {\n console.warn('ButtonSegmented requires at least 2 items');\n }\n\n // Check if any item has an icon - if so, all should have icons\n const hasIcons = validItems.some((item) => item.icon);\n\n const handleClick = (index: number) => {\n if (index !== activeIndex && onChange) {\n onChange(index, validItems[index]);\n }\n };\n\n return (\n <div\n ref={ref}\n className={clsx('arbor-button-segmented', className)}\n style={{ ...segmentedStyles.container, ...style }}\n role=\"group\"\n aria-label=\"Segmented button group\"\n {...props}\n >\n {validItems.map((item, index) => {\n const isActive = index === activeIndex;\n const isHovered = hoveredIndex === index;\n\n let buttonStyle: React.CSSProperties = {\n ...segmentedStyles.button.base,\n };\n\n if (isActive) {\n buttonStyle = {\n ...buttonStyle,\n ...segmentedStyles.button.active,\n ...(isHovered && segmentedStyles.button.activeHover),\n };\n } else {\n buttonStyle = {\n ...buttonStyle,\n ...segmentedStyles.button.default,\n ...(isHovered && segmentedStyles.button.hover),\n };\n }\n\n return (\n <button\n key={item.value || index}\n type=\"button\"\n style={buttonStyle}\n onClick={() => handleClick(index)}\n onMouseEnter={() => setHoveredIndex(index)}\n onMouseLeave={() => setHoveredIndex(null)}\n aria-pressed={isActive}\n >\n {hasIcons && item.icon && (\n <span\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: '16px',\n height: '16px',\n }}\n >\n {item.icon}\n </span>\n )}\n {item.label}\n </button>\n );\n })}\n </div>\n );\n }\n);\n\nButtonSegmented.displayName = 'ButtonSegmented';\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ListRowProps {
|
|
4
|
+
/**
|
|
5
|
+
* The main value/content text (required)
|
|
6
|
+
*/
|
|
7
|
+
value: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional label text displayed on the left
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional note text displayed on the right (italic)
|
|
14
|
+
*/
|
|
15
|
+
note?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Show the right arrow icon - enables hover state and indicates row is clickable
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
icon?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Click handler - typically used with icon prop for navigation
|
|
23
|
+
*/
|
|
24
|
+
onClick?: () => void;
|
|
25
|
+
/**
|
|
26
|
+
* Additional CSS class name
|
|
27
|
+
*/
|
|
28
|
+
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Additional inline styles
|
|
31
|
+
*/
|
|
32
|
+
style?: React.CSSProperties;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* ListRow component - Arbor Design System
|
|
36
|
+
*
|
|
37
|
+
* A flexible list row component for displaying content within sections.
|
|
38
|
+
* Supports optional label, note, and icon props.
|
|
39
|
+
* Hover state is only enabled when icon is present (indicating clickable row).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* // Basic row with just value
|
|
44
|
+
* <ListRow value="John Smith" />
|
|
45
|
+
*
|
|
46
|
+
* // With label
|
|
47
|
+
* <ListRow label="Name" value="John Smith" />
|
|
48
|
+
*
|
|
49
|
+
* // With label and note
|
|
50
|
+
* <ListRow label="Name" value="John Smith" note="Primary contact" />
|
|
51
|
+
*
|
|
52
|
+
* // Clickable row with icon
|
|
53
|
+
* <ListRow
|
|
54
|
+
* label="Name"
|
|
55
|
+
* value="John Smith"
|
|
56
|
+
* icon
|
|
57
|
+
* onClick={() => navigate('/user/123')}
|
|
58
|
+
* />
|
|
59
|
+
*
|
|
60
|
+
* // All props
|
|
61
|
+
* <ListRow
|
|
62
|
+
* label="Name"
|
|
63
|
+
* value="John Smith"
|
|
64
|
+
* note="View profile"
|
|
65
|
+
* icon
|
|
66
|
+
* onClick={() => navigate('/user/123')}
|
|
67
|
+
* />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare const ListRow: React.ForwardRefExoticComponent<ListRowProps & React.RefAttributes<HTMLDivElement>>;
|
|
71
|
+
|
|
72
|
+
export { ListRow, type ListRowProps };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ListRowProps {
|
|
4
|
+
/**
|
|
5
|
+
* The main value/content text (required)
|
|
6
|
+
*/
|
|
7
|
+
value: string;
|
|
8
|
+
/**
|
|
9
|
+
* Optional label text displayed on the left
|
|
10
|
+
*/
|
|
11
|
+
label?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional note text displayed on the right (italic)
|
|
14
|
+
*/
|
|
15
|
+
note?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Show the right arrow icon - enables hover state and indicates row is clickable
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
icon?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Click handler - typically used with icon prop for navigation
|
|
23
|
+
*/
|
|
24
|
+
onClick?: () => void;
|
|
25
|
+
/**
|
|
26
|
+
* Additional CSS class name
|
|
27
|
+
*/
|
|
28
|
+
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Additional inline styles
|
|
31
|
+
*/
|
|
32
|
+
style?: React.CSSProperties;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* ListRow component - Arbor Design System
|
|
36
|
+
*
|
|
37
|
+
* A flexible list row component for displaying content within sections.
|
|
38
|
+
* Supports optional label, note, and icon props.
|
|
39
|
+
* Hover state is only enabled when icon is present (indicating clickable row).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```tsx
|
|
43
|
+
* // Basic row with just value
|
|
44
|
+
* <ListRow value="John Smith" />
|
|
45
|
+
*
|
|
46
|
+
* // With label
|
|
47
|
+
* <ListRow label="Name" value="John Smith" />
|
|
48
|
+
*
|
|
49
|
+
* // With label and note
|
|
50
|
+
* <ListRow label="Name" value="John Smith" note="Primary contact" />
|
|
51
|
+
*
|
|
52
|
+
* // Clickable row with icon
|
|
53
|
+
* <ListRow
|
|
54
|
+
* label="Name"
|
|
55
|
+
* value="John Smith"
|
|
56
|
+
* icon
|
|
57
|
+
* onClick={() => navigate('/user/123')}
|
|
58
|
+
* />
|
|
59
|
+
*
|
|
60
|
+
* // All props
|
|
61
|
+
* <ListRow
|
|
62
|
+
* label="Name"
|
|
63
|
+
* value="John Smith"
|
|
64
|
+
* note="View profile"
|
|
65
|
+
* icon
|
|
66
|
+
* onClick={() => navigate('/user/123')}
|
|
67
|
+
* />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare const ListRow: React.ForwardRefExoticComponent<ListRowProps & React.RefAttributes<HTMLDivElement>>;
|
|
71
|
+
|
|
72
|
+
export { ListRow, type ListRowProps };
|
package/dist/ListRow.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/ListRow/index.ts
|
|
31
|
+
var ListRow_exports = {};
|
|
32
|
+
__export(ListRow_exports, {
|
|
33
|
+
ListRow: () => ListRow
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(ListRow_exports);
|
|
36
|
+
|
|
37
|
+
// src/ListRow/ListRow.tsx
|
|
38
|
+
var React = __toESM(require("react"));
|
|
39
|
+
var import_clsx = require("clsx");
|
|
40
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
|
+
var CaretIcon = ({ isHovered }) => {
|
|
42
|
+
if (isHovered) {
|
|
43
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
44
|
+
"path",
|
|
45
|
+
{
|
|
46
|
+
d: "M6 4L10 8L6 12",
|
|
47
|
+
stroke: "#2f2f2f",
|
|
48
|
+
strokeWidth: "1.2",
|
|
49
|
+
strokeLinecap: "round",
|
|
50
|
+
strokeLinejoin: "round"
|
|
51
|
+
}
|
|
52
|
+
) });
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
55
|
+
"path",
|
|
56
|
+
{
|
|
57
|
+
d: "M6 4L10 8L6 12",
|
|
58
|
+
stroke: "#b3b3b3",
|
|
59
|
+
strokeWidth: "1.2",
|
|
60
|
+
strokeLinecap: "round",
|
|
61
|
+
strokeLinejoin: "round"
|
|
62
|
+
}
|
|
63
|
+
) });
|
|
64
|
+
};
|
|
65
|
+
var listRowStyles = {
|
|
66
|
+
container: {
|
|
67
|
+
display: "flex",
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
width: "100%",
|
|
70
|
+
borderBottom: "1px solid #f8f8f8",
|
|
71
|
+
fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
72
|
+
boxSizing: "border-box",
|
|
73
|
+
borderRadius: "8px",
|
|
74
|
+
transition: "background-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out",
|
|
75
|
+
outline: "none"
|
|
76
|
+
},
|
|
77
|
+
containerHover: {
|
|
78
|
+
backgroundColor: "#f8f8f8"
|
|
79
|
+
},
|
|
80
|
+
containerFocus: {
|
|
81
|
+
outline: "3px solid #3cad51",
|
|
82
|
+
outlineOffset: "-3px"
|
|
83
|
+
},
|
|
84
|
+
containerClickable: {
|
|
85
|
+
cursor: "pointer"
|
|
86
|
+
},
|
|
87
|
+
content: {
|
|
88
|
+
display: "flex",
|
|
89
|
+
alignItems: "center",
|
|
90
|
+
justifyContent: "space-between",
|
|
91
|
+
width: "100%",
|
|
92
|
+
padding: "4px 8px",
|
|
93
|
+
minHeight: "28px"
|
|
94
|
+
},
|
|
95
|
+
label: {
|
|
96
|
+
fontSize: "13px",
|
|
97
|
+
fontWeight: "600",
|
|
98
|
+
color: "#2f2f2f",
|
|
99
|
+
lineHeight: "1.5",
|
|
100
|
+
width: "190px",
|
|
101
|
+
flexShrink: 0
|
|
102
|
+
},
|
|
103
|
+
valueContainer: {
|
|
104
|
+
flex: 1,
|
|
105
|
+
display: "flex",
|
|
106
|
+
alignItems: "center"
|
|
107
|
+
},
|
|
108
|
+
value: {
|
|
109
|
+
fontSize: "13px",
|
|
110
|
+
fontWeight: "400",
|
|
111
|
+
color: "#2f2f2f",
|
|
112
|
+
lineHeight: "1.5"
|
|
113
|
+
},
|
|
114
|
+
rightContainer: {
|
|
115
|
+
display: "flex",
|
|
116
|
+
alignItems: "center",
|
|
117
|
+
justifyContent: "flex-end",
|
|
118
|
+
gap: "8px",
|
|
119
|
+
flexShrink: 0
|
|
120
|
+
},
|
|
121
|
+
note: {
|
|
122
|
+
fontSize: "13px",
|
|
123
|
+
fontWeight: "400",
|
|
124
|
+
fontStyle: "italic",
|
|
125
|
+
color: "#2f2f2f",
|
|
126
|
+
lineHeight: "1.5",
|
|
127
|
+
textAlign: "right"
|
|
128
|
+
},
|
|
129
|
+
iconWrapper: {
|
|
130
|
+
display: "flex",
|
|
131
|
+
alignItems: "center",
|
|
132
|
+
justifyContent: "center",
|
|
133
|
+
width: "16px",
|
|
134
|
+
height: "16px",
|
|
135
|
+
flexShrink: 0
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
var ListRow = React.forwardRef(
|
|
139
|
+
({ value, label, note, icon = false, onClick, className, style, ...props }, ref) => {
|
|
140
|
+
const [isHovered, setIsHovered] = React.useState(false);
|
|
141
|
+
const [isFocused, setIsFocused] = React.useState(false);
|
|
142
|
+
const showHoverState = icon && isHovered;
|
|
143
|
+
const isClickable = icon && onClick;
|
|
144
|
+
const containerStyle = {
|
|
145
|
+
...listRowStyles.container,
|
|
146
|
+
...showHoverState && listRowStyles.containerHover,
|
|
147
|
+
...isFocused && listRowStyles.containerFocus,
|
|
148
|
+
...isClickable && listRowStyles.containerClickable,
|
|
149
|
+
...style
|
|
150
|
+
};
|
|
151
|
+
const handleClick = () => {
|
|
152
|
+
if (isClickable && onClick) {
|
|
153
|
+
onClick();
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
const handleKeyDown = (event) => {
|
|
157
|
+
if (isClickable && (event.key === "Enter" || event.key === " ")) {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
onClick?.();
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
163
|
+
"div",
|
|
164
|
+
{
|
|
165
|
+
ref,
|
|
166
|
+
className: (0, import_clsx.clsx)("arbor-list-row", className),
|
|
167
|
+
style: containerStyle,
|
|
168
|
+
onClick: handleClick,
|
|
169
|
+
onMouseEnter: () => icon && setIsHovered(true),
|
|
170
|
+
onMouseLeave: () => setIsHovered(false),
|
|
171
|
+
onFocus: () => setIsFocused(true),
|
|
172
|
+
onBlur: () => setIsFocused(false),
|
|
173
|
+
onKeyDown: handleKeyDown,
|
|
174
|
+
tabIndex: isClickable ? 0 : void 0,
|
|
175
|
+
role: isClickable ? "button" : void 0,
|
|
176
|
+
...props,
|
|
177
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: listRowStyles.content, children: [
|
|
178
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: listRowStyles.label, children: label }),
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: listRowStyles.valueContainer, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: listRowStyles.value, children: value }) }),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: listRowStyles.rightContainer, children: [
|
|
181
|
+
note && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: listRowStyles.note, children: note }),
|
|
182
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: listRowStyles.iconWrapper, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CaretIcon, { isHovered }) })
|
|
183
|
+
] })
|
|
184
|
+
] })
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
ListRow.displayName = "ListRow";
|
|
190
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
191
|
+
0 && (module.exports = {
|
|
192
|
+
ListRow
|
|
193
|
+
});
|
|
194
|
+
//# sourceMappingURL=ListRow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ListRow/index.ts","../src/ListRow/ListRow.tsx"],"sourcesContent":["export { ListRow } from './ListRow';\nexport type { ListRowProps } from './ListRow';\n","import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface ListRowProps {\n /**\n * The main value/content text (required)\n */\n value: string;\n /**\n * Optional label text displayed on the left\n */\n label?: string;\n /**\n * Optional note text displayed on the right (italic)\n */\n note?: string;\n /**\n * Show the right arrow icon - enables hover state and indicates row is clickable\n * @default false\n */\n icon?: boolean;\n /**\n * Click handler - typically used with icon prop for navigation\n */\n onClick?: () => void;\n /**\n * Additional CSS class name\n */\n className?: string;\n /**\n * Additional inline styles\n */\n style?: React.CSSProperties;\n}\n\n// Caret/Arrow icon - transforms on hover\nconst CaretIcon = ({ isHovered }: { isHovered: boolean }) => {\n if (isHovered) {\n // Arrow pointing right on hover\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"#2f2f2f\"\n strokeWidth=\"1.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n }\n // Default caret (chevron right)\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M6 4L10 8L6 12\"\n stroke=\"#b3b3b3\"\n strokeWidth=\"1.2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n};\n\n// Arbor Design System list row styles\nconst listRowStyles = {\n container: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n borderBottom: '1px solid #f8f8f8',\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n boxSizing: 'border-box' as const,\n borderRadius: '8px',\n transition: 'background-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out',\n outline: 'none',\n },\n containerHover: {\n backgroundColor: '#f8f8f8',\n },\n containerFocus: {\n outline: '3px solid #3cad51',\n outlineOffset: '-3px',\n },\n containerClickable: {\n cursor: 'pointer',\n },\n content: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n padding: '4px 8px',\n minHeight: '28px',\n },\n label: {\n fontSize: '13px',\n fontWeight: '600',\n color: '#2f2f2f',\n lineHeight: '1.5',\n width: '190px',\n flexShrink: 0,\n },\n valueContainer: {\n flex: 1,\n display: 'flex',\n alignItems: 'center',\n },\n value: {\n fontSize: '13px',\n fontWeight: '400',\n color: '#2f2f2f',\n lineHeight: '1.5',\n },\n rightContainer: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: '8px',\n flexShrink: 0,\n },\n note: {\n fontSize: '13px',\n fontWeight: '400',\n fontStyle: 'italic',\n color: '#2f2f2f',\n lineHeight: '1.5',\n textAlign: 'right' 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};\n\n/**\n * ListRow component - Arbor Design System\n *\n * A flexible list row component for displaying content within sections.\n * Supports optional label, note, and icon props.\n * Hover state is only enabled when icon is present (indicating clickable row).\n *\n * @example\n * ```tsx\n * // Basic row with just value\n * <ListRow value=\"John Smith\" />\n *\n * // With label\n * <ListRow label=\"Name\" value=\"John Smith\" />\n *\n * // With label and note\n * <ListRow label=\"Name\" value=\"John Smith\" note=\"Primary contact\" />\n *\n * // Clickable row with icon\n * <ListRow\n * label=\"Name\"\n * value=\"John Smith\"\n * icon\n * onClick={() => navigate('/user/123')}\n * />\n *\n * // All props\n * <ListRow\n * label=\"Name\"\n * value=\"John Smith\"\n * note=\"View profile\"\n * icon\n * onClick={() => navigate('/user/123')}\n * />\n * ```\n */\nexport const ListRow = React.forwardRef<HTMLDivElement, ListRowProps>(\n ({ value, label, note, icon = false, onClick, className, style, ...props }, ref) => {\n const [isHovered, setIsHovered] = React.useState(false);\n const [isFocused, setIsFocused] = React.useState(false);\n\n // Only enable hover state when icon is present\n const showHoverState = icon && isHovered;\n const isClickable = icon && onClick;\n\n const containerStyle: React.CSSProperties = {\n ...listRowStyles.container,\n ...(showHoverState && listRowStyles.containerHover),\n ...(isFocused && listRowStyles.containerFocus),\n ...(isClickable && listRowStyles.containerClickable),\n ...style,\n };\n\n const handleClick = () => {\n if (isClickable && onClick) {\n onClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (isClickable && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n onClick?.();\n }\n };\n\n return (\n <div\n ref={ref}\n className={clsx('arbor-list-row', className)}\n style={containerStyle}\n onClick={handleClick}\n onMouseEnter={() => icon && setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onKeyDown={handleKeyDown}\n tabIndex={isClickable ? 0 : undefined}\n role={isClickable ? 'button' : undefined}\n {...props}\n >\n <div style={listRowStyles.content}>\n {label && <div style={listRowStyles.label}>{label}</div>}\n <div style={listRowStyles.valueContainer}>\n <span style={listRowStyles.value}>{value}</span>\n </div>\n <div style={listRowStyles.rightContainer}>\n {note && <span style={listRowStyles.note}>{note}</span>}\n {icon && (\n <div style={listRowStyles.iconWrapper}>\n <CaretIcon isHovered={isHovered} />\n </div>\n )}\n </div>\n </div>\n </div>\n );\n }\n);\n\nListRow.displayName = 'ListRow';\n"],"mappings":"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","names":[]}
|