Toggle.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright 2021-2024 Avaiga Private Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  5. * the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  10. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. * specific language governing permissions and limitations under the License.
  12. */
  13. import React, { CSSProperties, MouseEvent, SyntheticEvent, useCallback, useEffect, useState } from "react";
  14. import Box from "@mui/material/Box";
  15. import Switch from "@mui/material/Switch";
  16. import Typography from "@mui/material/Typography";
  17. import ToggleButton from "@mui/material/ToggleButton";
  18. import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
  19. import Tooltip from "@mui/material/Tooltip";
  20. import { createSendUpdateAction } from "../../context/taipyReducers";
  21. import ThemeToggle from "./ThemeToggle";
  22. import { LovProps, useLovListMemo } from "./lovUtils";
  23. import { useClassNames, useDispatch, useDynamicProperty, useModule } from "../../utils/hooks";
  24. import { emptyStyle, getSuffixedClassNames, getUpdateVar } from "./utils";
  25. import { Icon, IconAvatar } from "../../utils/icon";
  26. import { FormControlLabel } from "@mui/material";
  27. const groupSx = { verticalAlign: "middle" };
  28. interface ToggleProps extends LovProps<string> {
  29. style?: CSSProperties;
  30. label?: string;
  31. unselectedValue?: string;
  32. allowUnselect?: boolean;
  33. mode?: string;
  34. isSwitch? : boolean;
  35. }
  36. const Toggle = (props: ToggleProps) => {
  37. const {
  38. id,
  39. style = emptyStyle,
  40. label,
  41. updateVarName = "",
  42. propagate = true,
  43. lov,
  44. defaultLov = "",
  45. unselectedValue = "",
  46. updateVars = "",
  47. valueById,
  48. mode = "",
  49. isSwitch = false,
  50. } = props;
  51. const dispatch = useDispatch();
  52. const [value, setValue] = useState(props.defaultValue);
  53. const [bVal, setBVal] = useState(() =>
  54. typeof props.defaultValue === "boolean"
  55. ? props.defaultValue
  56. : typeof props.value === "boolean"
  57. ? props.value
  58. : false
  59. );
  60. const module = useModule();
  61. const className = useClassNames(props.libClassName, props.dynamicClassName, props.className);
  62. const active = useDynamicProperty(props.active, props.defaultActive, true);
  63. const hover = useDynamicProperty(props.hoverText, props.defaultHoverText, undefined);
  64. const lovList = useLovListMemo(lov, defaultLov);
  65. const changeValue = useCallback(
  66. (evt: MouseEvent, val: string) => {
  67. if (!props.allowUnselect && val === null) {
  68. return;
  69. }
  70. dispatch(
  71. createSendUpdateAction(
  72. updateVarName,
  73. val === null ? unselectedValue : val,
  74. module,
  75. props.onChange,
  76. propagate,
  77. valueById ? undefined : getUpdateVar(updateVars, "lov")
  78. )
  79. );
  80. },
  81. [
  82. unselectedValue,
  83. updateVarName,
  84. propagate,
  85. dispatch,
  86. updateVars,
  87. valueById,
  88. props.onChange,
  89. props.allowUnselect,
  90. module,
  91. ]
  92. );
  93. const changeSwitchValue = useCallback(
  94. (evt: SyntheticEvent, checked: boolean) =>
  95. dispatch(createSendUpdateAction(updateVarName, checked, module, props.onChange, propagate)),
  96. [updateVarName, dispatch, props.onChange, propagate, module]
  97. );
  98. useEffect(() => {
  99. typeof props.value === "boolean" ? setBVal(props.value) : props.value !== undefined && setValue(props.value);
  100. }, [props.value]);
  101. return mode.toLowerCase() === "theme" ? (
  102. <ThemeToggle {...props} />
  103. ) : (
  104. <Box id={id} sx={style} className={className}>
  105. {label && !isSwitch ? <Typography>{label}</Typography> : null}
  106. <Tooltip title={hover || ""}>
  107. {isSwitch ? (
  108. <FormControlLabel
  109. control={<Switch />}
  110. checked={bVal}
  111. onChange={changeSwitchValue}
  112. disabled={!active}
  113. label={label}
  114. className={getSuffixedClassNames(className, "-switch")}
  115. />
  116. ) : (
  117. <ToggleButtonGroup value={value} exclusive onChange={changeValue} disabled={!active} sx={groupSx}>
  118. {lovList &&
  119. lovList.map((v) => (
  120. <ToggleButton value={v.id} key={v.id}>
  121. {typeof v.item === "string" ? (
  122. <Typography>{v.item}</Typography>
  123. ) : (
  124. <IconAvatar id={v.id} img={v.item as Icon} />
  125. )}
  126. </ToggleButton>
  127. ))}
  128. </ToggleButtonGroup>
  129. )}
  130. </Tooltip>
  131. </Box>
  132. );
  133. };
  134. export default Toggle;