@willphan1712000/frontend
v2.4.1
Published
Frontend Library
Readme
@willphan1712000/frontend
Reusable React UI components and frontend utilities packaged for application development following Will component interface called WUII which stands for Will UI Interface
What this package includes
Components
DropdownSelectMultiSelectRangeSliderOptionSliderColorPickerSliderDynamicListFileDropZoneInfoOverlaySpinnerButtonModernButtonAvatarInputGoogleTextAreaInputFileUploadImageImageImageEditor
Utilities
CanvasImageUtilitiesTransformtoolsLinearAlgebrauseThemeState
Auth helpers
useSessionSessionProvideruseAuthClientAuthInterfaceStorageInterface
Installation
This package is intended for React applications.
npm install @willphan1712000/frontendMake sure your app already has React and React DOM installed:
npm install react react-domWill UI Interface (WUII)
To ensure ultimate consistency, all interactive UI components in this package implement the WUII<T> interface. The generic type T represents the data type the component operates on.
The WUII<T> Interface
export default interface WUII<T = any> {
value?: T;
setValue?: (value?: T) => void;
options?: Options;
range?: Range;
label?: string;
isReadOnly?: boolean;
description?: string;
styling?: {
primaryColor?: string;
backgroundColor?: string;
textColor?: string;
hoverBackgroundColor?: string;
focusColor?: string;
borderColor?: string;
destructive?: string;
width?: string;
};
config?: {
default?: string;
accept?: string;
};
}Common Properties
value?: T- The current value of the component.setValue?: (value?: T) => void- Callback to update the value.isReadOnly?: boolean- If set totrue, disables user interactions and shows a"Locked - Read Only"tooltip instead of the description.description?: string- Custom tooltip text shown on hover of the info icon.styling?: object- Custom styling overrides (e.g., colors, width).config?: object- Component-specific behavior configuration (e.g.,acceptfile extensions ordefaultassets).
Core component usage
DropdownSelect
DropdownSelect is a custom dropdown selection input component that supports filtering options via an integrated search input, as well as read-only states and custom tooltip info guidance.
import { useState } from 'react';
import { DropdownSelect, type Options } from '@willphan1712000/frontend';
const options: Options = [
{ label: 'Apple', value: 'apple' },
{ label: 'Orange', value: 'orange' },
];
export default function Example() {
const [value, setValue] = useState('');
return (
<DropdownSelect
options={options}
value={value}
setValue={setValue}
isReadOnly={false}
description="Choose your preferred fruit"
styling={{
backgroundColor: '#ffffff',
textColor: '#000000',
hoverBackgroundColor: '#f0f0f0',
}}
/>
);
}Props:
options: { label: string; value: string }[]- List of select options.value: string- The currently selected value.setValue: (value?: string) => void- Callback function triggered when a new value is selected.isReadOnly?: boolean- If set totrue, disables opening the dropdown list and shows a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional custom styling configurations:backgroundColor?: string- Background color of the select box and list elements (defaults to'#fff').textColor?: string- Color of the text inside the input box and dropdown options (defaults to'#000').hoverBackgroundColor?: string- Background color of an option when hovered (defaults to'#f0f0f0').
MultiSelect
MultiSelect is a custom selection input component allowing users to choose multiple options from a search-enabled dropdown list, featuring tag-style selected values, hover help tooltips, and read-only support.
import { useState } from 'react';
import { MultiSelect } from '@willphan1712000/frontend';
const options = [
{ label: 'React', value: 'react' },
{ label: 'TypeScript', value: 'typescript' },
];
export default function Example() {
const [values, setValues] = useState<string[]>([]);
return (
<MultiSelect
options={options}
value={values}
setValue={setValues}
isReadOnly={false}
description="Select your tech stack"
styling={{
backgroundColor: '#ffffff',
textColor: '#000000',
hoverBackgroundColor: '#f0f0f0',
}}
/>
);
}Props:
options: { label: string; value: string }[]- List of select options.value: string[]- An array of currently selected values.setValue: (value?: string[]) => void- Callback to update selected values.isReadOnly?: boolean- If set totrue, disables opening the dropdown list, clearing all items, or removing individual options, and displays a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional custom styling configurations:backgroundColor?: string- Background color of the select box and list elements (defaults to'#fff').textColor?: string- Color of the text inside the input box and dropdown options (defaults to'#000').hoverBackgroundColor?: string- Background color of an option when hovered (defaults to'#f0f0f0').
RangeSlider
RangeSlider allows users to select a numeric value within a range by dragging a slider track, with custom tooltip info display and read-only support.
import { useState } from 'react';
import { RangeSlider } from '@willphan1712000/frontend';
export default function Example() {
const [value, setValue] = useState('50');
return (
<RangeSlider
value={value}
setValue={setValue}
range={{
min: '0',
max: '100',
}}
isReadOnly={false}
description="Select the volume percentage"
styling={{
primaryColor: '#2563eb',
width: '240',
backgroundColor: '#ffffff',
textColor: '#000000',
}}
/>
);
}Props:
value: string- The current value.setValue: (value?: string) => void- Callback function triggered when the slider value changes.range?: object- Object containing range boundaries:min?: string- Minimum value of the range (defaults to'0').max?: string- Maximum value of the range (defaults to'100').
isReadOnly?: boolean- If set totrue, disables dragging or changing the slider, and shows a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional custom styling configurations:primaryColor?: string- Custom track/thumb color (defaults to'purple').width?: string- The width of the slider component in pixels (defaults to'200').backgroundColor?: string- Background color of the tooltip (defaults to'#fff').textColor?: string- Text color of the tooltip (defaults to'#000').
OptionSlider
OptionSlider allows users to select a value by choosing from a set of options represented visually as blocks, with custom tooltip info display and read-only support.
import { useState } from 'react';
import { OptionSlider } from '@willphan1712000/frontend';
const options = [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
];
export default function Example() {
const [value, setValue] = useState('medium');
return (
<OptionSlider
value={value}
setValue={setValue}
options={options}
isReadOnly={false}
description="Choose intensity level"
styling={{
backgroundColor: '#ffffff',
textColor: '#000000',
borderColor: '#2563eb',
}}
/>
);
}Props:
value: string- The current value.setValue: (value?: string) => void- Callback function triggered when a new option is selected.options: { label: ReactNode; value: string }[]- List of options.labelcan be a React Node representing the option.isReadOnly?: boolean- If set totrue, disables changing the selected option, and shows a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional custom styling configurations:backgroundColor?: string- Background color of the tooltip (defaults to'#fff').textColor?: string- Text color of the tooltip (defaults to'#000').borderColor?: string- Border color of the options container and selected option (defaults to'#000').
ColorPickerSlider
ColorPickerSlider allows users to select a color by dragging the slider across a spectrum, with custom tooltip info display and read-only support.
import { useState } from 'react';
import { ColorPickerSlider } from '@willphan1712000/frontend';
export default function Example() {
const [value, setValue] = useState('#2563eb');
return (
<ColorPickerSlider
value={value}
setValue={setValue}
isReadOnly={false}
description="Pick your favorite color"
styling={{
width: '240',
backgroundColor: '#ffffff',
textColor: '#000000',
}}
/>
);
}Props:
value: string- The current color value.setValue: (value: string) => void- Callback function triggered when the slider value changes.isReadOnly?: boolean- If set totrue, disables changing the color slider and shows "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional custom styling configurations:width?: string- The width of the slider track in pixels (defaults to'200').backgroundColor?: string- Background color of the tooltip (defaults to'#000').textColor?: string- Text color of the tooltip (defaults to'#fff').
Button
import { Button } from '@willphan1712000/frontend';
export default function Example() {
return (
<Button
buttonType="gradient"
content="Submit"
type="button"
onClick={() => console.log('clicked')}
/>
);
}Supports:
buttonType="normal"buttonType="solid"buttonType="gradient"
Additional styling props:
content?: stringmain?: stringtext?: stringfirst?: stringsecond?: stringisLoading?: boolean
Also accepts normal button props such as onClick, type, disabled, and style.
Avatar
Avatar combines image upload, preview, edit, and remove flows.
import { useState } from 'react';
import { Avatar } from '@willphan1712000/frontend';
const [src, setSrc] = useState<string | undefined>(undefined);
<Avatar
value={src}
setValue={setSrc}
config={{ default: '/images/default-avatar.png' }}
/>;Props:
value?: string- Current base64 string or URL of the avatar image.setValue: (value?: string) => void- Callback function to update the image string.config?: object- Optional component configurations:default?: string- Default fallback image URL.
DynamicList
DynamicList is an interactive list component that allows users to add, remove, edit, and reorder (via drag-and-drop) a list of text inputs. It supports read-only mode, custom labelling, and hover descriptions.
import { useState } from 'react';
import { DynamicList } from '@willphan1712000/frontend';
const [values, setValues] = useState<string[]>(['Option 1', 'Option 2']);
<DynamicList
value={values}
setValue={setValues}
isReadOnly={false}
label="option"
description="List of options"
styling={{
backgroundColor: '#ffffff',
borderColor: '#e2e8f0',
textColor: '#1a202c'
}}
/>Props:
value: string[]- An array of strings representing the current values in the list.setValue: (value: string[]) => void- Callback triggered when the list values change.isReadOnly?: boolean- If set totrue, disables adding, deleting, editing, and dragging items (defaults tofalse).label?: string- Label used for input placeholders and the "Add" button (defaults to'value').description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional configurations:backgroundColor?: string- Background color for the list container and items (defaults to'#fff').borderColor?: string- Border color for the list container and items (defaults to'#f0f0f0').textColor?: string- Text color for input values and buttons (defaults to'#000').
FileDropZone
FileDropZone provides an interactive drag-and-drop area for uploading files, with custom validation by file extension and support for custom styling.
import { useState } from 'react';
import { FileDropZone } from '@willphan1712000/frontend';
const [file, setFile] = useState<File | undefined>(undefined);
<FileDropZone
label="Upload configuration"
value={file}
setValue={setFile}
config={{ accept: '.json' }}
isReadOnly={false}
description="Drag & drop your JSON configuration file"
styling={{
backgroundColor: '#fafafa',
borderColor: '#1a73e8',
textColor: '#3c4043',
destructive: '#d93025'
}}
/>Props:
label?: string- The text prompt displayed inside the drop zone.value?: File- Optional initial file to display as selected.setValue?: (value?: File) => void- Callback function triggered when a valid file is dropped or selected.config?: object- Optional configuration for component options:accept?: string- Allowed file extension/type suffix (e.g.".json").
isReadOnly?: boolean- If set totrue, disables changing the file and shows "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'').styling?: object- Optional configuration for custom styling:backgroundColor?: string- Custom background color of the drop zone (defaults to'#fff').borderColor?: string- Custom border color of the drop zone (defaults to'#fff').textColor?: string- Custom text and icon color inside the drop zone (defaults to'#000').destructive?: string- Custom color for error messages (defaults to'#df0408').
Info
Info renders a hover-help icon that displays a tooltip-style message when hovered. The tooltip automatically flips to the opposite side when it would overflow the viewport edges.
import { Info } from '@willphan1712000/frontend';
<Info
message="Helpful guidance for this field."
options={{
color: '#1f2937',
backgroundColor: '#f3f4f6',
}}
/>Props:
message?: string- Tooltip content shown on hover.options?: { color?: string; backgroundColor?: string }- Optional styling for the tooltip text and background.
Overlay
Overlay renders a full-screen background overlay (with a backdrop blur effect) around a central content container. Clicking outside the content container (on the overlay itself) triggers a close callback.
import { useState } from 'react';
import { Overlay } from '@willphan1712000/frontend';
const [isOpen, setIsOpen] = useState(false);
<Overlay
open={isOpen}
close={() => setIsOpen(false)}
options={{
backgroundColor: 'rgba(0, 0, 0, 0.5)'
}}
>
<div style={{ padding: '20px', background: '#fff', borderRadius: '8px' }}>
<h3>Overlay Content</h3>
<p>This is inside the overlay.</p>
</div>
</Overlay>Props:
open?: boolean- Controls whether the overlay is visible.close?: () => void- Callback function triggered when the overlay is clicked (outside the child element).options?: object- Optional custom configurations:backgroundColor?: string- Custom background color of the overlay (defaults to'#fff').
children?: React.ReactNode- Content inside the center container.
Spinner
Spinner renders a full-screen modal loading overlay with an animated spinning circle indicator and customizable text, implementing the WUII<string> interface.
import { Spinner } from '@willphan1712000/frontend';
export default function Example() {
return (
<Spinner
value="WillPhan"
styling={{
textColor: '#6f6f6f',
}}
/>
);
}Props:
value?: string- Custom text displayed below the circular spinner (defaults to'WillPhan').styling?: object- Optional custom styling configurations:textColor?: string- Color for the text gradient base and active spinner top border (defaults to'#6f6f6f').
InputGoogle
InputGoogle is a floating label input component designed to mimic Google's sign-in input fields, with built-in tooltip info display and read-only support.
import { useState } from 'react';
import { InputGoogle } from '@willphan1712000/frontend';
export default function Example() {
const [value, setValue] = useState('');
return (
<InputGoogle
value={value}
setValue={setValue}
label="Email or phone"
description="Enter your registered email address"
isReadOnly={false}
styling={{
focusColor: '#1a73e8',
backgroundColor: '#ffffff',
textColor: '#202124',
borderColor: '#dadce0',
}}
/>
);
}Props:
value?: string- The current value of the input field.setValue?: (value?: string) => void- Callback function triggered on input change.label?: string- The text for the floating label (defaults to'Input Google Component Label').description?: string- Description tooltip text shown on hover of the info icon (defaults to'Input Google Description'). Displays when the input is not read-only.isReadOnly?: boolean- If set totrue, the input becomes read-only and displays a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).styling?: object- Optional configuration for custom styling:focusColor?: string- Border and label color when the input is focused.backgroundColor?: string- Background color of the input container and label background.textColor?: string- Color of the text input and default label state.borderColor?: string- Default border color when not focused.
TextArea
TextArea is a floating label multi-line text input component with built-in tooltip info display and read-only support.
import { useState } from 'react';
import { TextArea } from '@willphan1712000/frontend';
export default function Example() {
const [value, setValue] = useState('');
return (
<TextArea
value={value}
setValue={setValue}
label="Bio"
description="Tell us about yourself"
isReadOnly={false}
styling={{
focusColor: '#1a73e8',
backgroundColor: '#ffffff',
textColor: '#202124',
borderColor: '#dadce0',
}}
/>
);
}Props:
value?: string- The current value of the textarea.setValue?: (value?: string) => void- Callback function triggered on value change.label?: string- The text for the floating label (defaults to'Text Area Component Label').isReadOnly?: boolean- If set totrue, the textarea becomes read-only and displays a "Locked - Read Only" tooltip message instead of the description (defaults tofalse).description?: string- Description tooltip text shown on hover of the info icon (defaults to'Text Area Description'). Displays when the textarea is not read-only.styling?: object- Optional configuration for custom styling:focusColor?: string- Border and label color when the textarea is focused.backgroundColor?: string- Background color of the textarea container and label background.textColor?: string- Color of the text and default label state.borderColor?: string- Default border color when not focused.
Auth usage
The auth helpers are designed around an auth client object that implements AuthInterface.
import {
SessionProvider,
useAuthClient,
type AuthInterface,
} from '@willphan1712000/frontend';
class AuthClient implements AuthInterface {
getSignInUrl() {
return '/signin';
}
async signin() {}
async validate() {
return {
username: 'will',
email: '[email protected]',
role: 'admin',
};
}
async signout() {}
}
const authClient = new AuthClient();
function AppProviders({ children }: { children: React.ReactNode }) {
const session = useAuthClient(authClient);
return (
<SessionProvider value={session}>
{children}
</SessionProvider>
);
}useAuthClient returns:
isLoadingsessionauth
Theme management usage
useThemeState
A custom React hook for managing, persisting, and applying the application's theme state ('light', 'dark', or 'system'). It synchronizes state with browser localStorage and applies/removes the theme class on document.body.
import { useThemeState } from '@willphan1712000/frontend';
const Example = () => {
const { setThemeState, getThemeState } = useThemeState();
return (
<div>
<p>Current Theme: {getThemeState()}</p>
<button onClick={() => setThemeState('light')}>Light</button>
<button onClick={() => setThemeState('dark')}>Dark</button>
<button onClick={() => setThemeState('system')}>System</button>
</div>
);
};API Reference
getThemeState(): 'light' | 'dark' | 'system'
Retrieves the active theme setting fromlocalStorage. Defaults to'light'.setThemeState(mode: 'light' | 'dark' | 'system'): void
Sets the active theme setting.'light': Stores'light', removes'will-dark'class fromdocument.body, and disables OS preference event listeners.'dark': Stores'dark', adds'will-dark'class todocument.body, and disables OS preference event listeners.'system': Stores'system', automatically toggles'will-dark'based on OS preferences, and registers a listener to react to future OS preference changes.
Configuration Details
- Local Storage Key:
'will-theme' - CSS Class Applied to
<body>:'will-dark'
Exported utilities
import {
Canvas,
ImageUtilities,
Transform,
tools,
LinearAlgebra,
} from '@willphan1712000/frontend';Included helpers:
tools.handleAsync(...)tools.textProcessing(...)tools.getOrCreateUUID(...)tools.copyToClipboard(...)
Development
Install dependencies:
npm installBuild the package:
npm run buildRun in watch mode during development:
npm run devLocal package testing with npm link
Inside this package:
npm linkInside the app where you want to test it:
npm link @willphan1712000/frontendIf React reports multiple copies loaded, link the consumer app's React instance:
npm link <path_to_your_testing_project>/node_modules/reactNotes
- The package is built with
tsup. - It ships CommonJS, ESM, and TypeScript declaration files.
- Source code is written in TypeScript and React.
Contributing
If you find a bug or want to improve the package, open an issue or submit a pull request.
Portfolio:
Contact:
