
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
@fgv/ts-res-ui-components
Advanced tools
Reusable React components for ts-res resource visualization and management
React components for building user interfaces that work with the ts-res multidimensional resource management library.
This library provides a complete set of React components, hooks, and utilities for creating applications that visualize, manage, and interact with ts-res resource systems. It supports the full workflow from importing configurations to resolving resources with dynamic context.
This packlet is largely AI written, and it shows.
This library now uses the ts-res zip-archive packlet as the single source of truth for all ZIP operations, providing:
The ImportView
component handles ZIP files automatically, and the ZipTools
namespace provides processing helpers for custom ZIP workflows.
npm install @fgv/ts-res-ui-components
This library requires the following peer dependencies:
{
"@fgv/ts-res": "^5.0.0",
"@fgv/ts-utils": "^5.0.0",
"@fgv/ts-json-base": "^5.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
The ResourceOrchestrator
component provides centralized state management for all ts-res UI functionality:
import React from 'react';
import { ResourceOrchestrator, ImportView, SourceView } from '@fgv/ts-res-ui-components';
function App() {
return (
<ResourceOrchestrator>
{({ state, actions }) => (
<div className="min-h-screen bg-gray-50">
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-8">Resource Manager</h1>
{!state.processedResources ? (
<ImportView
onImport={actions.importDirectory}
onBundleImport={actions.importBundle}
onZipImport={actions.importZipWithConfig}
/>
) : (
<SourceView
resources={state.processedResources}
onExport={actions.exportData}
/>
)}
</div>
</div>
)}
</ResourceOrchestrator>
);
}
export default App;
For more granular control, you can use individual hooks:
import React from 'react';
import { useResourceData, SourceView } from '@fgv/ts-res-ui-components';
function MyResourceViewer() {
const { state, actions } = useResourceData();
const handleFileImport = async (files: File[]) => {
const importedFiles = await processFiles(files); // Your file processing logic
await actions.processFiles(importedFiles);
};
return (
<div>
{state.isProcessing && <div>Processing...</div>}
{state.error && <div className="error">{state.error}</div>}
{state.processedResources && (
<SourceView
resources={state.processedResources}
onExport={(data) => console.log('Export:', data)}
/>
)}
</div>
);
}
ResourceOrchestrator (state management)
āāā ImportView (file/bundle/ZIP import)
āāā SourceView (resource collection display)
āāā FilterView (context filtering)
āāā CompiledView (compiled resource structure)
āāā ResolutionView (resource resolution testing)
āāā ConfigurationView (system configuration)
ConfigurationView
ImportView
or programmatically
ProcessedResources
object containing:
ResourceManagerBuilder
for build-time operationsCompiledResourceCollection
for runtime efficiencyResourceResolver
for resource resolutionFilterView
SourceView
and CompiledView
ResolutionView
The main orchestration component that manages all state and provides actions via render props.
<ResourceOrchestrator
initialConfiguration={myConfig}
onStateChange={(state) => console.log('State changed:', state)}
>
{({ state, actions }) => (
// Your UI components
)}
</ResourceOrchestrator>
Visual configuration management for ts-res system settings including qualifier types, qualifiers, and resource types.
<ConfigurationView
configuration={state.activeConfiguration}
onConfigurationChange={actions.applyConfiguration}
onSave={actions.saveConfiguration}
hasUnsavedChanges={state.hasConfigurationChanges}
onMessage={(type, message) => console.log(type, message)}
/>
Key features:
Handles importing resource files, directories, bundles, and ZIP files. Uses the ts-res zip-archive packlet for all ZIP operations.
<ImportView
onImport={actions.importDirectory}
onBundleImport={actions.importBundle}
onZipImport={(zipData, config) => {
// zipData contains files and directory structure from ZIP
// config contains any configuration found in the ZIP
actions.importDirectory(zipData, config);
}}
acceptedFileTypes={['.json', '.ts', '.js']}
onMessage={(type, message) => console.log(type, message)}
/>
Core component for browsing and selecting resources with advanced features like search, annotations, and pending resource support. The resource picker is a generic component used by all of the views, which can also be used to power other application-specific views.
<ResourcePicker
resources={state.processedResources}
selectedResourceId={selectedId}
onResourceSelect={(selection) => {
setSelectedId(selection.resourceId);
// Access resource data directly without additional lookups
if (selection.resourceData) {
handleResourceData(selection.resourceData);
}
// Handle pending resources
if (selection.isPending) {
console.log(`Pending ${selection.pendingType} operation`);
}
}}
options={{
defaultView: "tree",
enableSearch: true,
searchPlaceholder: "Search resources...",
height: "500px"
}}
resourceAnnotations={{
'user.welcome': {
badge: { text: '3', variant: 'info' },
suffix: '(3 candidates)'
}
}}
pendingResources={pendingChanges}
/>
Key features:
A debugging/design tool for interactively configuring ResourcePicker behavior. Hidden by default for production use, but can be enabled in development:
// All view components support pickerOptionsPresentation
<SourceView
resources={state.processedResources}
pickerOptionsPresentation="collapsible" // Enable picker options UI
onMessage={(type, message) => console.log(`${type}: ${message}`)}
/>
// Direct usage in custom components
<PickerTools.ResourcePickerOptionsControl
options={pickerOptions}
onOptionsChange={setPickerOptions}
presentation="popup" // 'hidden' | 'inline' | 'collapsible' | 'popup' | 'popover'
title="Picker Configuration"
showAdvanced={true}
/>
Presentation modes:
'hidden'
: Not displayed (default for production)'inline'
: Always visible with expanded controls'collapsible'
: Expandable/collapsible section'popup'
: Full modal dialog overlay'popover'
: Small dropdown overlayDisplays the source resource collection with search and navigation capabilities using the enhanced ResourcePicker.
<SourceView
resources={state.processedResources}
onExport={actions.exportData}
onMessage={(type, message) => console.log(`${type}: ${message}`)}
pickerOptions={{
defaultView: "list",
enableSearch: true,
searchPlaceholder: "Search resources..."
}}
/>
Provides filtering capabilities with context value specification and dual-resource comparison.
<FilterView
resources={state.processedResources}
filterState={filterState}
filterActions={filterActions}
filterResult={filterResult}
onFilterResult={setFilterResult}
onMessage={(type, message) => console.log(`${type}: ${message}`)}
pickerOptions={{
enableSearch: true,
searchPlaceholder: "Search resources..."
}}
/>
Shows the compiled resource structure with detailed candidate information using the enhanced ResourcePicker.
<CompiledView
resources={state.processedResources}
filterResult={filterResult}
useNormalization={true}
onExport={(data, type) => exportData(data, type)}
onMessage={(type, message) => console.log(`${type}: ${message}`)}
pickerOptions={{
defaultView: "tree",
enableSearch: true
}}
/>
Interactive resource resolution testing with context management and support for custom resource editors via the ResourceEditorFactory pattern.
<ResolutionView
resources={state.processedResources}
resolutionState={resolutionState}
resolutionActions={resolutionActions}
availableQualifiers={availableQualifiers}
resourceEditorFactory={myResourceEditorFactory}
onMessage={(type, message) => console.log(`${type}: ${message}`)}
pickerOptions={{
defaultView: "list",
enableSearch: true,
searchPlaceholder: "Search resources for resolution testing..."
}}
/>
The ResolutionView supports custom editors for specific resource types through the ResourceEditorFactory
interface:
import { ResourceEditorFactory, ResourceEditorResult, ResourceEditorProps } from '@fgv/ts-res-ui-components';
// Custom editor component
const MarketInfoEditor: React.FC<ResourceEditorProps> = ({
value,
resourceId,
isEdited,
editedValue,
onSave,
onCancel,
disabled,
className
}) => {
// Custom form-based editor implementation
return (
<div className={`market-info-editor ${className}`}>
{/* Custom editing interface for market information */}
</div>
);
};
// Resource editor factory
class MyResourceEditorFactory implements ResourceEditorFactory {
createEditor(resourceId: string, resourceType: string, value: any): ResourceEditorResult {
if (resourceType === 'marketInfo') {
return {
success: true,
editor: MarketInfoEditor
};
}
return {
success: false,
message: `No custom editor available for resource type '${resourceType}'`
};
}
}
// Usage
const editorFactory = new MyResourceEditorFactory();
<ResolutionView
resources={resources}
resourceEditorFactory={editorFactory}
// ... other props
/>
Benefits of Custom Editors:
Displays and manages application messages with filtering, search, and copy functionality. Perfect for debugging interfaces and development tools where message visibility is critical.
import { MessagesWindow, ViewTools } from '@fgv/ts-res-ui-components';
function MyApplication() {
const [messages, setMessages] = useState<ViewTools.Message[]>([]);
const addMessage = (type: ViewTools.Message['type'], text: string) => {
const newMessage: ViewTools.Message = {
id: `msg-${Date.now()}-${Math.random()}`,
type,
message: text,
timestamp: new Date()
};
setMessages(prev => [...prev, newMessage]);
};
const clearMessages = () => {
setMessages([]);
};
return (
<div className="flex flex-col h-screen">
<div className="flex-1">
{/* Main application content */}
<button onClick={() => addMessage('info', 'Processing started')}>
Add Info Message
</button>
<button onClick={() => addMessage('success', 'Operation completed')}>
Add Success Message
</button>
<button onClick={() => addMessage('error', 'Something went wrong')}>
Add Error Message
</button>
</div>
{/* Messages window at bottom */}
<MessagesWindow
messages={messages}
onClearMessages={clearMessages}
/>
</div>
);
}
Key features:
To integrate MessagesWindow into your application and provide user feedback during operations:
import { ViewTools } from '@fgv/ts-res-ui-components';
function useMessages() {
const [messages, setMessages] = useState<ViewTools.Message[]>([]);
const addMessage = useCallback((type: ViewTools.Message['type'], message: string) => {
const newMessage: ViewTools.Message = {
id: `msg-${Date.now()}-${Math.random()}`,
type,
message,
timestamp: new Date()
};
setMessages(prev => [...prev, newMessage]);
}, []);
const clearMessages = useCallback(() => {
setMessages([]);
}, []);
return { messages, addMessage, clearMessages };
}
function MyResourceTool() {
const { messages, addMessage, clearMessages } = useMessages();
const [resources, setResources] = useState(null);
const handleFileImport = async (files) => {
try {
addMessage('info', 'Starting file import...');
const processed = await processFiles(files);
setResources(processed);
addMessage('success', `Successfully imported ${files.length} files`);
} catch (error) {
addMessage('error', `Import failed: ${error.message}`);
}
};
const handleResourceFilter = (filterValues) => {
if (Object.keys(filterValues).length === 0) {
addMessage('warning', 'No filter values provided');
return;
}
try {
const filtered = applyFilters(resources, filterValues);
addMessage('success', `Filtered to ${filtered.length} resources`);
} catch (error) {
addMessage('error', `Filter failed: ${error.message}`);
}
};
return (
<div className="flex flex-col h-screen">
<div className="flex-1">
<ImportView onImport={handleFileImport} onMessage={addMessage} />
<FilterView onFilter={handleResourceFilter} onMessage={addMessage} />
{/* Other components that use onMessage callback */}
</div>
<ViewTools.MessagesWindow
messages={messages}
onClearMessages={clearMessages}
/>
</div>
);
}
Common patterns for adding messages:
Message callback integration:
Most components in this library accept an onMessage
callback prop that you can connect to your message system. This provides consistent feedback across all operations.
š See complete hooks documentation ā for detailed examples and patterns
All hooks are organized within their respective namespaces alongside their related components and utilities for better discoverability and logical grouping.
Main orchestrator hook for resource processing, configuration, and resolution.
import { ResourceTools } from '@fgv/ts-res-ui-components';
const { state, actions } = ResourceTools.useResourceData();
// Process files
await actions.processFiles(importedFiles);
// Resolve a resource
const result = await actions.resolveResource('my.resource', {
language: 'en-US',
environment: 'production'
});
// Apply configuration
actions.applyConfiguration(newConfig);
// Check processing state
if (state.isProcessing) {
console.log('Processing resources...');
} else if (state.error) {
console.error('Processing failed:', state.error);
} else if (state.processedResources) {
console.log('Resources ready!');
}
Manages view state including messages and resource selection.
import { ViewTools } from '@fgv/ts-res-ui-components';
const { messages, selectedResourceId, addMessage, clearMessages, selectResource } = ViewTools.useViewState();
// Display operation feedback
const handleOperation = async () => {
try {
await someAsyncOperation();
addMessage('success', 'Operation completed successfully');
} catch (error) {
addMessage('error', `Operation failed: ${error.message}`);
}
};
// Use with MessagesWindow component
return (
<div>
<button onClick={handleOperation}>Run Operation</button>
<ViewTools.MessagesWindow
messages={messages}
onClearMessages={clearMessages}
/>
</div>
);
Manages resource filtering state with change tracking and validation.
import { FilterTools } from '@fgv/ts-res-ui-components';
const { state, actions } = FilterTools.useFilterState({
enabled: true,
values: { platform: 'web', locale: 'en' }
});
// Update filter values with change tracking
actions.updateFilterValue('language', 'en-US');
actions.updateFilterValue('environment', 'prod');
// Apply filters when ready
if (state.hasPendingChanges) {
actions.applyFilters();
}
Comprehensive state management for resource resolution and editing.
import { ResolutionTools } from '@fgv/ts-res-ui-components';
const { state, actions, availableQualifiers } = ResolutionTools.useResolutionState(
processedResources,
(type, message) => addMessage(type, message),
(updatedResources) => setProcessedResources(updatedResources)
);
// Set context for resolution testing
actions.updateContext({ language: 'en-US', platform: 'web' });
// Start editing a resource
actions.selectResource('user.welcome');
actions.startEditing();
// Save edits with validation
actions.saveEdit(editedValue);
Manages system configuration state with change tracking and import/export capabilities.
import { ConfigurationTools } from '@fgv/ts-res-ui-components';
const { state, actions, templates } = ConfigurationTools.useConfigurationState(
undefined,
(config) => console.log('Configuration changed:', config),
(hasChanges) => setHasUnsavedChanges(hasChanges)
);
// Load a template
const loadResult = actions.loadTemplate('minimal');
// Add a new qualifier with validation
actions.addQualifier({
name: 'language',
typeName: 'language',
defaultPriority: 100
});
// Check for unsaved changes
if (state.hasUnsavedChanges) {
actions.applyConfiguration();
}
// Export configuration
const exportResult = actions.exportToJson({ pretty: true });
if (exportResult.isSuccess()) {
downloadFile(exportResult.value, 'configuration.json');
}
All hooks are organized within logical namespaces alongside their related components and utilities:
ResourceTools.useResourceData
- Core data orchestration (import, processing, configuration, resolution)ViewTools.useViewState
- View state management (messages, resource selection)FilterTools.useFilterState
- Resource filtering with change trackingResolutionTools.useResolutionState
- Resource resolution and editingConfigurationTools.useConfigurationState
- System configuration managementThis organization provides:
FilterTools.useFilterState
is self-documentingThis library uses Tailwind CSS for styling. Make sure to include Tailwind CSS in your project:
npm install -D tailwindcss
Add the library's source files to your Tailwind content configuration:
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./node_modules/@fgv/ts-res-ui-components/**/*.{js,jsx,ts,tsx}'
],
theme: {
extend: {},
},
plugins: [],
}
All components accept a className
prop for custom styling:
<SourceView
className="my-custom-class"
resources={resources}
/>
import { TsResTools } from '@fgv/ts-res-ui-components';
// Custom processing pipeline
const customProcessor = async (files: ImportedFile[]) => {
// Pre-process files
const processedFiles = files.map(transformFile);
// Create configuration
const config = await createConfigFromFiles(processedFiles);
// Create ts-res system
const system = await TsResTools.createTsResSystemFromConfig(config);
return system;
};
const { state, actions } = useResourceData();
// Complex context resolution
const resolveWithComplexContext = async (resourceId: string) => {
const context = {
language: getUserLanguage(),
region: getUserRegion(),
theme: getThemePreference(),
featureFlags: await getFeatureFlags()
};
return await actions.resolveResource(resourceId, context);
};
const { state, actions } = useResourceData();
// Create and export bundle
const exportBundle = async () => {
if (state.processedResources) {
const bundleData = {
...state.processedResources.compiledCollection,
metadata: {
version: '1.0.0',
created: new Date().toISOString(),
description: 'My resource bundle'
}
};
actions.exportData(bundleData, 'bundle');
}
};
The library provides comprehensive error handling through the state management system:
<ResourceOrchestrator>
{({ state, actions }) => (
<div>
{state.error && (
<div className="bg-red-50 border border-red-200 rounded p-4 mb-4">
<h3 className="text-red-800 font-medium">Error</h3>
<p className="text-red-600">{state.error}</p>
<button
onClick={actions.clearError}
className="mt-2 px-3 py-1 bg-red-600 text-white rounded text-sm"
>
Dismiss
</button>
</div>
)}
{/* Rest of your UI */}
</div>
)}
</ResourceOrchestrator>
For better organization and discoverability, utility functions are organized into logical namespaces alongside their related view components:
import {
FilterTools, // FilterView + filtering utilities
ResolutionTools, // ResolutionView + resolution utilities
ConfigurationTools, // ConfigurationView + configuration utilities
TsResTools, // SourceView, CompiledView + ts-res utilities
ViewTools, // MessagesWindow + view state utilities
ZipTools, // ImportView + ZIP processing helpers
FileTools // File processing utilities
} from '@fgv/ts-res-ui-components';
// Use view components from namespaces
<FilterTools.FilterView {...filterProps} />
<ResolutionTools.ResolutionView {...resolutionProps} />
<ViewTools.MessagesWindow {...messageProps} />
<TsResTools.SourceView {...sourceProps} />
<ZipTools.ImportView {...importProps} />
// Use utility functions from namespaces
const hasFilters = FilterTools.hasFilterValues(filterState.values);
const resolver = ResolutionTools.createResolverWithContext(resources, context);
const system = await TsResTools.createTsResSystemFromConfig(config);
// ZIP processing helpers for ts-res-ui-components integration
const processResult = await ZipTools.processZipLoadResult(zipData, config);
All components are also available at the top level for backward compatibility.
This library is written in TypeScript and provides comprehensive type definitions with enhanced support for resource selection and generic resource data.
import type {
ProcessedResources,
FilterState,
ResolutionResult,
Message,
ImportedFile,
// Enhanced ResourcePicker types
ResourceSelection,
ResourcePickerProps,
ResourceAnnotation,
ResourceAnnotations,
PendingResource,
// Custom editor factory types
ResourceEditorFactory,
ResourceEditorResult,
ResourceEditorProps,
// Hook return types
UseViewStateReturn,
UseFilterStateReturn,
UseResolutionStateReturn
} from '@fgv/ts-res-ui-components';
// Import organized namespaces for components and utilities
import {
FilterTools,
ResolutionTools,
TsResTools,
ZipTools
} from '@fgv/ts-res-ui-components';
// Type-safe component with enhanced resource selection
interface MyResourceViewProps<T = unknown> {
resources: ProcessedResources;
onMessage: (type: Message['type'], message: string) => void;
onResourceSelect: (selection: ResourceSelection<T>) => void;
}
const MyResourceView = <T = unknown>({ resources, onMessage, onResourceSelect }: MyResourceViewProps<T>) => {
return (
<ResourcePicker<T>
resources={resources}
onResourceSelect={(selection) => {
// TypeScript knows selection has resourceId, resourceData, isPending, etc.
onResourceSelect(selection);
}}
resourceAnnotations={{
'user.welcome': {
badge: { text: 'NEW', variant: 'new' },
suffix: '(3 candidates)'
}
}}
/>
);
};
// Type-safe custom editor factory
class TypedResourceEditorFactory implements ResourceEditorFactory {
createEditor(resourceId: string, resourceType: string, value: any): ResourceEditorResult {
// Full type safety for factory pattern
if (resourceType === 'marketInfo') {
return { success: true, editor: MarketInfoEditor };
}
return { success: false, message: `No editor for ${resourceType}` };
}
}
This library is part of a Rush.js monorepo. Rush is a build orchestrator for JavaScript monorepos that provides scalable build performance and consistent package management.
If you're new to this monorepo, follow these steps to get started:
Install Rush globally (if not already installed):
npm install -g @microsoft/rush
Clone the repository and install dependencies:
git clone https://github.com/ErikFortune/fgv.git
cd fgv
rush install
Build all projects (including dependencies):
rush build
š Learn more about Rush: Official Rush Documentation
All development commands use Rush's rushx
tool to run scripts within this specific project:
# Build this project only
rushx build
# Build all projects in the monorepo (from root)
rush build
# Test this project (includes coverage by default)
rushx test
# Test all projects in the monorepo (from root)
rush test
# Test specific projects with dependencies
rush test --to ts-res-ui-components
# Test only this project without dependencies
rush test --only ts-res-ui-components
# Lint this project
rushx lint
# Fix lint issues automatically
rushx fixlint
# Lint all projects in the monorepo (from root)
rush prettier
# Clean build artifacts
rushx clean
# Update dependencies (from repository root)
rush update
# Add a new dependency to this project (from repository root)
rush add -p <package-name>
# Check for security vulnerabilities (from repository root)
rush audit
This library is located at libraries/ts-res-ui-components/
within the monorepo and depends on several other libraries in the workspace:
@fgv/ts-res
- Core resource management library@fgv/ts-utils
- Utility functions and Result pattern@fgv/ts-json-base
- JSON validation and processing@fgv/ts-bcp47
- BCP47 language tag processingAll workspace dependencies use workspace:*
version ranges for automatic version resolution.
MIT License - see LICENSE file for details.
Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
Comprehensive API documentation is available in the docs directory:
The API documentation includes detailed examples, usage patterns, and type information for all public APIs.
For questions and support, please:
FAQs
Reusable React components for ts-res resource visualization and management
The npm package @fgv/ts-res-ui-components receives a total of 217 weekly downloads. As such, @fgv/ts-res-ui-components popularity was classified as not popular.
We found that @fgv/ts-res-ui-components demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Ā It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.