material-you-react
Version:
Material You: Material You (M3) Design system and its components for simple integration with Next.Js or other react-based frameworks
1,027 lines (1,011 loc) • 106 kB
JavaScript
'use strict';
var React = require('react');
/**
* @params backgroundColor: string - sets Background color
* @params items: string[] - An array of icon names to display. Example: `['home', 'search']`.
* @params floatingActionButton: Displays the FAB when `true`. Example: `true`. |
* @returns React.ReactNode-
* @description
* This component is a BottomAppBar component.
*/
function BottomAppBar({ innerRef, ...props }) {
var _a;
const [isHovered, setIsHovered] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);
return (React.createElement("div", { ref: innerRef, id: "bottomAppBar", className: "bottom-app-bar", style: {
backgroundColor: `${(_a = props.backgroundColor) !== null && _a !== void 0 ? _a : "rgb(var(--md-sys-color-surface-container))"}`,
width: "100vw",
height: "80px",
padding: props.floatingActionButton ? "16px" : "12px 16px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
position: "fixed",
bottom: 0,
left: 0,
} },
React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "16px",
} }, props.items.map((element, index) => (React.createElement("span", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onMouseDown: () => setIsActive(true), onMouseUp: () => setIsActive(false), key: index, className: `md-elevation
${!isHovered ? "md-elevation-0" : "md-elevation-1"}
label-large material-symbols-rounded material-symbols-outlined`, style: {
width: "24px",
height: "24px",
cursor: "pointer",
color: `${isActive
? "rgb(var(--md-sys-color-on-tertiary-container))"
: "rgb(var(--md-sys-color-on-secondary-container))"}`,
} }, element || "add")))),
props.floatingActionButton));
}
function TopAppBarCenterAligned(props) {
var _a;
const [isScrolled, setScrollState] = React.useState(false);
window.onscroll = function () {
if (window.scrollY > 0) {
setScrollState(true);
}
else {
setScrollState(false);
}
};
return (React.createElement("div", { className: `md-elevation $isScrolled ? "md-elevation-2" : "md-elevation-0"}`, style: {
zIndex: 1,
backgroundColor: `${(_a = props.containerBackgroundColor) !== null && _a !== void 0 ? _a : (isScrolled
? "rgb(var(--md-sys-color-surface-container))"
: "rgb(var(--md-sys-color-surface))")}`,
position: "sticky",
width: "100vw",
height: "64px",
borderRadius: "0px",
padding: "0px 16px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
gap: "24px",
top: "0",
left: "0",
color: "rgb(var(--md-sys-color-on-surface))",
} },
React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "48px",
height: "48px",
cursor: "pointer",
} }, props.leadingIcon && (React.createElement("div", { style: {
width: "24px",
height: "24px",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.leadingIcon || "arrow_back")))),
React.createElement("p", { className: "title-large", style: {
width: "fit-content",
color: "rgb(var(--md-sys-color-on-surface))",
} }, props.headline),
props.avatar || props.avatarImage ? (React.createElement("div", { key: "avatar", style: {
width: "48px",
fontSize: "30px",
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "48px",
cursor: "pointer",
color: "rgb(var(--md-sys-color-on-surface-variant))",
} }, props.avatarImage ? (React.createElement("img", { src: props.avatarImage, style: {
width: "30px",
height: "30px",
objectFit: "cover",
borderRadius: "15px",
} })) : (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "30px",
} }, "account_circle")))) : (React.createElement("div", { style: {
width: "48px",
fontSize: "30px",
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "48px",
cursor: "pointer",
color: "rgb(var(--md-sys-color-on-surface-variant))",
} }))));
}
function TopAppBarCenterSmall(props) {
var _a;
const [isScrolled, setScrollState] = React.useState(false);
window.onscroll = function () {
if (window.scrollY > 0) {
setScrollState(true);
}
else {
setScrollState(false);
}
};
return (React.createElement("div", { className: `${isScrolled ? "md-elevation-2" : "md-elevation-0"} md-elevation`, style: {
zIndex: 1,
backgroundColor: `${(_a = props.containerBackgroundColor) !== null && _a !== void 0 ? _a : (isScrolled
? "rgb(var(--md-sys-color-surface-container))"
: "rgb(var(--md-sys-color-surface))")}`,
position: "sticky",
width: "100vw",
height: "64px",
borderRadius: "0px",
padding: "0px 16px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
gap: "24px",
top: "0",
left: "0",
color: "rgb(var(--md-sys-color-on-surface))",
} },
React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "16px",
} },
props.leadingIcon && (React.createElement("div", { style: {
width: "24px",
height: "24px",
cursor: "pointer",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.leadingIcon || "arrow_back"))),
React.createElement("p", { className: "title-large", style: {
color: "rgb(var(--md-sys-color-on-surface))",
} }, props.headline)),
(props.trailingIcons || props.avatar || props.avatarImage) && (React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "24px",
} },
props.trailingIcons &&
props.trailingIcons.map((icon, index) => (React.createElement("div", { key: index, style: {
width: "24px",
height: "24px",
cursor: "pointer",
color: "rgb(var(--md-sys-color-on-surface-variant))",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, icon)))),
(props.avatar || props.avatarImage) && (React.createElement("div", { key: "avatar", style: {
width: "48px",
fontSize: "30px",
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "48px",
cursor: "pointer",
color: "rgb(var(--md-sys-color-on-surface-variant))",
} }, props.avatarImage ? (React.createElement("img", { src: props.avatarImage, style: {
width: "30px",
height: "30px",
objectFit: "cover",
borderRadius: "15px",
} })) : (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "30px",
} }, "account_circle"))))))));
}
function TopAppBarCenterMedium(props) {
var _a;
const [isScrolled, setScrollState] = React.useState(false);
const [scrollY, setScrollY] = React.useState(0);
window.onscroll = function () {
if (window.scrollY > 0) {
setScrollY(window.scrollY);
setScrollState(true);
}
else {
setScrollY(0);
setScrollState(false);
}
};
return (React.createElement("div", { className: "md-elevation-0 md-elevation", style: {
zIndex: 1,
backgroundColor: `${((_a = props.containerBackgroundColor) !== null && _a !== void 0 ? _a : isScrolled)
? "rgb(var(--md-sys-color-surface-container))"
: "rgb(var(--md-sys-color-surface))"}`,
width: "100vw",
height: isScrolled ? `${112 - Math.min(96, scrollY) / 2}px` : "112px",
borderRadius: "0px",
padding: isScrolled ? "0px 16px" : "20px 16px 24px 24px",
display: "flex",
justifyContent: "space-between",
alignItems: isScrolled ? "center" : "start",
gap: "24px",
position: "sticky",
top: "0",
left: "0",
transition: "all 0.3s ease",
} },
React.createElement("div", { style: {
transition: "all 0.3s ease",
display: "flex",
flexDirection: isScrolled ? "row" : "column",
justifyContent: isScrolled ? "space-between" : "start",
alignItems: "start",
gap: "16px",
width: isScrolled ? `100%` : "auto",
} },
React.createElement("div", { style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-surface))",
cursor: "pointer",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.leadingIcon || "arrow_back")),
React.createElement("p", { className: isScrolled ? "title-large" : "headline-small", style: {
width: isScrolled ? "100%" : "auto",
transition: "all 0.3s ease",
textAlign: isScrolled ? "center" : "start",
color: "rgb(var(--md-sys-color-on-surface))",
} }, props.headline)),
props.trailingIcons && (React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "24px",
} }, props.trailingIcons.map((icon, index) => (React.createElement("div", { key: index, style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-surface-variant))",
cursor: "pointer",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, icon))))))));
}
function TopAppBarCenterLarge(props) {
var _a;
const [isScrolled, setScrollState] = React.useState(false);
const [scrollY, setScrollY] = React.useState(0);
window.onscroll = function () {
if (window.scrollY > 0) {
setScrollState(true);
setScrollY(window.scrollY);
}
else {
setScrollState(false);
setScrollY(0);
}
};
return (React.createElement("div", { style: {
zIndex: 1,
backgroundColor: `${((_a = props.containerBackgroundColor) !== null && _a !== void 0 ? _a : isScrolled)
? "rgb(var(--md-sys-color-surface-container))"
: "rgb(var(--md-sys-color-surface))"}`,
width: "100vw",
height: isScrolled ? `${152 - Math.min(64, scrollY) / 2}px` : "152px",
borderRadius: "0px",
padding: isScrolled ? "16px" : "20px 16px 28px",
display: "flex",
justifyContent: "space-between",
alignItems: "start",
gap: "24px",
position: "sticky",
top: "0",
left: "0",
} },
React.createElement("div", { style: {
height: "100%",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
alignItems: "start",
gap: "16px",
} },
React.createElement("div", { style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-surface))",
cursor: "pointer",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.leadingIcon || "arrow_back")),
React.createElement("p", { className: "headline-medium", style: {
whiteSpace: "pre-line",
color: "rgb(var(--md-sys-color-on-surface))",
} }, props.headline)),
props.trailingIcons && (React.createElement("div", { style: {
display: "flex",
justifyContent: "center",
alignItems: "center",
gap: "24px",
} }, props.trailingIcons.map((icon, index) => (React.createElement("div", { key: index, style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-surface-variant))",
cursor: "pointer",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, icon))))))));
}
const ElevatedButton = (props) => {
const [isHovered, setIsHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);
const [isFocusedWithKeyboard, setIsFocusedWithKeyboard] = React.useState(true);
const [isActive, setIsActive] = React.useState(false);
const handleClick = () => {
const params = {};
props.onClickCallback(params);
};
return (React.createElement("button", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onFocus: () => setIsFocused(true), onBlur: () => {
setIsFocused(false);
setIsFocusedWithKeyboard(true);
}, onMouseDown: () => {
setIsActive(true);
setIsFocusedWithKeyboard(false);
}, onTouchStart: () => setIsFocusedWithKeyboard(false), onMouseUp: () => setIsActive(false), onClick: handleClick, className: ` md-elevation ${props.disabled
? "md-elevation-0"
: isActive || isFocused || !isHovered
? "md-elevation-1"
: "md-elevation-2"} label-large`, style: {
width: props.width || "fit-content",
outlineOffset: isFocused && isFocusedWithKeyboard ? "2px" : undefined,
outline: isFocused && isFocusedWithKeyboard
? "3px solid rgb(var(--md-sys-color-secondary))"
: "",
cursor: props.disabled ? "not-allowed" : "pointer",
display: "flex",
height: "40px",
backgroundColor: props.disabled
? "rgba(var(--md-sys-color-on-surface), 12%)"
: isFocused || isActive
? `color-mix(in srgb, ${props.containerColor ||
"rgb(var(--md-sys-color-surface-container-low))"},rgb(var(--md-sys-color-primary)) 10%)`
: isHovered
? `color-mix(in srgb, ${props.containerColor ||
"rgb(var(--md-sys-color-surface-container-low))"},rgb(var(--md-sys-color-primary)) 8%)`
: `${props.containerColor ||
"rgb(var(--md-sys-color-surface-container-low))"}`,
borderRadius: "20px",
padding: props.icon != null ? "0px 24px 0px 16px" : "0px 24px",
alignItems: "center",
justifyContent: "center",
color: props.disabled
? "rgba(var(--md-sys-color-on-surface), 38%)"
: props.contentColor || "rgb(var(--md-sys-color-primary))",
} },
props.icon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "18px !important",
marginRight: "8px",
} }, props.icon)),
props.children));
};
const FilledButton = (props) => {
var _a;
const [isHovered, setIsHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);
const [isFocusedWithKeyboard, setIsFocusedWithKeyboard] = React.useState(true);
const [isDragged, setIsDragged] = React.useState(false);
const handleClick = () => {
const params = {};
props.onClickCallback(params);
};
return (React.createElement("button", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onFocus: () => setIsFocused(true), onBlur: () => {
setIsFocused(false);
setIsFocusedWithKeyboard(true);
}, onMouseDown: () => {
setIsActive(true);
setIsFocusedWithKeyboard(false);
}, onTouchStart: () => setIsFocusedWithKeyboard(false), onMouseUp: () => setIsActive(false), onDragStart: () => setIsDragged(true), onDragEnd: () => setIsDragged(false), draggable: (_a = props.draggable) !== null && _a !== void 0 ? _a : true, onClick: handleClick, className: ` md-elevation
${isDragged
? "md-elevation-3"
: !isHovered
? "md-elevation-0"
: "md-elevation-1"}
label-large`, style: {
width: props.width || "fit-content",
outlineOffset: isFocusedWithKeyboard ? "2px" : undefined,
outline: isFocused && !isDragged && isFocusedWithKeyboard
? "3px solid rgb(var(--md-sys-color-secondary))"
: "",
cursor: props.disabled ? "not-allowed" : "pointer",
display: "flex",
height: "40px",
backgroundColor: props.disabled
? "rgba(var(--md-sys-color-on-surface), 12%)"
: isDragged
? `color-mix(in srgb, ${props.containerColor || "rgb(var(--md-sys-color-primary))"},rgb(var(--md-sys-color-on-primary)) 16%)`
: isFocused || isActive
? `color-mix(in srgb, ${props.containerColor || "rgb(var(--md-sys-color-primary))"},rgb(var(--md-sys-color-on-primary)) 10%)`
: isHovered
? `color-mix(in srgb, ${props.containerColor || "rgb(var(--md-sys-color-primary))"},rgb(var(--md-sys-color-on-primary)) 8%)`
: `${props.containerColor || "rgb(var(--md-sys-color-primary))"}`,
borderRadius: "20px",
padding: props.icon != null ? "0px 24px 0px 16px" : "0px 24px",
alignItems: "center",
justifyContent: "center",
color: props.disabled
? "rgba(var(--md-sys-color-on-surface), 38%)"
: props.contentColor || "rgb(var(--md-sys-color-on-primary))",
} },
props.icon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "18px !important",
marginRight: "8px",
} }, props.icon)),
props.children));
};
const FilledTonalButton = (props) => {
return (React.createElement(FilledButton, { onClickCallback: props.onClickCallback, children: props.children, icon: props.icon, disabled: props.disabled, containerColor: "rgb(var(--md-sys-color-secondary-container))", contentColor: "rgb(var(--md-sys-color-on-secondary-container))", width: props.width, draggable: false }));
};
const OutlinedButton = (props) => {
const [isHovered, setIsHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);
const [isFocusedWithKeyboard, setIsFocusedWithKeyboard] = React.useState(true);
const handleClick = () => {
const params = {};
props.onClickCallback(params);
};
return (React.createElement("button", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onFocus: () => setIsFocused(true), onBlur: () => {
setIsFocused(false);
setIsFocusedWithKeyboard(true);
}, onMouseDown: () => {
setIsActive(true);
setIsFocusedWithKeyboard(false);
}, onTouchStart: () => setIsFocusedWithKeyboard(false), onMouseUp: () => setIsActive(false), onClick: handleClick, className: `md-elevation-0
label-large`, style: {
width: props.width || "fit-content",
outlineOffset: isFocused && isFocusedWithKeyboard ? "2px" : undefined,
outline: isFocused && isFocusedWithKeyboard
? "3px solid rgb(var(--md-sys-color-secondary))"
: "",
border: props.disabled
? "rgba(var(--md-sys-color-on-surface), 12%)"
: isFocused
? "1px solid rgb(var(--md-sys-color-primary))"
: "1px solid rgb(var(--md-sys-color-outline))",
cursor: props.disabled ? "not-allowed" : "pointer",
display: "flex",
height: "40px",
backgroundColor: props.disabled
? "transparent"
: //
isFocused || isActive
? `rgba(var(--md-sys-color-primary), 10%)`
: isHovered
? `rgba(var(--md-sys-color-primary), 8%)`
: "transparent",
// : `${props.containerColor || "rgb(var(--md-sys-color-primary))"}`,
borderRadius: "20px",
padding: props.icon != null ? "0px 24px 0px 16px" : "0px 24px",
alignItems: "center",
justifyContent: "center",
color: props.disabled
? "rgba(var(--md-sys-color-on-surface), 38%)"
: props.contentColor || "rgb(var(--md-sys-color-primary))",
} },
props.icon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "18px !important",
marginRight: "8px",
} }, props.icon)),
props.children));
};
const TextButton = (props) => {
const [isHovered, setIsHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);
const [isActive, setIsActive] = React.useState(false);
const [isFocusedWithKeyboard, setIsFocusedWithKeyboard] = React.useState(true);
const handleClick = () => {
const params = {};
props.onClickCallback(params);
};
return (React.createElement("button", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onFocus: () => setIsFocused(true), onBlur: () => {
setIsFocused(false);
setIsFocusedWithKeyboard(true);
}, onMouseDown: () => {
setIsActive(true);
setIsFocusedWithKeyboard(false);
}, onTouchStart: () => setIsFocusedWithKeyboard(false), onMouseUp: () => setIsActive(false), className: `md-elevation-0
label-large`, onClick: handleClick, style: {
width: props.width || "fit-content",
outlineOffset: isFocused && isFocusedWithKeyboard ? "2px" : undefined,
outline: isFocused && isFocusedWithKeyboard
? "3px solid rgb(var(--md-sys-color-secondary))"
: "",
cursor: props.disabled ? "not-allowed" : "pointer",
display: "flex",
height: "40px",
backgroundColor: props.disabled
? "transparent"
: //
isFocused || isActive
? `rgba(var(--md-sys-color-primary), 10%)`
: isHovered
? `rgba(var(--md-sys-color-primary), 8%)`
: "transparent",
// : `${props.containerColor || "rgb(var(--md-sys-color-primary))"}`,
borderRadius: "20px",
padding: props.icon != null ? "0px 16px 0px 12px" : "0px 12px",
alignItems: "center",
justifyContent: "center",
color: props.disabled
? "rgba(var(--md-sys-color-on-surface), 38%)"
: props.contentColor || "rgb(var(--md-sys-color-primary))",
} },
props.icon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "18px !important",
marginRight: "8px",
} }, props.icon)),
props.children));
};
const FloatingActionButton = (props) => {
const ref = React.useRef(null);
const [parentClass, setParentClass] = React.useState("");
React.useEffect(() => {
var _a;
const domNode = ref.current;
if (domNode !== undefined && domNode !== null && domNode.parentNode) {
setParentClass(((_a = domNode.parentElement) === null || _a === void 0 ? void 0 : _a.className) || "ID");
}
}, [ref.current]);
const handleClick = () => {
const params = {};
props.onClickCallback(params);
};
return (React.createElement("button", { onClick: handleClick, ref: ref, className: parentClass.includes("bottom-app-bar")
? "md-elevation-0"
: "md-elevation-3", style: {
backgroundColor: "rgb(var(--md-sys-color-primary-container))",
width: "56px",
height: "56px",
borderRadius: "16px",
display: "flex",
justifyContent: "center",
alignItems: "center",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-primary-container))",
} }, "add")));
};
/**
* Props for the Menu component.
* @params {React.ReactNode} `children` - The content to be rendered inside the menu. Accepts `MenuItem` as a childrens.
* @params {number} `displayLimit` - Optional. Specifies the maximum number of items to display before enabling scroll.
* If not provided, the menu will expand to fit all content without scrolling.
*/
function Menu(props) {
const [allowedHeight, setAllowedHeight] = React.useState('fit-content');
const [shouldScroll, setShouldScroll] = React.useState(false);
React.useEffect(() => {
if (props.displayLimit) {
const calculatedHeight = props.displayLimit * 48;
setAllowedHeight(`${calculatedHeight}px`);
setShouldScroll(true);
}
}, [props.displayLimit]);
return (React.createElement("div", { style: {
width: '200px',
// minWidth: '112px',
// maxWidth: '280px',
backgroundColor: 'rgb(var(--md-sys-color-surface-container))',
height: allowedHeight,
borderRadius: '4px',
display: 'flex',
justifyContent: 'start',
alignItems: 'center',
flexDirection: 'column',
...(shouldScroll && { overflowY: 'scroll' })
}, className: "md-elevation-2" }, props.children));
}
/**
* Props for MenuItem Component
* @param (string) [optional] `leadingIcon` - Icon displayed at start of item
* @param (string) [optional] `trailingIcon` - Icon displayed at end of item
* @param (string) [optional] `trailingText` - Text displayed at end of item
* @param (string) [required] `label` - Primary text content of menu item
* @param (boolean) [optional] `disable` - Whether item is disabled
* @param (React.ReactNode) [optional] `children` - Inner content to render
* @param (function) [optional] `onClickCallback` - Callback fired on item click, accepts generic param
*/
const MenuItem = (props) => {
const [isHovered, setIsHovered] = React.useState(false);
const [isFocused, setIsFocused] = React.useState(false);
const [isPressed, setIsPressed] = React.useState(false);
const menuItemRef = React.useRef(null);
// Defines where to position the child Menus of Menu-Item.
const [childPosition, setChildPosition] = React.useState("Right");
const [subChildren, setSubChildren] = React.useState(null);
const [showChild, setShowChild] = React.useState(false);
React.useEffect(() => {
if (menuItemRef.current) {
const rect = menuItemRef.current.getBoundingClientRect();
const menuLeftPosition = rect.left;
const menuRightPosition = rect.right;
setChildPosition(`${menuLeftPosition > menuRightPosition ? "Left" : "Right"}`);
}
// Restricting to only display whose Children.type = `Menu`
const childrenArray = React.Children.toArray(props.children);
childrenArray.forEach((child) => {
if (React.isValidElement(child)) {
setSubChildren(child);
}
});
}, []);
const handleClick = () => {
const params = {};
if (props.onClickCallback) {
props.onClickCallback(params);
}
};
return (React.createElement("div", { ref: menuItemRef, onMouseEnter: () => {
setIsHovered(true);
setShowChild(true);
}, onMouseLeave: () => {
setIsHovered(false);
setShowChild(false);
}, onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), onMouseDown: () => setIsPressed(true), onMouseUp: () => setIsPressed(false), onClick: handleClick, style: {
width: "100%",
padding: "8px 12px",
height: "48px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
backgroundColor: isFocused
? "rgb(var(--md-sys-color-secondary))"
: isHovered
? "rgba(var(--md-sys-color-on-surface), 8%)"
: isFocused || isPressed
? "rgba(var(--md-sys-color-on-surface), 1%)"
: "rgb(var(--md-sys-color-surface-container))",
cursor: props.disable ? "not-allowed" : "pointer",
pointerEvents: props.disable ? "none" : "auto",
position: "relative",
} },
React.createElement("div", { style: {
gap: "12px",
display: "flex",
justifyContent: "start",
alignItems: "center",
} },
props.leadingIcon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "24px",
color: props.disable
? "rgb(var(--md-sys-color-on-surface))"
: isHovered || isFocused || isPressed
? "rgb(var(--md-sys-color-on-surface-variant)"
: "rgb(var(--md-sys-color-on-surface-variant))",
opacity: props.disable ? "0.38" : "",
} }, props.leadingIcon || "")),
React.createElement("p", { style: {
font: "var(--md-sys-typescale-label-large-font)",
fontWeight: "var(--md-sys-typescale-label-large-weight)",
fontSize: "var(--md-sys-typescale-label-large-size)",
lineHeight: "var(--md-sys-typescale-label-large-line-height)",
letterSpacing: "var(--md-sys-typescale-label-large-tracking)",
color: props.disable || isHovered || isFocused || isPressed
? "rgb(var(--md-sys-color-on-surface))"
: "rgb(var(--md-sys-color-on-surface))",
opacity: props.disable ? "0.38" : "",
} }, props.label)),
React.createElement("div", { style: {
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
} },
props.trailingIcon && (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined", style: {
fontSize: "24px",
color: props.disable
? "rgb(var(--md-sys-color-on-surface))"
: isHovered || isFocused || isPressed
? "rgb(var(--md-sys-color-on-surface-variant)"
: "rgb(var(--md-sys-color-on-surface-variant))",
opacity: props.disable ? "0.38" : "",
} }, subChildren ? "arrow_drop_down" : props.trailingIcon || "")),
props.trailingText && (React.createElement("span", { style: {
font: "var(--md-sys-typescale-label-large-font)",
fontWeight: "var(--md-sys-typescale-label-large-weight)",
fontSize: "var(--md-sys-typescale-label-large-size)",
lineHeight: "var(--md-sys-typescale-label-large-line-height)",
letterSpacing: "var(--md-sys-typescale-label-large-tracking)",
color: "rgb(var(--md-sys-color-on-surface-variant))",
} }, props.trailingText || ""))),
showChild && (React.createElement("div", { style: {
position: "absolute",
top: 0,
right: childPosition === "Right" ? "100%" : "",
left: childPosition === "Left" ? "100%" : "",
} }, subChildren && subChildren))));
};
/**
* Props for OutlinedTextField Component
* @param (string) [required] `value` - Current value of the input field
* @param (function) [required] `onValueChange` - Handler function for value changes
* @param ("textarea" | "" | "dropdown") [optional] `type` - Type of input field
* @param (string[]) [optional] `options` - Available options for dropdown type
* @param (number) [optional] `rows` - Number of rows for textarea
* @param (string) [optional] `containerWidth` - Width of the input container
* @param (string) [optional] `leadingIcon` - Icon displayed at start of input
* @param (string) [required] `labelText` - Label text for the input field
* @param (string) [optional] `inputType` - HTML input type attribute
* @param (number) [optional] `maxLength` - Maximum allowed input length
* @param (boolean) [optional] `required` - Whether field is required
* @param (string) [optional] `supportingText` - Helper text below input
* @param (string) [optional] `trailingIcon` - Icon displayed at end of input
* @param (boolean) [optional] `disabled` - Whether field is disabled
* @param (boolean) [optional] `error` - Whether field is in error state
*/
function FilledTextField(props) {
var _a;
const [givenInputType, setGivenInputType] = React.useState("");
const [isFocused, setIsFocused] = React.useState(false);
const textareaRef = React.useRef(null);
const [menuPosition, setMenuPosition] = React.useState("Bottom");
const textFieldRef = React.useRef(null);
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
const menuRef = React.useRef(null);
const handleInputChange = (e) => {
props.onValueChange(e.target.value);
};
const handleMenuItemClick = (value) => {
props.onValueChange(value);
setIsMenuOpen(false);
};
const handleFocus = () => {
setIsFocused(true);
if (props.type === "dropdown") {
setIsMenuOpen(true);
}
};
const handleBlur = (e) => {
var _a;
if (props.type === "dropdown") {
const isClickInsideMenu = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.relatedTarget);
if (!isClickInsideMenu) {
setTimeout(() => {
setIsFocused(false);
}, 200);
}
}
else {
setIsFocused(false);
}
};
const handleTrailingIconClick = (e) => {
if (props.inputType === "password") {
setGivenInputType(givenInputType === "text" ? "password" : "text");
}
else {
props.onValueChange("");
}
};
React.useEffect(() => {
var _a;
if (props.type === "textarea" && textareaRef.current) {
const textarea = textareaRef.current;
textarea.style.height = "auto";
textarea.style.height = `${textarea.scrollHeight}px`;
}
if (givenInputType === "") {
setGivenInputType((_a = props.inputType) !== null && _a !== void 0 ? _a : "text");
}
if (props.type === "dropdown") {
if (textFieldRef.current) {
const rect = textFieldRef.current.getBoundingClientRect();
const menuTopPosition = rect.top;
const menuBottomPosition = rect.bottom;
setMenuPosition(`${menuTopPosition > menuBottomPosition ? "Top" : "Bottom"}`);
}
}
}, [props.value, props.type]);
return (React.createElement("div", { ref: textFieldRef, style: {
width: (_a = props.containerWidth) !== null && _a !== void 0 ? _a : "",
display: "flex",
flexDirection: "column",
justifyContent: "start",
alignItems: "center",
gap: "4px",
opacity: props.disabled ? 0.4 : 1,
pointerEvents: props.disabled ? "none" : "auto",
cursor: "pointer",
transition: "all 0.3s ease",
position: "relative",
} },
React.createElement("div", { className: `filled-text-field-inner-container ${isFocused ? "focused" : ""} ${props.error ? "error" : ""}`, style: {
width: "100%",
minHeight: "56px",
height: "auto",
padding: `${props.leadingIcon && props.trailingIcon
? "8px 12px"
: props.leadingIcon
? "8px 16px 8px 12px"
: "8px 16px"}`,
borderTopLeftRadius: "4px",
borderTopRightRadius: "4px",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
gap: `${props.leadingIcon || props.trailingIcon ? "16px" : "0px"}`,
}, onFocus: handleFocus, onBlur: handleBlur },
props.leadingIcon && (React.createElement("div", { className: `filled-text-field-leading-icon ${props.error && "error"}`, style: {
width: "24px",
height: "24px",
color: "rgb(var(--md-sys-color-on-surface-variant))",
cursor: "none",
} },
React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.leadingIcon || ""))),
React.createElement("div", { className: "filled-text-field-input-box", style: { position: "relative" } },
props.type === "textarea" ? (React.createElement("textarea", { ref: textareaRef, value: props.value, required: props.required, disabled: props.disabled, maxLength: props.maxLength, onChange: handleInputChange, placeholder: "", className: `filled-text-field-input ${props.error ? "error" : ""}`, style: {
color: "rgb(var(--md-sys-color-on-surface))",
font: "var(--md-sys-typescale-body-large-font)",
lineHeight: "var(--md-sys-typescale-body-large-line-height)",
fontSize: "var(--md-sys-typescale-body-large-size)",
fontWeight: "var(--md-sys-typescale-body-large-weight)",
letterSpacing: "var(--md-sys-typescale-body-large-tracking)",
caretColor: props.error
? "rgb(var(--md-sys-color-error))"
: "rgb(var(--md-sys-color-primary))",
resize: "none",
overflow: "hidden",
} })) : (React.createElement("input", { type: givenInputType, value: props.value, required: props.required, disabled: props.disabled, maxLength: props.maxLength, onChange: handleInputChange, onKeyDown: (e) => {
if (props.type === "dropdown") {
e.preventDefault();
}
}, placeholder: "", className: `filled-text-field-input ${props.error ? "error" : ""}`, style: {
color: "rgb(var(--md-sys-color-on-surface))",
font: "var(--md-sys-typescale-body-large-font)",
lineHeight: "var(--md-sys-typescale-body-large-line-height)",
fontSize: "var(--md-sys-typescale-body-large-size)",
fontWeight: "var(--md-sys-typescale-body-large-weight)",
letterSpacing: "var(--md-sys-typescale-body-large-tracking)",
caretColor: props.error
? "rgb(var(--md-sys-color-error))"
: "rgb(var(--md-sys-color-primary))",
} })),
React.createElement("label", { className: `filled-text-field-label ${props.error ? "error" : ""}` },
props.labelText,
props.required && "*")),
props.trailingIcon && props.value.length > 0 && (React.createElement("div", { onClick: (e) => handleTrailingIconClick(), className: `filled-text-field-trailing-icon ${props.error && "error"}`, style: {
width: "24px",
height: "24px",
cursor: "pointer",
userSelect: "none",
} },
" ",
props.inputType === "password" ? (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, givenInputType === "text" ? "visibility_off" : "visibility")) : (React.createElement("span", { className: "material-symbols-rounded material-symbols-outlined" }, props.trailingIcon || ""))))),
React.createElement("div", { style: {
width: "100%",
display: "flex",
justifyContent: "space-between",
alignItems: "start",
padding: "0px 16px",
gap: "16px",
color: `${props.error
? "rgb(var(--md-sys-color-error))"
: "rgb(var(--md-sys-color-on-surface-variant))"}`,
font: "var(--md-sys-typescale-body-small-font)",
fontWeight: "var(--md-sys-typescale-body-small-weight)",
fontSize: "var(--md-sys-typescale-body-small-size)",
lineHeight: "var(--md-sys-typescale-body-small-line-height)",
letterSpacing: "var(--md-sys-typescale-body-small-tracking)",
} },
React.createElement("p", null, props.supportingText),
props.maxLength && (React.createElement("p", null,
props.value.length,
"/",
props.maxLength))),
props.type === "dropdown" && props.options && isMenuOpen && (React.createElement("div", { ref: menuRef, style: {
position: "absolute",
top: menuPosition === "Top" ? 0 : "",
bottom: menuPosition === "Bottom" ? 0 : "",
left: 0,
} },
React.createElement(Menu, null, props.options.map((item, index) => (React.createElement(MenuItem, { key: index, label: item, onClickCallback: () => handleMenuItemClick(item) }))))))));
}
/**
* Props for OutlinedTextField Component
* @param (string) [required] `value` - Current value of the input field
* @param (function) [required] `onValueChange` - Handler function for value changes
* @param ("textarea" | "" | "dropdown") [optional] `type` - Type of input field
* @param (string[]) [optional] `options` - Available options for dropdown type
* @param (number) [optional] `rows` - Number of rows for textarea
* @param (string) [optional] `containerWidth` - Width of the input container
* @param (string) [optional] `leadingIcon` - Icon displayed at start of input
* @param (string) [required] `labelText` - Label text for the input field
* @param (string) [optional] `inputType` - HTML input type attribute
* @param (number) [optional] `maxLength` - Maximum allowed input length
* @param (boolean) [optional] `required` - Whether field is required
* @param (string) [optional] `supportingText` - Helper text below input
* @param (string) [optional] `trailingIcon` - Icon displayed at end of input
* @param (boolean) [optional] `disabled` - Whether field is disabled
* @param (boolean) [optional] `error` - Whether field is in error state
*/
function OutlinedTextField(props) {
var _a;
const [givenInputType, setGivenInputType] = React.useState("");
const [isFocused, setIsFocused] = React.useState(false);
const [parentBGColor, setParentBGColor] = React.useState("");
const textareaRef = React.useRef(null);
// const textFieldRef = useRef<HTMLDivElement | null>(null);
const [menuPosition, setMenuPosition] = React.useState("Bottom");
const textFieldRef = React.useRef(null);
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
const menuRef = React.useRef(null);
const handleInputChange = (e) => {
props.onValueChange(e.target.value);
};
const handleMenuItemClick = (value) => {
props.onValueChange(value);
setIsMenuOpen(false);
};
const handleFocus = () => {
setIsFocused(true);
if (props.type === "dropdown") {
setIsMenuOpen(true);
}
};
const handleBlur = (e) => {
var _a;
if (props.type === "dropdown") {
const isClickInsideMenu = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.relatedTarget);
if (!isClickInsideMenu) {
setTimeout(() => {
setIsFocused(false);
}, 200);
}
}
else {
setIsFocused(false);
}
};
// Recursively gets the background color of the parent, which uses this component.
const getParentBackgroundColor = (element) => {
if (!element)
return null;
const computedStyle = window.getComputedStyle(element);
const bgColor = computedStyle.backgroundColor;
if (bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)") {
return bgColor;
}
return getParentBackgroundColor(element.parentElement);
};
const handleTrailingIconClick = (e) => {
if (props.inputType === "password") {
setGivenInputType(givenInputType === "text" ? "password" : "text");
}
else {
props.onValueChange("");
}
};
React.useEffect(() => {
var _a;
if (props.type === "textarea" && textareaRef.current) {
const textarea = textareaRef.current;
textarea.style.height = "auto";
textarea.style.height = `${textarea.scrollHeight}px`;
}
if (givenInputType === "") {
setGivenInputType((_a = props.inputType) !== null && _a !== void 0 ? _a : "text");
}
if (props.type === "dropdown") {
if (textFieldRef.current) {
const rect = textFieldRef.current.getBoundingClientRect();
const menuTopPosition = rect.top;
const menuBottomPosition = rect.bottom;
setMenuPosition(`${menuTopPosition > menuBottomPosition ? "Top" : "Bottom"}`);
}
}
}, [props.value, props.type]);
React.useEffect(() => {
if (parentBGColor === "") {
if (textFieldRef.current) {
let parentBackgroundColor = getParentBackgroundColor(textFieldRef.current);
setParentBGColor(parentBackgroundColor);
}
}
}, []);
return (React.createElement("div", { ref: textFieldRef, style: {
width: (_a = props.containerWidth) !== null && _a !== void 0 ? _a : "",
display: "flex",
flexDirection: "column",
justifyContent: "start",
alignItems: "center",
gap: "4px",
opacity: props.disabled ? 0.4 : 1,
pointerEvents: props.disabled ? "none" : "auto",
cursor: "pointer",
transition: "all 0