beacon-ui 3.1.7 → 3.1.9
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/CHANGELOG.md +24 -0
- package/dist/components/Button.d.ts +3 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +52 -28
- package/dist/components/Menu.d.ts +25 -3
- package/dist/components/Menu.d.ts.map +1 -1
- package/dist/components/Menu.js +86 -29
- package/dist/components/MenuItem.d.ts +13 -0
- package/dist/components/MenuItem.d.ts.map +1 -0
- package/dist/components/MenuItem.js +90 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.1.9] - 2025-12-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Menu component now supports render props for full customization:
|
|
12
|
+
- `renderSwitch` - Customize or replace the Switch component with your own implementation
|
|
13
|
+
- `renderToggleButton` - Customize or replace the toggle button (menu/close icon) with your own component
|
|
14
|
+
- `renderButton` - Customize or replace the menu action button with your own component
|
|
15
|
+
- Menu component callback props for handling interactions:
|
|
16
|
+
- `onSwitchChange` - Callback when Switch value changes
|
|
17
|
+
- `onToggleButtonClick` - Callback when toggle button is clicked
|
|
18
|
+
- `onButtonClick` - Callback when menu action button is clicked
|
|
19
|
+
- Exported render prop types: `SwitchRenderProps`, `ToggleButtonRenderProps`, `MenuButtonRenderProps`
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Menu component now uses internal state management for Switch, allowing better control and customization
|
|
23
|
+
- Render props are optional - if not provided, Menu uses default components (backward compatible)
|
|
24
|
+
|
|
25
|
+
## [3.1.8] - 2025-12-29
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- Button component now preserves variant colors (success, critical, warning) when in loading state
|
|
29
|
+
- Previously, buttons would revert to default/primary color when loading was enabled
|
|
30
|
+
- Loading state no longer overrides variant-specific colors
|
|
31
|
+
|
|
8
32
|
## [3.1.7] - 2025-12-29
|
|
9
33
|
|
|
10
34
|
### Changed
|
|
@@ -4,6 +4,7 @@ export type ButtonSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
|
4
4
|
export type CornerRadiusStep = 0 | 1 | 2 | 3 | 4 | 5;
|
|
5
5
|
export type JustifyContent = "center" | "space-between";
|
|
6
6
|
export type ButtonState = "default" | "hovered" | "focused" | "pressed";
|
|
7
|
+
export type ButtonColor = "primary" | "success" | "critical" | "warning";
|
|
7
8
|
export interface ButtonProps extends Omit<ComponentPropsWithRef<"button">, "type"> {
|
|
8
9
|
variant?: ButtonVariant;
|
|
9
10
|
size?: ButtonSize;
|
|
@@ -14,8 +15,9 @@ export interface ButtonProps extends Omit<ComponentPropsWithRef<"button">, "type
|
|
|
14
15
|
justifyContent?: JustifyContent;
|
|
15
16
|
loading?: boolean;
|
|
16
17
|
state?: ButtonState;
|
|
18
|
+
color?: ButtonColor;
|
|
17
19
|
type?: "button" | "submit" | "reset";
|
|
18
20
|
children: React.ReactNode;
|
|
19
21
|
}
|
|
20
|
-
export declare function Button({ variant, size, cornerRadius, startIcon, endIcon, fillContainer, justifyContent, loading, disabled, state: stateProp, type, children, className, style, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, onMouseDown, onMouseUp, ref, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare function Button({ variant, size, cornerRadius, startIcon, endIcon, fillContainer, justifyContent, loading, disabled, state: stateProp, color, type, children, className, style, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, onMouseDown, onMouseUp, ref, ...rest }: ButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
21
23
|
//# sourceMappingURL=Button.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/components/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAI9E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,eAAe,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/components/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkC,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAI9E,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,eAAe,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AACxE,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAChF,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAkED,wBAAgB,MAAM,CAAC,EACrB,OAAkB,EAClB,IAAW,EACX,YAAgB,EAChB,SAAS,EACT,OAAO,EACP,aAAqB,EACrB,cAAyB,EACzB,OAAe,EACf,QAAgB,EAChB,KAAK,EAAE,SAAS,EAChB,KAAiB,EACjB,IAAe,EACf,QAAQ,EACR,SAAS,EACT,KAAK,EACL,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,GAAG,EACH,GAAG,IAAI,EACR,EAAE,WAAW,2CAiPb"}
|
|
@@ -55,7 +55,7 @@ const LOADER_ICON_SIZE_MAP = {
|
|
|
55
55
|
lg: 32,
|
|
56
56
|
xl: 40,
|
|
57
57
|
};
|
|
58
|
-
export function Button({ variant = "filled", size = "md", cornerRadius = 2, startIcon, endIcon, fillContainer = false, justifyContent = "center", loading = false, disabled = false, state: stateProp, type = "button", children, className, style, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, onMouseDown, onMouseUp, ref, ...rest }) {
|
|
58
|
+
export function Button({ variant = "filled", size = "md", cornerRadius = 2, startIcon, endIcon, fillContainer = false, justifyContent = "center", loading = false, disabled = false, state: stateProp, color = "primary", type = "button", children, className, style, onClick, onMouseEnter, onMouseLeave, onFocus, onBlur, onMouseDown, onMouseUp, ref, ...rest }) {
|
|
59
59
|
const themeContext = useThemeSafe();
|
|
60
60
|
const sizeConfig = SIZE_CONFIG[size];
|
|
61
61
|
const borderRadius = CORNER_RADIUS_MAP[cornerRadius];
|
|
@@ -97,7 +97,8 @@ export function Button({ variant = "filled", size = "md", cornerRadius = 2, star
|
|
|
97
97
|
}
|
|
98
98
|
onMouseUp?.(e);
|
|
99
99
|
}, [disabled, loading, stateProp, onMouseUp]);
|
|
100
|
-
const isDisabled = disabled
|
|
100
|
+
const isDisabled = disabled;
|
|
101
|
+
const isLoading = loading;
|
|
101
102
|
const currentState = isDisabled ? "default" : state;
|
|
102
103
|
const buttonStyles = useMemo(() => {
|
|
103
104
|
const baseStyles = {
|
|
@@ -113,7 +114,7 @@ export function Button({ variant = "filled", size = "md", cornerRadius = 2, star
|
|
|
113
114
|
borderStyle: "solid",
|
|
114
115
|
borderColor: "transparent",
|
|
115
116
|
borderRadius,
|
|
116
|
-
cursor: isDisabled ? "not-allowed" : "pointer",
|
|
117
|
+
cursor: (isDisabled || isLoading) ? "not-allowed" : "pointer",
|
|
117
118
|
transition: "background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease",
|
|
118
119
|
minHeight: sizeConfig.height,
|
|
119
120
|
paddingLeft: sizeConfig.paddingX,
|
|
@@ -123,34 +124,49 @@ export function Button({ variant = "filled", size = "md", cornerRadius = 2, star
|
|
|
123
124
|
width: fillContainer ? "100%" : "auto",
|
|
124
125
|
opacity: isDisabled ? 0.6 : 1,
|
|
125
126
|
};
|
|
127
|
+
// Get color token prefixes based on color prop
|
|
128
|
+
const colorPrefix = color === "primary" ? "primary" : color;
|
|
129
|
+
const bgToken = `--bg-${colorPrefix}`;
|
|
130
|
+
const bgTonalToken = `--bg-${colorPrefix}-tonal`;
|
|
131
|
+
const bgHoverToken = `--bg-${colorPrefix}-on-hover`;
|
|
132
|
+
const bgPressedToken = color === "primary" ? `--bg-${colorPrefix}-pressed` : `--bg-${colorPrefix}-on-hover`;
|
|
133
|
+
const bgFocusedToken = color === "primary" ? `--bg-${colorPrefix}-on-focused` : `--bg-${colorPrefix}-on-hover`;
|
|
134
|
+
const bgTonalHoverToken = color === "primary" ? `--bg-${colorPrefix}-tonal-on-hover` : `--bg-${colorPrefix}-tonal`;
|
|
135
|
+
const fgToken = `--fg-${colorPrefix}`;
|
|
136
|
+
const fgTonalToken = `--fg-${colorPrefix}-on-tonal`;
|
|
137
|
+
const fgHoverToken = color === "primary" ? `--fg-${colorPrefix}-on-hover` : `--fg-${colorPrefix}`;
|
|
138
|
+
const borderToken = `--border-${colorPrefix}`;
|
|
139
|
+
const borderTonalToken = `--border-${colorPrefix}-tonal`;
|
|
140
|
+
const borderHoverToken = color === "primary" ? `--border-${colorPrefix}-on-hover` : `--border-${colorPrefix}`;
|
|
141
|
+
// For non-primary colors, use the base border token for hover since there's no specific hover border token
|
|
126
142
|
// Get base variant styles
|
|
127
143
|
let variantStyles = {};
|
|
128
144
|
switch (variant) {
|
|
129
145
|
case "filled":
|
|
130
146
|
variantStyles = {
|
|
131
|
-
backgroundColor:
|
|
147
|
+
backgroundColor: `var(${bgToken})`,
|
|
132
148
|
color: "var(--fg-on-action)",
|
|
133
|
-
borderColor:
|
|
149
|
+
borderColor: `var(${bgToken})`,
|
|
134
150
|
};
|
|
135
151
|
break;
|
|
136
152
|
case "tonal":
|
|
137
153
|
variantStyles = {
|
|
138
|
-
backgroundColor:
|
|
139
|
-
color:
|
|
140
|
-
borderColor:
|
|
154
|
+
backgroundColor: `var(${bgTonalToken})`,
|
|
155
|
+
color: `var(${fgTonalToken})`,
|
|
156
|
+
borderColor: `var(${borderTonalToken})`,
|
|
141
157
|
};
|
|
142
158
|
break;
|
|
143
159
|
case "outline":
|
|
144
160
|
variantStyles = {
|
|
145
161
|
backgroundColor: "transparent",
|
|
146
|
-
color:
|
|
147
|
-
borderColor:
|
|
162
|
+
color: `var(${fgToken})`,
|
|
163
|
+
borderColor: `var(${borderToken})`,
|
|
148
164
|
};
|
|
149
165
|
break;
|
|
150
166
|
case "link":
|
|
151
167
|
variantStyles = {
|
|
152
168
|
backgroundColor: "transparent",
|
|
153
|
-
color:
|
|
169
|
+
color: `var(${fgToken})`,
|
|
154
170
|
borderWidth: 0,
|
|
155
171
|
borderStyle: "none",
|
|
156
172
|
borderColor: "transparent",
|
|
@@ -160,6 +176,7 @@ export function Button({ variant = "filled", size = "md", cornerRadius = 2, star
|
|
|
160
176
|
break;
|
|
161
177
|
}
|
|
162
178
|
// Apply state-specific overrides
|
|
179
|
+
// When loading, preserve variant colors and don't apply state-specific styles
|
|
163
180
|
const stateStyles = {};
|
|
164
181
|
if (isDisabled) {
|
|
165
182
|
if (variant === "filled") {
|
|
@@ -180,44 +197,51 @@ export function Button({ variant = "filled", size = "md", cornerRadius = 2, star
|
|
|
180
197
|
stateStyles.color = "var(--fg-disabled)";
|
|
181
198
|
}
|
|
182
199
|
}
|
|
183
|
-
else if (currentState === "hovered") {
|
|
200
|
+
else if (!isLoading && currentState === "hovered") {
|
|
184
201
|
if (variant === "filled") {
|
|
185
|
-
stateStyles.backgroundColor =
|
|
186
|
-
stateStyles.borderColor =
|
|
202
|
+
stateStyles.backgroundColor = `var(${bgHoverToken})`;
|
|
203
|
+
stateStyles.borderColor = `var(${bgHoverToken})`;
|
|
187
204
|
}
|
|
188
205
|
else if (variant === "tonal") {
|
|
189
|
-
stateStyles.backgroundColor =
|
|
206
|
+
stateStyles.backgroundColor = `var(${bgTonalHoverToken})`;
|
|
190
207
|
}
|
|
191
208
|
else if (variant === "outline") {
|
|
192
|
-
stateStyles.borderColor =
|
|
209
|
+
stateStyles.borderColor = `var(${borderHoverToken})`;
|
|
193
210
|
}
|
|
194
211
|
else if (variant === "link") {
|
|
195
|
-
stateStyles.color =
|
|
212
|
+
stateStyles.color = `var(${fgHoverToken})`;
|
|
196
213
|
}
|
|
197
214
|
}
|
|
198
|
-
else if (currentState === "pressed") {
|
|
215
|
+
else if (!isLoading && currentState === "pressed") {
|
|
199
216
|
if (variant === "filled") {
|
|
200
|
-
stateStyles.backgroundColor =
|
|
201
|
-
stateStyles.borderColor =
|
|
217
|
+
stateStyles.backgroundColor = `var(${bgPressedToken})`;
|
|
218
|
+
stateStyles.borderColor = `var(${bgPressedToken})`;
|
|
202
219
|
}
|
|
203
220
|
else if (variant === "tonal") {
|
|
204
|
-
stateStyles.backgroundColor =
|
|
221
|
+
stateStyles.backgroundColor = `var(${bgTonalHoverToken})`;
|
|
205
222
|
}
|
|
206
223
|
}
|
|
207
|
-
else if (currentState === "focused") {
|
|
224
|
+
else if (!isLoading && currentState === "focused") {
|
|
208
225
|
if (variant === "filled") {
|
|
209
|
-
stateStyles.backgroundColor =
|
|
210
|
-
stateStyles.borderColor =
|
|
226
|
+
stateStyles.backgroundColor = `var(${bgFocusedToken})`;
|
|
227
|
+
stateStyles.borderColor = `var(${bgFocusedToken})`;
|
|
211
228
|
}
|
|
212
229
|
else if (variant === "outline") {
|
|
213
|
-
stateStyles.borderColor =
|
|
230
|
+
stateStyles.borderColor = `var(${borderToken})`;
|
|
214
231
|
}
|
|
215
|
-
stateStyles.outline =
|
|
232
|
+
stateStyles.outline = `2px solid var(${borderToken})`;
|
|
216
233
|
stateStyles.outlineOffset = "2px";
|
|
217
234
|
}
|
|
218
235
|
return { ...baseStyles, ...variantStyles, ...stateStyles, ...style };
|
|
219
|
-
}, [variant, sizeConfig, borderRadius, fillContainer, justifyContent, currentState, isDisabled, style]);
|
|
236
|
+
}, [variant, sizeConfig, borderRadius, fillContainer, justifyContent, currentState, isDisabled, isLoading, color, style]);
|
|
220
237
|
const showStartIcon = !loading && startIcon;
|
|
221
238
|
const showEndIcon = !loading && endIcon;
|
|
222
|
-
|
|
239
|
+
const handleClick = useCallback((e) => {
|
|
240
|
+
if (isDisabled || isLoading) {
|
|
241
|
+
e.preventDefault();
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
onClick?.(e);
|
|
245
|
+
}, [isDisabled, isLoading, onClick]);
|
|
246
|
+
return (_jsx("button", { ref: ref, type: type, className: className, style: buttonStyles, disabled: isDisabled, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, ...rest, children: loading ? (_jsx(LoaderIcon, { size: LOADER_ICON_SIZE_MAP[size], className: "ds-button-loading-spinner" })) : (_jsxs(_Fragment, { children: [showStartIcon && _jsx("span", { style: { display: "inline-flex", alignItems: "center" }, children: startIcon }), children, showEndIcon && _jsx("span", { style: { display: "inline-flex", alignItems: "center" }, children: endIcon })] })) }));
|
|
223
247
|
}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import { ComponentPropsWithRef } from "react";
|
|
1
|
+
import { ComponentPropsWithRef, ReactNode } from "react";
|
|
2
2
|
type MenuVariant = "desktop" | "tablet-open" | "tablet-closed" | "mobile-open" | "mobile-closed" | "close-menu";
|
|
3
|
-
interface MenuItem {
|
|
3
|
+
export interface MenuItem {
|
|
4
4
|
id: string;
|
|
5
5
|
label: string;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
selected?: boolean;
|
|
8
|
+
onClick?: (item: MenuItem) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface SwitchRenderProps {
|
|
11
|
+
checked: boolean;
|
|
12
|
+
onChange: (checked: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface ToggleButtonRenderProps {
|
|
15
|
+
isOpen: boolean;
|
|
16
|
+
onClick: () => void;
|
|
17
|
+
}
|
|
18
|
+
export interface MenuButtonRenderProps {
|
|
19
|
+
onClick: () => void;
|
|
6
20
|
}
|
|
7
21
|
export interface MenuProps extends ComponentPropsWithRef<"div"> {
|
|
8
22
|
variant?: MenuVariant;
|
|
@@ -13,7 +27,15 @@ export interface MenuProps extends ComponentPropsWithRef<"div"> {
|
|
|
13
27
|
headerSubtitle?: string;
|
|
14
28
|
showChevrons?: boolean;
|
|
15
29
|
avatarImageUrl?: string;
|
|
30
|
+
selectedItemId?: string;
|
|
31
|
+
onItemClick?: (item: MenuItem) => void;
|
|
32
|
+
renderSwitch?: (props: SwitchRenderProps) => ReactNode;
|
|
33
|
+
renderToggleButton?: (props: ToggleButtonRenderProps) => ReactNode;
|
|
34
|
+
renderButton?: (props: MenuButtonRenderProps) => ReactNode;
|
|
35
|
+
onSwitchChange?: (checked: boolean) => void;
|
|
36
|
+
onToggleButtonClick?: () => void;
|
|
37
|
+
onButtonClick?: () => void;
|
|
16
38
|
}
|
|
17
|
-
export declare function Menu({ variant, showMenu, showButton, menuItems, headerTitle, headerSubtitle, showChevrons, avatarImageUrl, className, style, ref, ...rest }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export declare function Menu({ variant, showMenu, showButton, menuItems, headerTitle, headerSubtitle, showChevrons, avatarImageUrl, selectedItemId, onItemClick, renderSwitch, renderToggleButton, renderButton, onSwitchChange, onToggleButtonClick, onButtonClick, className, style, ref, ...rest }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
18
40
|
export {};
|
|
19
41
|
//# sourceMappingURL=Menu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../src/components/Menu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAW,qBAAqB,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../src/components/Menu.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAW,qBAAqB,EAAoC,SAAS,EAAE,MAAM,OAAO,CAAC;AAMpG,KAAK,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,GAAG,YAAY,CAAC;AAEhH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,SAAU,SAAQ,qBAAqB,CAAC,KAAK,CAAC;IAC7D,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,SAAS,CAAC;IACvD,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,SAAS,CAAC;IACnE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,SAAS,CAAC;IAC3D,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAUD,wBAAgB,IAAI,CAAC,EACnB,OAAmB,EACnB,QAAe,EACf,UAAiB,EACjB,SAA8B,EAC9B,WAAqB,EACrB,cAA2B,EAC3B,YAAmB,EACnB,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,SAAS,2CAieX"}
|
package/dist/components/Menu.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo } from "react";
|
|
4
|
-
import {
|
|
3
|
+
import { useMemo, useState, useCallback, useEffect } from "react";
|
|
4
|
+
import { CloseIcon, MenuIcon, DownloadIcon } from "../icons";
|
|
5
5
|
import { Switch } from "./Switch";
|
|
6
6
|
import { useThemeSafe } from "../providers/ThemeProvider";
|
|
7
|
+
import { MenuItem as MenuItemComponent } from "./MenuItem";
|
|
7
8
|
const DEFAULT_MENU_ITEMS = [
|
|
8
9
|
{ id: "1", label: "Menu Item #1" },
|
|
9
10
|
{ id: "2", label: "Menu Item #2" },
|
|
@@ -11,9 +12,31 @@ const DEFAULT_MENU_ITEMS = [
|
|
|
11
12
|
{ id: "4", label: "Menu Item #4" },
|
|
12
13
|
{ id: "5", label: "Menu Item #5" },
|
|
13
14
|
];
|
|
14
|
-
export function Menu({ variant = "desktop", showMenu = true, showButton = true, menuItems = DEFAULT_MENU_ITEMS, headerTitle = "Title", headerSubtitle = "Subtitle", showChevrons = true, avatarImageUrl, className, style, ref, ...rest }) {
|
|
15
|
+
export function Menu({ variant = "desktop", showMenu = true, showButton = true, menuItems = DEFAULT_MENU_ITEMS, headerTitle = "Title", headerSubtitle = "Subtitle", showChevrons = true, avatarImageUrl, selectedItemId, onItemClick, renderSwitch, renderToggleButton, renderButton, onSwitchChange, onToggleButtonClick, onButtonClick, className, style, ref, ...rest }) {
|
|
15
16
|
const themeContext = useThemeSafe();
|
|
16
17
|
const theme = themeContext?.theme ?? "dark";
|
|
18
|
+
const [hoveredItemId, setHoveredItemId] = useState(null);
|
|
19
|
+
const [switchChecked, setSwitchChecked] = useState(theme === "dark");
|
|
20
|
+
// Update switch checked state when theme changes
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
setSwitchChecked(theme === "dark");
|
|
23
|
+
}, [theme]);
|
|
24
|
+
const handleSwitchChange = useCallback((checked) => {
|
|
25
|
+
setSwitchChecked(checked);
|
|
26
|
+
if (onSwitchChange) {
|
|
27
|
+
onSwitchChange(checked);
|
|
28
|
+
}
|
|
29
|
+
}, [onSwitchChange]);
|
|
30
|
+
const handleToggleButtonClick = useCallback(() => {
|
|
31
|
+
if (onToggleButtonClick) {
|
|
32
|
+
onToggleButtonClick();
|
|
33
|
+
}
|
|
34
|
+
}, [onToggleButtonClick]);
|
|
35
|
+
const handleButtonClick = useCallback(() => {
|
|
36
|
+
if (onButtonClick) {
|
|
37
|
+
onButtonClick();
|
|
38
|
+
}
|
|
39
|
+
}, [onButtonClick]);
|
|
17
40
|
const containerStyles = useMemo(() => {
|
|
18
41
|
const baseStyles = {
|
|
19
42
|
display: "flex",
|
|
@@ -111,17 +134,6 @@ export function Menu({ variant = "desktop", showMenu = true, showButton = true,
|
|
|
111
134
|
overflow: "hidden",
|
|
112
135
|
};
|
|
113
136
|
}, []);
|
|
114
|
-
const menuItemStyles = useMemo(() => {
|
|
115
|
-
return {
|
|
116
|
-
display: "flex",
|
|
117
|
-
gap: "var(--spacing-200)",
|
|
118
|
-
alignItems: "center",
|
|
119
|
-
padding: "var(--spacing-200) var(--spacing-200)",
|
|
120
|
-
borderRadius: "var(--corner-radius-200)",
|
|
121
|
-
backgroundColor: "var(--bg-page-primary)",
|
|
122
|
-
width: "100%",
|
|
123
|
-
};
|
|
124
|
-
}, []);
|
|
125
137
|
const buttonStyles = useMemo(() => {
|
|
126
138
|
return {
|
|
127
139
|
display: "flex",
|
|
@@ -187,7 +199,7 @@ export function Menu({ variant = "desktop", showMenu = true, showButton = true,
|
|
|
187
199
|
};
|
|
188
200
|
}, []);
|
|
189
201
|
if (variant === "close-menu") {
|
|
190
|
-
return (_jsx("div", { ref: ref, className: className, style: { ...containerStyles, ...style }, ...rest, children: _jsx("button", { style: iconButtonStyles, children: _jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "32px", height: "32px" }, children: _jsx(CloseIcon, { size: 32 }) }) }) }));
|
|
202
|
+
return (_jsx("div", { ref: ref, className: className, style: { ...containerStyles, ...style }, ...rest, children: renderToggleButton ? (renderToggleButton({ isOpen: true, onClick: handleToggleButtonClick })) : (_jsx("button", { style: iconButtonStyles, onClick: handleToggleButtonClick, children: _jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "32px", height: "32px" }, children: _jsx(CloseIcon, { size: 32 }) }) })) }));
|
|
191
203
|
}
|
|
192
204
|
const isDesktop = variant === "desktop";
|
|
193
205
|
const isTabletOpen = variant === "tablet-open";
|
|
@@ -196,12 +208,27 @@ export function Menu({ variant = "desktop", showMenu = true, showButton = true,
|
|
|
196
208
|
const isMobileClosed = variant === "mobile-closed";
|
|
197
209
|
const showMenuItems = (isDesktop || isTabletOpen || isMobileOpen) && showMenu;
|
|
198
210
|
const showHeaderContent = isDesktop || isTabletOpen || isTabletClosed;
|
|
199
|
-
return (_jsxs("div", { ref: ref, className: className, style: { ...containerStyles, ...style }, ...rest, children: [isDesktop ? (_jsx(_Fragment, { children: _jsxs("div", { style: headerStyles, children: [_jsx("div", { style: avatarStyles, children:
|
|
211
|
+
return (_jsxs("div", { ref: ref, className: className, style: { ...containerStyles, ...style }, ...rest, children: [isDesktop ? (_jsx(_Fragment, { children: _jsxs("div", { style: headerStyles, children: [_jsx("div", { style: avatarStyles, children: _jsx("img", { src: avatarImageUrl || "/images/avatars/avatar-female.png", alt: "User avatar", style: {
|
|
200
212
|
width: "100%",
|
|
201
213
|
height: "100%",
|
|
202
214
|
objectFit: "cover",
|
|
203
215
|
objectPosition: "center",
|
|
204
|
-
}
|
|
216
|
+
}, onError: (e) => {
|
|
217
|
+
// Fallback to icon if image fails to load
|
|
218
|
+
const target = e.target;
|
|
219
|
+
target.style.display = "none";
|
|
220
|
+
const iconContainer = target.parentElement;
|
|
221
|
+
if (iconContainer && !iconContainer.querySelector("svg")) {
|
|
222
|
+
const iconWrapper = document.createElement("div");
|
|
223
|
+
iconWrapper.style.display = "flex";
|
|
224
|
+
iconWrapper.style.alignItems = "center";
|
|
225
|
+
iconWrapper.style.justifyContent = "center";
|
|
226
|
+
iconWrapper.style.width = "100%";
|
|
227
|
+
iconWrapper.style.height = "100%";
|
|
228
|
+
iconWrapper.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 12C14.21 12 16 10.21 16 8C16 5.79 14.21 4 12 4C9.79 4 8 5.79 8 8C8 10.21 9.79 12 12 12ZM12 14C9.33 14 4 15.34 4 18V20H20V18C20 15.34 14.67 14 12 14Z" fill="var(--fg-neutral)"/></svg>`;
|
|
229
|
+
iconContainer.appendChild(iconWrapper);
|
|
230
|
+
}
|
|
231
|
+
} }) }), showHeaderContent && (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "var(--spacing-none)", flex: 1 }, children: [_jsx("p", { style: {
|
|
205
232
|
fontFamily: "var(--font-secondary)",
|
|
206
233
|
fontSize: "var(--body-small-text-size)",
|
|
207
234
|
lineHeight: "var(--body-small-line-height)",
|
|
@@ -217,12 +244,27 @@ export function Menu({ variant = "desktop", showMenu = true, showButton = true,
|
|
|
217
244
|
margin: 0,
|
|
218
245
|
}, children: headerSubtitle })] }))] }) })) : (
|
|
219
246
|
/* Tablet/Mobile: Header and Footer in single row */
|
|
220
|
-
_jsxs("div", { style: mainRowStyles, children: [_jsxs("div", { style: headerStyles, children: [_jsx("div", { style: avatarStyles, children:
|
|
247
|
+
_jsxs("div", { style: mainRowStyles, children: [_jsxs("div", { style: headerStyles, children: [_jsx("div", { style: avatarStyles, children: _jsx("img", { src: avatarImageUrl || "/images/avatars/avatar-female.png", alt: "User avatar", style: {
|
|
221
248
|
width: "100%",
|
|
222
249
|
height: "100%",
|
|
223
250
|
objectFit: "cover",
|
|
224
251
|
objectPosition: "center",
|
|
225
|
-
}
|
|
252
|
+
}, onError: (e) => {
|
|
253
|
+
// Fallback to icon if image fails to load
|
|
254
|
+
const target = e.target;
|
|
255
|
+
target.style.display = "none";
|
|
256
|
+
const iconContainer = target.parentElement;
|
|
257
|
+
if (iconContainer && !iconContainer.querySelector("svg")) {
|
|
258
|
+
const iconWrapper = document.createElement("div");
|
|
259
|
+
iconWrapper.style.display = "flex";
|
|
260
|
+
iconWrapper.style.alignItems = "center";
|
|
261
|
+
iconWrapper.style.justifyContent = "center";
|
|
262
|
+
iconWrapper.style.width = "100%";
|
|
263
|
+
iconWrapper.style.height = "100%";
|
|
264
|
+
iconWrapper.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 12C14.21 12 16 10.21 16 8C16 5.79 14.21 4 12 4C9.79 4 8 5.79 8 8C8 10.21 9.79 12 12 12ZM12 14C9.33 14 4 15.34 4 18V20H20V18C20 15.34 14.67 14 12 14Z" fill="var(--fg-neutral)"/></svg>`;
|
|
265
|
+
iconContainer.appendChild(iconWrapper);
|
|
266
|
+
}
|
|
267
|
+
} }) }), showHeaderContent && (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "var(--spacing-none)", flex: 1 }, children: [_jsx("p", { style: {
|
|
226
268
|
fontFamily: "var(--font-secondary)",
|
|
227
269
|
fontSize: "var(--body-small-text-size)",
|
|
228
270
|
lineHeight: "var(--body-small-line-height)",
|
|
@@ -236,20 +278,35 @@ export function Menu({ variant = "desktop", showMenu = true, showButton = true,
|
|
|
236
278
|
fontWeight: "var(--font-weight-secondary-medium)",
|
|
237
279
|
color: "var(--fg-neutral)",
|
|
238
280
|
margin: 0,
|
|
239
|
-
}, children: headerSubtitle })] }))] }), _jsxs("div", { style: footerStyles, children: [showButton && (_jsxs("div", { style: buttonStyles, children: [_jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "16px", height: "16px" }, children: _jsx(DownloadIcon, { size: 16 }) }), _jsx("span", { children: "Button" })] }))
|
|
281
|
+
}, children: headerSubtitle })] }))] }), _jsxs("div", { style: footerStyles, children: [showButton && (renderButton ? (renderButton({ onClick: handleButtonClick })) : (_jsxs("div", { style: buttonStyles, onClick: handleButtonClick, children: [_jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "16px", height: "16px" }, children: _jsx(DownloadIcon, { size: 16 }) }), _jsx("span", { children: "Button" })] }))), renderSwitch ? (renderSwitch({ checked: switchChecked, onChange: handleSwitchChange })) : (_jsx(Switch, { checked: switchChecked, onChange: handleSwitchChange, showIcons: true })), renderToggleButton ? (renderToggleButton({
|
|
282
|
+
isOpen: isTabletOpen || isMobileOpen,
|
|
283
|
+
onClick: handleToggleButtonClick
|
|
284
|
+
})) : (_jsx("button", { style: iconButtonStyles, onClick: handleToggleButtonClick, children: _jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "32px", height: "32px" }, children: [(isTabletOpen || isMobileOpen) && _jsx(CloseIcon, { size: 32 }), (isTabletClosed || isMobileClosed) && _jsx(MenuIcon, { size: 32 })] }) }))] })] })), showMenuItems && (_jsx("div", { style: {
|
|
240
285
|
display: "flex",
|
|
241
286
|
flexDirection: "column",
|
|
242
287
|
gap: "var(--spacing-200)",
|
|
243
288
|
padding: isDesktop ? "var(--spacing-600) 0" : "var(--spacing-400) var(--spacing-200)",
|
|
244
289
|
width: "100%",
|
|
245
290
|
flex: isDesktop ? 1 : undefined,
|
|
246
|
-
}, children: menuItems.map((item) =>
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
291
|
+
}, children: menuItems.map((item) => {
|
|
292
|
+
const isSelected = selectedItemId === item.id || item.selected === true;
|
|
293
|
+
const isHovered = hoveredItemId === item.id;
|
|
294
|
+
const handleClick = () => {
|
|
295
|
+
if (item.onClick) {
|
|
296
|
+
item.onClick(item);
|
|
297
|
+
}
|
|
298
|
+
if (onItemClick) {
|
|
299
|
+
onItemClick(item);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
const handleMouseEnter = () => {
|
|
303
|
+
setHoveredItemId(item.id);
|
|
304
|
+
};
|
|
305
|
+
const handleMouseLeave = () => {
|
|
306
|
+
setHoveredItemId(null);
|
|
307
|
+
};
|
|
308
|
+
// Determine state for MenuItem component
|
|
309
|
+
const itemState = isSelected ? "Active" : isHovered ? "Hovered" : "Default";
|
|
310
|
+
return (_jsx(MenuItemComponent, { menuTitle: item.label, iconStart: true, iconStart1: item.icon || null, iconEnd: showChevrons, iconEnd1: null, state: itemState, onClick: handleClick, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }, item.id));
|
|
311
|
+
}) })), isDesktop && (_jsxs(_Fragment, { children: [showButton && (_jsx("div", { style: { display: "flex", flexDirection: "column", gap: "var(--spacing-400)", padding: "var(--spacing-400)", width: "100%" }, children: renderButton ? (renderButton({ onClick: handleButtonClick })) : (_jsxs("div", { style: buttonStyles, onClick: handleButtonClick, children: [_jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", width: "16px", height: "16px" }, children: _jsx(DownloadIcon, { size: 16 }) }), _jsx("span", { children: "Button" })] })) })), _jsx("div", { style: footerStyles, children: renderSwitch ? (renderSwitch({ checked: switchChecked, onChange: handleSwitchChange })) : (_jsx(Switch, { checked: switchChecked, onChange: handleSwitchChange, showIcons: true })) })] }))] }));
|
|
255
312
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ComponentPropsWithRef, ReactNode } from "react";
|
|
2
|
+
export type MenuItemState = "Default" | "Hovered" | "Active" | "Disabled";
|
|
3
|
+
export interface MenuItemProps extends Omit<ComponentPropsWithRef<"button">, "onClick"> {
|
|
4
|
+
menuTitle?: string;
|
|
5
|
+
iconStart?: boolean;
|
|
6
|
+
iconStart1?: ReactNode | null;
|
|
7
|
+
iconEnd?: boolean;
|
|
8
|
+
iconEnd1?: ReactNode | null;
|
|
9
|
+
state?: MenuItemState;
|
|
10
|
+
onClick?: () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function MenuItem({ menuTitle, iconStart, iconStart1, iconEnd, iconEnd1, state, onClick, className, style, ...rest }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=MenuItem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MenuItem.d.ts","sourceRoot":"","sources":["../../src/components/MenuItem.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGzD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,QAAQ,CAAC,EACvB,SAAuB,EACvB,SAAgB,EAChB,UAAiB,EACjB,OAAc,EACd,QAAe,EACf,KAAiB,EACjB,OAAO,EACP,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,aAAa,2CAiIf"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { UserPersonIcon, ChevronRightIcon } from "../icons";
|
|
4
|
+
export function MenuItem({ menuTitle = "Menu Item", iconStart = true, iconStart1 = null, iconEnd = true, iconEnd1 = null, state = "Default", onClick, className, style, ...rest }) {
|
|
5
|
+
const isActive = state === "Active";
|
|
6
|
+
const isDisabled = state === "Disabled";
|
|
7
|
+
const isHovered = state === "Hovered";
|
|
8
|
+
const isDefault = state === "Default";
|
|
9
|
+
// Background colors based on state
|
|
10
|
+
const backgroundColor = isActive
|
|
11
|
+
? "var(--bg-primary-tonal)"
|
|
12
|
+
: isHovered
|
|
13
|
+
? "var(--bg-page-secondary)"
|
|
14
|
+
: isDisabled
|
|
15
|
+
? "var(--bg-page-primary)"
|
|
16
|
+
: "var(--bg-page-primary)";
|
|
17
|
+
// Text colors based on state
|
|
18
|
+
const textColor = isActive
|
|
19
|
+
? "var(--fg-primary-on-tonal)"
|
|
20
|
+
: isDisabled
|
|
21
|
+
? "var(--fg-on-disabled)"
|
|
22
|
+
: isHovered
|
|
23
|
+
? "var(--fg-neutral)"
|
|
24
|
+
: "var(--fg-neutral-secondary)";
|
|
25
|
+
// Icon colors based on state
|
|
26
|
+
const iconColor = isActive
|
|
27
|
+
? "var(--fg-primary-on-tonal)"
|
|
28
|
+
: isDisabled
|
|
29
|
+
? "var(--fg-on-disabled)"
|
|
30
|
+
: isHovered
|
|
31
|
+
? "var(--fg-neutral)"
|
|
32
|
+
: "var(--fg-neutral-secondary)";
|
|
33
|
+
// Chevron colors based on state
|
|
34
|
+
const chevronColor = isActive
|
|
35
|
+
? "var(--fg-primary-on-tonal)"
|
|
36
|
+
: isDisabled
|
|
37
|
+
? "var(--fg-on-disabled)"
|
|
38
|
+
: "var(--fg-neutral)";
|
|
39
|
+
// Border for disabled state
|
|
40
|
+
const borderStyle = isDisabled
|
|
41
|
+
? "var(--border-width-25) solid var(--border-neutral-tertiary)"
|
|
42
|
+
: "none";
|
|
43
|
+
const containerStyles = {
|
|
44
|
+
display: "flex",
|
|
45
|
+
gap: "var(--spacing-200)",
|
|
46
|
+
alignItems: "center",
|
|
47
|
+
padding: "var(--spacing-200) var(--spacing-200)",
|
|
48
|
+
borderRadius: "var(--corner-radius-200)",
|
|
49
|
+
width: "100%",
|
|
50
|
+
backgroundColor,
|
|
51
|
+
border: borderStyle,
|
|
52
|
+
cursor: isDisabled ? "not-allowed" : onClick ? "pointer" : "default",
|
|
53
|
+
transition: "background-color 0.2s ease, border-color 0.2s ease",
|
|
54
|
+
...style,
|
|
55
|
+
};
|
|
56
|
+
return (_jsxs("button", { type: "button", className: className, style: containerStyles, onClick: isDisabled ? undefined : onClick, disabled: isDisabled, ...rest, children: [iconStart && (_jsx("div", { style: {
|
|
57
|
+
display: "flex",
|
|
58
|
+
alignItems: "center",
|
|
59
|
+
justifyContent: "center",
|
|
60
|
+
width: "20px",
|
|
61
|
+
height: "20px",
|
|
62
|
+
flexShrink: 0,
|
|
63
|
+
color: iconColor,
|
|
64
|
+
}, children: iconStart1 || _jsx(UserPersonIcon, { size: 20 }) })), _jsx("p", { style: {
|
|
65
|
+
fontFamily: "var(--font-secondary)",
|
|
66
|
+
fontSize: "var(--body-small-text-size)",
|
|
67
|
+
lineHeight: "var(--body-small-line-height)",
|
|
68
|
+
fontWeight: isActive ? "var(--font-weight-secondary-semibold)" : "var(--font-weight-secondary-medium)",
|
|
69
|
+
color: textColor,
|
|
70
|
+
margin: 0,
|
|
71
|
+
flex: 1,
|
|
72
|
+
textAlign: "left",
|
|
73
|
+
}, children: menuTitle }), iconEnd && !isDisabled && (_jsx("div", { style: {
|
|
74
|
+
display: "flex",
|
|
75
|
+
alignItems: "center",
|
|
76
|
+
justifyContent: "center",
|
|
77
|
+
width: "16px",
|
|
78
|
+
height: "16px",
|
|
79
|
+
flexShrink: 0,
|
|
80
|
+
color: chevronColor,
|
|
81
|
+
}, children: iconEnd1 || _jsx(ChevronRightIcon, { size: 16 }) })), iconEnd && isDisabled && (_jsx("div", { style: {
|
|
82
|
+
display: "flex",
|
|
83
|
+
alignItems: "center",
|
|
84
|
+
justifyContent: "center",
|
|
85
|
+
width: "16px",
|
|
86
|
+
height: "16px",
|
|
87
|
+
flexShrink: 0,
|
|
88
|
+
color: chevronColor,
|
|
89
|
+
}, children: iconEnd1 || _jsx(ChevronRightIcon, { size: 16 }) }))] }));
|
|
90
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,10 @@ export { Switch } from "./components/Switch";
|
|
|
5
5
|
export { Input } from "./components/Input";
|
|
6
6
|
export { Avatar } from "./components/Avatar";
|
|
7
7
|
export { Chip } from "./components/Chip";
|
|
8
|
-
export { Menu } from "./components/Menu";
|
|
8
|
+
export { Menu, type MenuItem as MenuItemData } from "./components/Menu";
|
|
9
|
+
export { MenuItem, type MenuItemProps, type MenuItemState } from "./components/MenuItem";
|
|
9
10
|
export { RadioButton } from "./components/RadioButton";
|
|
10
|
-
export type { ButtonProps, ButtonVariant, ButtonSize, CornerRadiusStep, JustifyContent, ButtonState } from "./components/Button";
|
|
11
|
+
export type { ButtonProps, ButtonVariant, ButtonSize, CornerRadiusStep, JustifyContent, ButtonState, ButtonColor } from "./components/Button";
|
|
11
12
|
export type { CardProps, CardType, ProductCardSize, ProductCardStatus, ExperienceCardType, GenericCardStatus } from "./components/Card";
|
|
12
13
|
export type { CheckboxProps, CheckboxStatus } from "./components/Checkbox";
|
|
13
14
|
export type { SwitchProps, SwitchStatus } from "./components/Switch";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC9I,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxI,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC3E,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC3G,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGlF,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,eAAe,EACf,eAAe,EACf,WAAW,GACZ,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { Input } from "./components/Input";
|
|
|
7
7
|
export { Avatar } from "./components/Avatar";
|
|
8
8
|
export { Chip } from "./components/Chip";
|
|
9
9
|
export { Menu } from "./components/Menu";
|
|
10
|
+
export { MenuItem } from "./components/MenuItem";
|
|
10
11
|
export { RadioButton } from "./components/RadioButton";
|
|
11
12
|
// Providers
|
|
12
13
|
export { ThemeProvider, useTheme, useThemeSafe } from "./providers/ThemeProvider";
|