Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 4 additions & 27 deletions components/InfoButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,10 @@ import BaseModal from "../../../src/components/Common/Modal";
import { InformationCircleIcon } from "@heroicons/react/20/solid";
import useOnClickOutside from "@/submodules/react-components/hooks/useHooks/useOnClickOutside";
import { Transition } from "@headlessui/react";
import { INFO_BUTTON_DEFAULT_VALUES, InfoButtonConfig, InfoButtonProps } from "../types/infoButton";

type InfoButtonProps = {
content: string | JSX.Element;
infoButtonSize?: "xs" | "sm" | "md" | "lg";
infoButtonColorClass?: string;
access?: "hover" | "click";
display?: "absoluteDiv" | "modal"
divPosition?: "top" | "bottom" | "left" | "right"; // only for absoluteDiv relevant
divZIndexClass?: string;
}

type InfoConfig = {
size: number;
cursorClass: string;
positionClass: string;
hideInfo: () => void;
showInfo: () => void;
}

function generateAndCheckConfig(props: InfoButtonProps, setOpen: Dispatch<SetStateAction<boolean>>): InfoConfig {
function generateAndCheckConfig(props: InfoButtonProps, setOpen: Dispatch<SetStateAction<boolean>>): InfoButtonConfig {
if (props.access == "hover" && props.display == "modal") console.warn("InfoButton - Hover access and modal display are not recommended")
const config: any = {};
switch (props.infoButtonSize) {
Expand Down Expand Up @@ -53,17 +37,10 @@ function generateAndCheckConfig(props: InfoButtonProps, setOpen: Dispatch<SetSta
return config;
}

const DEFAULT_VALUES = {
size: "sm",
access: "hover",
display: "absoluteDiv",
divPosition: "top",
divZIndexClass: "z-10"
}

export function InfoButton(_props: InfoButtonProps) {
const [props] = useDefaults<InfoButtonProps>(_props, DEFAULT_VALUES);
const [config, setConfig] = useState<InfoConfig>(null);
const [props] = useDefaults<InfoButtonProps>(_props, INFO_BUTTON_DEFAULT_VALUES);
const [config, setConfig] = useState<InfoButtonConfig>(null);
const [open, setOpen] = useState(false);

useEffect(() => setConfig(generateAndCheckConfig(props, setOpen)), [props.infoButtonSize, props.access, props.display, props.divPosition]);
Expand Down
18 changes: 3 additions & 15 deletions components/LocalStorageDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,8 @@ import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useSta
import { useDefaults, useDefaultsByRef } from "../hooks/useDefaults";
import Dropdown from "./Dropdown";
import { CompareOptions, inStringList } from "@/submodules/javascript-functions/validations";
import { LOCAL_STORAGE_DROPDOWN_DEFAULTS, LocalStorageDropdownProps } from "../types/localStorageDropdown";

type LocalStorageDropdownProps = {
buttonName: string;
storageKey: string;
storageGroupKey?: string; //defaults to localDropdown
onOptionSelected?: (option: string) => void;
searchDefaultValue?: string;
excludedFromStorage?: { values: string[]; compareOptions?: CompareOptions[] }; // if the value is in this list it will not be added to the storage //setting this to null will assume all values are valid
}

const DEFAULTS = {
storageGroupKey: "localDropdown",
excludedFromStorage: { values: ["select", "enter"], compareOptions: [CompareOptions.IGNORE_CASE, CompareOptions.TRIM, CompareOptions.STARTS_WITH] }
}

function readFromLocalStorage(group: string, key: string): string[] {
const itemGroupString = localStorage.getItem(group);
Expand Down Expand Up @@ -68,8 +56,8 @@ function removeFromLocalStorage(group: string, key: string, rValue: string): str
export const LocalStorageDropdown = forwardRef((_props: LocalStorageDropdownProps, ref) => {


const [props] = useDefaults<LocalStorageDropdownProps>(_props, DEFAULTS);
const [propRef] = useDefaultsByRef<LocalStorageDropdownProps>(_props, DEFAULTS); // for unmounting
const [props] = useDefaults<LocalStorageDropdownProps>(_props, LOCAL_STORAGE_DROPDOWN_DEFAULTS);
const [propRef] = useDefaultsByRef<LocalStorageDropdownProps>(_props, LOCAL_STORAGE_DROPDOWN_DEFAULTS); // for unmounting
const [options, setOptions] = useState<string[]>(); // initially built with useLocalStorage however as state setters don't work during unmount changed to a common state
const [inputText, setInputText] = useState(props.buttonName ?? ''); // holds the current option independent of input field or dropdown so it can be collected if necessary
const inputTextRef = useRef<string>(); //ref is used to access data from a pointer which in turn can be access in the unmounting
Expand Down
19 changes: 19 additions & 0 deletions components/NoTableEntriesYet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { memo } from "react";
import { useDefaults } from "../hooks/useDefaults";
import { NO_TABLE_ENTRIES_YET_DEFAULTS, NoTableEntriesYetProps } from "../types/noTableEntriesYet";


function GetNoTableEntriesYet(_props: NoTableEntriesYetProps) {
const [props] = useDefaults<NoTableEntriesYetProps>(_props, NO_TABLE_ENTRIES_YET_DEFAULTS);

return <tr>
<td colSpan={props.tableColumns}>
<div className={`flex justify-center items-center w-full text-sm ${props.heightClass + " " + props.backgroundColorClass + " " + props.textColorClass + " " + props.marginBottomClass}`}>
{props.text}
</div>
</td>
</tr>

}

export const NoTableEntriesYet = memo(GetNoTableEntriesYet)
46 changes: 46 additions & 0 deletions types/infoButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Options for the InfoButton component
* @content {string | JSX.Element} - The content of the info button
* @infoButtonSize {"xs" | "sm" | "md" | "lg", optional} - The size of the info icon used as button
* @infoButtonColorClass {string, optional} - The color of the info icon used as button
* @access {"hover" | "click", optional} - How to access the info content
* @display {"absoluteDiv" | "modal"} - The display of the info button
* @divPosition {"top" | "bottom" | "left" | "right", optional} - The position of the info div - only used if display is absoluteDiv
* @divZIndexClass {string, optional} - The z-index of the info div - only used if display is absoluteDiv
*/

export type InfoButtonProps = {
content: string | JSX.Element;
infoButtonSize?: "xs" | "sm" | "md" | "lg";
infoButtonColorClass?: string;
access?: "hover" | "click";
display?: "absoluteDiv" | "modal"
divPosition?: "top" | "bottom" | "left" | "right";
divZIndexClass?: string;
}

/**
* Return type of the InfoButton helper function
* @size {number} - The size of the info icon used as button
* @cursorClass {string} - The cursor of the info icon used as button
* @positionClass {string} - The position of the info div - only used if display is absoluteDiv
* @hideInfo {function} - The function that will be called when the info div should be hidden
* @showInfo {function} - The function that will be called when the info div should be shown
*/

export type InfoButtonConfig = {
size: number;
cursorClass: string;
positionClass: string;
hideInfo: () => void;
showInfo: () => void;
}


export const INFO_BUTTON_DEFAULT_VALUES = {
size: "sm",
access: "hover",
display: "absoluteDiv",
divPosition: "top",
divZIndexClass: "z-10"
}
29 changes: 29 additions & 0 deletions types/localStorageDropdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

import { CompareOptions } from "@/submodules/javascript-functions/validations";

/**
* Options for the LocalStorage Dropdown component
* Note that a ref object can be linked to the component
* @buttonName {string} - The name of the button
* @storageKey {string} - The key inside the storage group
* @storageGroupKey {string, optional} - The key of the local storage value (defaults to localDropdown)
* @onOptionSelected {function, optional} - The function that will be called when an option is selected
* @searchDefaultValue {string, optional} - The default value of the search bar (similar to buttonName)
* @excludedFromStorage {object, optional} - Decided what values are exempt from being added to the storage - defaults to "starting with 'select' or 'enter'"
*/

export type LocalStorageDropdownProps = {
buttonName: string;
storageKey: string;
storageGroupKey?: string; //defaults to localDropdown
onOptionSelected?: (option: string) => void;
searchDefaultValue?: string;
excludedFromStorage?: { values: string[]; compareOptions?: CompareOptions[] }; // if the value is in this list it will not be added to the storage //setting this to null will assume all values are valid
}



export const LOCAL_STORAGE_DROPDOWN_DEFAULTS = {
storageGroupKey: "localDropdown",
excludedFromStorage: { values: ["select", "enter"], compareOptions: [CompareOptions.IGNORE_CASE, CompareOptions.TRIM, CompareOptions.STARTS_WITH] }
}
28 changes: 28 additions & 0 deletions types/noTableEntriesYet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

/**
* Options for the No table entries yet component
* @tableColumns {number} - The number of columns in the table (so the text can be across the whole table)
* @text {string, optional} - The text to be displayed
* @heightClass {string, optional} - The height of the component
* @backgroundColorClass {string, optional} - The background color of the component
* @textColorClass {string, optional} - The text color of the component
* @marginBottomClass {string, optional} - The margin bottom of the component
*/

export type NoTableEntriesYetProps = {
tableColumns: number;
text?: string;
heightClass?: string;
backgroundColorClass?: string;
textColorClass?: string;
marginBottomClass?: string; // can be used to offset common table paddings, usually negative
}


export const NO_TABLE_ENTRIES_YET_DEFAULTS = {
text: 'No data yet',
heightClass: 'h-16',
backgroundColorClass: 'bg-gray-50',
textColorClass: 'text-gray-700',
marginBottomClass: "",
}