123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- /*
- * Copyright 2021-2024 Avaiga Private Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- import React, { CSSProperties, useMemo, MouseEvent } from "react";
- import Avatar from "@mui/material/Avatar";
- import CardHeader from "@mui/material/CardHeader";
- import ListItemButton from "@mui/material/ListItemButton";
- import ListItemText from "@mui/material/ListItemText";
- import ListItemAvatar from "@mui/material/ListItemAvatar";
- import Tooltip from "@mui/material/Tooltip";
- import { TypographyProps } from "@mui/material";
- import { SxProps } from "@mui/system";
- import { TaipyActiveProps, TaipyChangeProps, TaipyLabelProps } from "./utils";
- import { getInitials } from "../../utils";
- import { LovItem } from "../../utils/lov";
- import { stringIcon, Icon, IconAvatar, avatarSx } from "../../utils/icon";
- export interface SelTreeProps extends LovProps, TaipyLabelProps {
- filter?: boolean;
- multiple?: boolean;
- width?: string | number;
- dropdown?: boolean;
- mode?: string;
- }
- export interface LovProps<T = string | string[], U = string> extends TaipyActiveProps, TaipyChangeProps {
- defaultLov?: string;
- lov?: LoV;
- value?: T;
- defaultValue?: U;
- height?: string | number;
- valueById?: boolean;
- }
- /**
- * A LoV (list of value) element.
- *
- * Each `LoVElt` holds:
- *
- * - Its identifier as a string;
- * - Its label (or icon) as a `stringIcon`;
- * - Potential child elements as an array of `LoVElt`s.
- */
- export type LoVElt = [string, stringIcon, LoVElt[]?];
- /**
- * A series of LoV elements.
- */
- export type LoV = LoVElt[];
- const getLovItem = (elt: LoVElt | string, tree = false): LovItem => {
- const it: LovItem = Array.isArray(elt)
- ? {
- id: elt[0],
- item: elt[1] || elt[0],
- }
- : { id: "" + elt, item: "" + elt };
- if (tree) {
- it.children = Array.isArray(elt) && elt.length > 2 ? elt[2]?.map((e) => getLovItem(e, true)) : [];
- }
- return it;
- };
- export const paperBaseSx = { width: "100%", mb: 2, display: "grid", gridTemplateRows: "auto 1fr" } as CSSProperties;
- /**
- * A React hook that returns a LoV list from the LoV default value and the LoV bound value.
- * @param lov - The bound lov value.
- * @param defaultLov - The JSON-stringified default LoV value.
- * @param tree - This flag indicates if the LoV list is a tree or a flat list (default is false).
- * @returns A list of LoV items.
- */
- export const useLovListMemo = (lov: LoV | undefined, defaultLov: string, tree = false): LovItem[] =>
- useMemo(() => {
- if (lov) {
- if (!Array.isArray(lov)) {
- console.debug("lov wrong format ", lov);
- return [];
- }
- return lov.map((elt) => getLovItem(elt, tree));
- } else if (defaultLov) {
- let parsedLov;
- try {
- parsedLov = JSON.parse(defaultLov);
- } catch {
- parsedLov = [];
- }
- return parsedLov.map((elt: LoVElt) => getLovItem(elt, tree));
- }
- return [];
- }, [lov, defaultLov, tree]);
- const cardSx = { p: 0 } as CSSProperties;
- export const LovImage = ({
- item,
- disableTypo,
- height,
- titleTypographyProps,
- }: {
- item: Icon;
- disableTypo?: boolean;
- height?: string;
- titleTypographyProps?: TypographyProps<"span", { component?: "span" }>;
- }) => {
- const sx = useMemo(
- () => (height ? { height: height, "& .MuiAvatar-img": { objectFit: "contain" } } : undefined) as SxProps,
- [height]
- );
- return (
- <CardHeader
- sx={cardSx}
- avatar={<IconAvatar img={item} sx={sx} />}
- title={item.text}
- disableTypography={disableTypo}
- titleTypographyProps={titleTypographyProps}
- />
- );
- };
- export const showItem = (elt: LovItem, searchValue: string) => {
- return (
- !searchValue ||
- ((typeof elt.item === "string" ? (elt.item as string) : (elt.item as Icon).text) || elt.id)
- .toLowerCase()
- .indexOf(searchValue.toLowerCase()) > -1
- );
- };
- export interface ItemProps {
- value: string;
- clickHandler: (evt: MouseEvent<HTMLElement>) => void;
- selectedValue: string[] | string;
- item: stringIcon;
- disabled: boolean;
- withAvatar?: boolean;
- titleTypographyProps?: TypographyProps<"span", { component?: "span" }>;
- }
- export const SingleItem = ({
- value,
- clickHandler,
- selectedValue,
- item,
- disabled,
- withAvatar = false,
- titleTypographyProps,
- }: ItemProps) => (
- <ListItemButton
- onClick={clickHandler}
- data-id={value}
- selected={Array.isArray(selectedValue) ? selectedValue.indexOf(value) !== -1 : selectedValue === value}
- disabled={disabled}
- >
- {typeof item === "string" ? (
- withAvatar ? (
- <ListItemAvatar>
- <CardHeader
- sx={cardSx}
- avatar={
- <Tooltip title={item}>
- <Avatar sx={avatarSx}>{getInitials(item)}</Avatar>
- </Tooltip>
- }
- title={item}
- titleTypographyProps={titleTypographyProps}
- />
- </ListItemAvatar>
- ) : (
- <ListItemText primary={item} />
- )
- ) : (
- <ListItemAvatar>
- <LovImage item={item} titleTypographyProps={titleTypographyProps} />
- </ListItemAvatar>
- )}
- </ListItemButton>
- );
- export const isLovParent = (lov: LovItem[] | undefined, id: string, childId: string, path: string[] = []): boolean => {
- if (!lov) {
- return false;
- }
- for (let i = 0; i < lov.length; i++) {
- if (lov[i].id === id && !(lov[i].children || []).length) {
- return false;
- } else if (lov[i].id === childId) {
- return path.includes(id);
- } else if (isLovParent(lov[i].children, id, childId, [...path, lov[i].id])) {
- return true;
- }
- }
- return false;
- };
|