| Crates.io | themed-styler |
| lib.rs | themed-styler |
| version | 1.2.9 |
| created_at | 2025-12-17 17:12:10.534462+00 |
| updated_at | 2026-01-05 14:28:15.49109+00 |
| description | Client-side runtime styling engine for web and Android/iOS Native with theme support and Tailwind subset |
| homepage | https://relaynet.online |
| repository | http://github.com/clevertree/themed-styler |
| max_upload_size | |
| id | 1990756 |
| size | 265,785 |
A high-performance styling engine for Relay that supports dynamic theme switching and consistent rendering across Web and Native platforms.
graph TD
subgraph "Theme Definition"
YAML[theme.yaml]
end
subgraph "Styler Core (Rust)"
Parser[CSS/Style Parser]
Engine[Theme Engine]
Unit[Unit Converter]
end
subgraph "Output"
Web[WASM / CSS]
Android[JNI / Style Objects]
end
YAML --> Engine
Parser --> Engine
Engine --> Unit
Unit --> Web
Unit --> Android
As part of the Relay project vision, we believe that design systems should be platform-agnostic and runtime-efficient. @clevertree/themed-styler allows developers to define themes once in YAML or JSON and have them applied consistently across Web (generating CSS) and Android/iOS Native (generating StyleSheets).
By offloading the style computation to a shared Rust core, we achieve:
Install from npm:
npm install @clevertree/themed-styler
# or
yarn add @clevertree/themed-styler
The package includes prebuilt WASM files in the wasm/ directory, so no additional build step is required during installation.
When you run npm install, the WASM files are automatically included:
node_modules/@clevertree/themed-styler/wasm/themed_styler.js (WASM wrapper)node_modules/@clevertree/themed-styler/wasm/themed_styler_bg.wasm (WASM binary)These are bundled and published with every version update. When you upgrade the package, the WASM files are updated automatically—no manual copy needed.
Initialize the WASM module in your app startup:
import { initThemedStyler, unifiedBridge, styleManager } from '@clevertree/themed-styler';
async function startApp() {
// Initialize the WASM styler
await initThemedStyler();
// Ensure default themes are loaded
await unifiedBridge.ensureDefaultsLoaded();
// Start auto-sync for style updates
styleManager.startAutoSync();
}
Then use themed components in your precompiled React code:
import { TSDiv, Text } from '@clevertree/themed-styler';
const MyComponent = () => (
<TSDiv tag="div" className="p-4 bg-surface text-primary">
<Text>Hello Relay!</Text>
</TSDiv>
);
The WASM files are loaded dynamically by initThemedStyler(). Here are key points for different bundlers:
For Vite:
WASM files must be served as static assets. Standard Vite configuration handles this automatically.
If using custom vite.config.ts, ensure .wasm files are not excluded from assets:
export default {
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name].[hash][extname]'
}
}
}
};
For esbuild:
--loader:.wasm=file to emit WASM as external files.For webpack:
file-loader or asset/resource is configured for .wasm files.If you see console errors like "Failed to load WASM" or network 404 errors for themed_styler_bg.wasm:
Step 1: Verify WASM files exist
ls node_modules/@clevertree/themed-styler/wasm/
# Should output:
# themed_styler.js
# themed_styler_bg.wasm
Step 2: Clear and reinstall if missing
rm -rf node_modules
npm install
Step 3: Rebuild your bundle
npm run build
Step 4: Check bundler output Verify that your bundle includes the WASM files in the dist directory:
ls dist/ # or dist/assets/ depending on your bundler
# Should see themed_styler*.wasm files
Step 5: For custom HTTP servers If using a non-Vite HTTP server, ensure it serves WASM with correct MIME type:
// Express.js example
app.use('/node_modules/@clevertree/themed-styler/wasm', express.static(
path.join(__dirname, 'node_modules/@clevertree/themed-styler/wasm'),
{
setHeaders: (res, path) => {
if (path.endsWith('.wasm')) {
res.setHeader('Content-Type', 'application/wasm');
}
}
}
));
Step 6: Check browser DevTools
themed_styler_bg.wasm requestStep 7: After upgrading the package
rm -rf distnpm run buildInitialize the native themed styler binding in your app:
import { initThemedStyler, ensureDefaultsLoaded } from '@clevertree/themed-styler/android';
import { TSDiv, View, Text } from '@clevertree/themed-styler/android';
async function startApp() {
// Initializes native Rust FFI binding via TurboModule
// Android: Uses JNI to call Rust native functions
// iOS: (Coming soon) Uses C-FFI to call Rust native functions
await initThemedStyler();
// Load default theme definitions from YAML
await ensureDefaultsLoaded();
}
// In your component
const MyComponent = () => (
<TSDiv tag="view" className="p-4 bg-surface text-primary">
<Text>Hello Relay!</Text>
</TSDiv>
);
For Android, ensure your app's native code has the Relay JNI module registered:
ThemedStyler module for JSI accessUse platform-specific entry points to avoid bundling unnecessary code:
// Web
import { initThemedStyler, TSDiv } from '@clevertree/themed-styler';
// Android/iOS Native
import { initThemedStyler, TSDiv } from '@clevertree/themed-styler/android';
TSDiv: A versatile themed component that maps to appropriate native views (View, ScrollView, SafeAreaView, etc.) based on the tag and className.styled: A utility for creating themed components, similar to styled-components but powered by the Relay Rust core.styleManager (Web only): Manages CSS rendering, auto-sync, and DOM updates.unifiedBridge: Provides unified theme registration and CSS generation API across platforms.View, Text, TouchableOpacity, SafeAreaView, etc., with theme awareness.If modifying the Rust core or TypeScript sources:
# Install dependencies
npm install
# Compile TypeScript and build WASM
npm run build
# The build script automatically:
# 1. Runs `wasm-pack build --release --target web --features wasm`
# 2. Copies WASM files to `wasm/` directory
# 3. Compiles TypeScript to `dist/web/`, `dist/android/`, and `dist/shared/`
Run the test suite:
# Web tests (Cypress)
cd tests/web
npm install
npm run test:e2e
Symptom: "Failed to initialize WASM styler" or console shows WASM module undefined.
Solution:
ls node_modules/@clevertree/themed-styler/wasm/themed_styler_bg.wasm (see Avoiding 404 Errors section above)rm -rf dist && npm run buildrm -rf node_modules && npm installSymptom: Components render but styles don't apply.
Solution:
initThemedStyler() is called before rendering componentsstyleManager.startAutoSync() is called to enable live style updatesunifiedBridge.ensureDefaultsLoaded() completes successfullyregisterTheme(name, definitions)Symptom: Components render but styles are empty.
Solution:
initThemedStyler() completes without errorsadb logcat | grep ThemedStylerthemed-styler ensures consistent rendering across Web and Native by implementing a unified unit conversion system.
px-as-dp LogicOn Android and iOS Native, physical pixels (px) vary significantly between devices due to different screen densities. To maintain design consistency with Web, themed-styler treats the px unit in CSS as Density-independent Pixels (dp) when rendering for Native platforms.
10px renders as exactly 10 physical pixels.10px is treated as 10dp and converted to physical pixels based on the device's display density.
xhdpi device (density = 2.0), 10px becomes 20 physical pixels.mdpi device (density = 1.0), 10px becomes 10 physical pixels.For text-related properties (like fontSize), themed-styler uses the device's Scaled Density instead of the base display density. This ensures that if a user has increased their system font size for accessibility, the Relay hooks will respect that setting.
| Unit | Behavior |
|---|---|
px |
Treated as dp on Native, physical pixels on Web. |
dp |
Explicit density-independent pixels (Native only). |
sp |
Scaled pixels for text (Native only). |
% |
Percentage of parent container. |
rem |
Root-relative units (converted to 16px base by default). |
vh/vw |
Viewport-relative units (Web only). |
Contributions are welcome! Please ensure:
npm run buildtsc --noEmitnpm run test:e2e (web)See LICENSE file in the repository.