legalesign-ui-react
v0.0.53
Published
StencilJS library with React output target
Readme
Legalesign Components Library for React
React wrapper for Legalesign UI web components, providing a native React experience with proper TypeScript support.
Table of Contents
Installation
npm install legalesign-ui-react
# or
pnpm install legalesign-ui-reactThis will add it to your package.json:
{
"dependencies": {
"legalesign-ui-react": "^0.0.1"
}
}Requirements
- React >= 18.0.0
- TypeScript >= 4.5.0 (optional, but recommended)
Usage
Basic Setup
Import components and styles in your app entry point or component:
import { LsButton, LsFormfield } from 'legalesign-ui-react';
import 'legalesign-ui-react/dist/index.css';
const App = () => {
return (
<div>
<LsButton variant="primary" text="Click me" />
<LsFormfield
name="email"
fieldId="email"
label="Email Address"
as="text"
placeholder="Enter your email"
required={true}
/>
</div>
);
};Key Differences from Web Components
When using the React wrapper instead of the web components directly:
| Aspect | Web Components (legalesign-ui) | React Wrapper (legalesign-ui-react) |
|--------|----------------------------------|---------------------------------------|
| Component names | <ls-button> (kebab-case) | <LsButton> (PascalCase) |
| Props | field-id="email" (kebab-case) | fieldId="email" (camelCase) |
| Boolean props | required (presence/absence) | required={true} (explicit) |
| Events | addEventListener('valueChange') | onValueChange={handler} |
| Refs | querySelector('ls-button') | useRef<HTMLLsButtonElement>() |
Event Handling
Events are exposed as React props with on prefix:
import { LsFormfield, LsButton } from 'legalesign-ui-react';
const MyForm = () => {
const handleChange = (event: CustomEvent) => {
console.log('Value changed:', event.detail);
};
const handleClick = () => {
console.log('Button clicked');
};
return (
<>
<LsFormfield
name="username"
fieldId="username"
label="Username"
as="text"
onValueChange={handleChange}
/>
<LsButton
variant="primary"
text="Submit"
onClick={handleClick}
/>
</>
);
};TypeScript
Component Props
All components are fully typed. The types are automatically generated from the Stencil components:
import { LsButton, LsFormfield } from 'legalesign-ui-react';
// Props are fully typed
const MyComponent = () => {
return (
<>
<LsButton variant="primary" text="Click me" />
<LsFormfield name="email" fieldId="email" as="text" required={true} />
</>
);
};Event Types
Events are typed as CustomEvent with proper detail types. Check the generated types for specific event signatures:
import { LsFormfield } from 'legalesign-ui-react';
const MyForm = () => {
const handleChange = (event: CustomEvent<{ name: string; value: string | number | boolean }>) => {
const { name, value } = event.detail;
console.log('Field changed:', name, value);
};
return (
<LsFormfield
name="email"
fieldId="email"
as="text"
onValueChange={handleChange}
/>
);
};Using Refs
Access the underlying web component element using refs:
import { useRef, useEffect } from 'react';
import { LsFormfield } from 'legalesign-ui-react';
const MyForm = () => {
const fieldRef = useRef<HTMLLsFormfieldElement>(null);
useEffect(() => {
if (fieldRef.current) {
// Access the element
console.log('Field element:', fieldRef.current);
}
}, []);
return (
<LsFormfield
ref={fieldRef}
name="email"
fieldId="email"
as="text"
/>
);
};Common Patterns
Form Validation
import { useState } from 'react';
import { LsFormfield, LsButton } from 'legalesign-ui-react';
const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleEmailChange = (event: CustomEvent<{ name: string; value: string | number | boolean }>) => {
setEmail(event.detail.value as string);
};
const handlePasswordChange = (event: CustomEvent<{ name: string; value: string | number | boolean }>) => {
setPassword(event.detail.value as string);
};
const handleSubmit = () => {
console.log('Submitting:', { email, password });
};
return (
<form onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>
<LsFormfield
name="email"
fieldId="email"
label="Email"
as="text"
required={true}
errorText="Please enter a valid email"
onValueChange={handleEmailChange}
/>
<LsFormfield
name="password"
fieldId="password"
label="Password"
as="password"
required={true}
onValueChange={handlePasswordChange}
/>
<LsButton
variant="primary"
text="Submit"
disabled={!email || !password}
onClick={handleSubmit}
/>
</form>
);
};Controlled Components
import { useState } from 'react';
import { LsFormfield } from 'legalesign-ui-react';
const ControlledInput = () => {
const [value, setValue] = useState('');
const handleChange = (event: CustomEvent<{ name: string; value: string | number | boolean }>) => {
setValue(event.detail.value as string);
};
return (
<LsFormfield
name="controlled"
fieldId="controlled"
label="Controlled Input"
as="text"
value={value}
onValueChange={handleChange}
/>
);
};Loading States
import { useState } from 'react';
import { LsButton, LsLoading } from 'legalesign-ui-react';
const AsyncAction = () => {
const [loading, setLoading] = useState(false);
const handleAction = async () => {
setLoading(true);
try {
await fetch('/api/action');
} finally {
setLoading(false);
}
};
return (
<>
<LsButton
variant="primary"
text="Submit"
loading={loading}
onClick={handleAction}
/>
{loading && <LsLoading text="Processing..." />}
</>
);
};Dynamic Form Fields
import { useState } from 'react';
import { LsFormfield, LsButton } from 'legalesign-ui-react';
const DynamicForm = () => {
const [fields, setFields] = useState([{ id: 0, value: '' }]);
const addField = () => {
setFields([...fields, { id: fields.length, value: '' }]);
};
const updateField = (id: number, value: string) => {
setFields(fields.map(f => f.id === id ? { ...f, value } : f));
};
const handleChange = (id: number) => (event: CustomEvent<{ name: string; value: string | number | boolean }>) => {
updateField(id, event.detail.value as string);
};
return (
<>
{fields.map((field) => (
<LsFormfield
key={field.id}
name={`field-${field.id}`}
fieldId={`field-${field.id}`}
label={`Field ${field.id + 1}`}
as="text"
value={field.value}
onValueChange={handleChange(field.id)}
/>
))}
<LsButton
variant="secondary"
text="Add Field"
onClick={addField}
/>
</>
);
};Migration Guide
From Web Components to React Wrapper
If you're currently using legalesign-ui web components directly in React, here's how to migrate:
Before (Web Components)
import 'legalesign-ui';
import 'legalesign-ui/dist/legalesign-components/legalesign-components.css';
const App = () => {
const handleChange = (e) => {
console.log(e.detail);
};
useEffect(() => {
const field = document.querySelector('ls-formfield');
field.addEventListener('valueChange', handleChange);
return () => field.removeEventListener('valueChange', handleChange);
}, []);
return (
<ls-formfield
name="email"
field-id="email"
as="text"
required
/>
);
};After (React Wrapper)
import { LsFormfield } from 'legalesign-ui-react';
import 'legalesign-ui-react/dist/index.css';
const App = () => {
const handleChange = (e: CustomEvent<string>) => {
console.log(e.detail);
};
return (
<LsFormfield
name="email"
fieldId="email"
as="text"
required={true}
onValueChange={handleChange}
/>
);
};Migration Checklist
- [ ] Replace
legalesign-uiwithlegalesign-ui-reactin package.json - [ ] Update CSS import path
- [ ] Convert component names from kebab-case to PascalCase
- [ ] Convert props from kebab-case to camelCase
- [ ] Convert boolean props to explicit
{true}or{false} - [ ] Replace
addEventListenerwithonprefixed props - [ ] Update TypeScript types if using
Development
Folder Structure
/___tests___
/dist
/lib
/components
/stencil-generated
components.ts
package.json
README.md
tsconfig.jsonBuilding
The React wrapper is automatically generated from the Stencil components using the React output target.
Development is done in the legalesign-ui package. See the legalesign-ui package on npm for details.
Local Development
# Build the web components first
cd packages/ui
pnpm build
# Build the React wrapper
cd ../ui-react
pnpm buildPublishing
Publishing is automated via GitHub Actions. When a PR is merged to main:
- Version is bumped based on PR title (
feat:→ minor,BREAKING CHANGE→ major, else → patch) - Both
legalesign-uiandlegalesign-ui-reactare built and published to npm - Version bump is committed and tagged
For details, see the root README.
Documentation
All components are documented in Storybook: https://ui.legalesign.io/
Note: Storybook shows web component examples. For React usage, refer to this README.
Support
- Issues: GitHub Issues
- Changelog: GitHub Releases
- Web Components Version: legalesign-ui on npm
License
Proprietary - Legalesign Ltd.
