npm package: @lnsy/command-panel
Description: A customizable command palette web component with keyboard shortcuts and fuzzy search
Author: LNSY
Latest version: 0.1.0

# Version 0.1.0. 

This software is in deep prototype state. I strongly advise against using it for now. 

# Command Panel Component

A customizable command palette web component built with vanilla JavaScript. Provides a keyboard-driven interface for executing commands in your web application, similar to VS Code's command palette or Spotlight on macOS.

## Features

- 🎯 **Keyboard-driven interface** - Quick access via customizable keyboard shortcuts (default: Ctrl+Shift+P)
- 🔍 **Fuzzy search** - Find commands quickly with intelligent fuzzy matching
- ⌨️ **Arrow key navigation** - Navigate through commands with up/down arrows
- 🎨 **Customizable styling** - CSS variables for easy theming
- 📦 **Zero dependencies** - Built on dataroom-js framework
- ♿ **Accessible** - Proper focus management and keyboard support
- 🚀 **Lightweight** - Minimal footprint with no external dependencies

## Installation

Install the package via npm:

```bash
npm install @lnsy/command-panel
```

## Quick Start

### 1. Import the Component

```javascript
import '@lnsy/command-panel';
```

### 2. Add to Your HTML

```html
<command-panel id="myCommandPanel"></command-panel>
```

### 3. Register Commands

```javascript
const commandPanel = document.getElementById('myCommandPanel');

// Add commands with icons and callbacks
commandPanel.addCommand('Create New File', '📄', () => {
  console.log('Creating new file...');
});

commandPanel.addCommand('Open Settings', '⚙️', () => {
  console.log('Opening settings...');
});

commandPanel.addCommand('Search Project', '🔍', () => {
  console.log('Searching project...');
});
```

### 4. Open the Panel

Press **Ctrl+Shift+P** (or **Cmd+Shift+P** on Mac) to open the command panel!

## Usage

### Adding Commands

Use the `addCommand` method to register commands:

```javascript
commandPanel.addCommand(name, icon, callback);
```

**Parameters:**
- `name` (string, required) - The display name of the command
- `icon` (string, optional) - An emoji or icon to display (can be `null`)
- `callback` (function, required) - Function to execute when command is selected

**Example:**

```javascript
// Command with icon
commandPanel.addCommand('Deploy Application', '🚀', () => {
  deployApp();
});

// Command without icon
commandPanel.addCommand('Toggle Dark Mode', null, () => {
  toggleDarkMode();
});
```

### Custom Keyboard Shortcuts

Customize the keyboard shortcut using the `open-keys` attribute:

```html
<!-- Use Alt+K instead of Ctrl+Shift+P -->
<command-panel id="myCommandPanel" open-keys="alt+k"></command-panel>
```

**Supported modifiers:**
- `ctrl` - Control key
- `shift` - Shift key
- `alt` - Alt/Option key
- `cmd` or `meta` - Command key (Mac) / Windows key

**Examples:**

```html
<!-- Ctrl+K -->
<command-panel open-keys="ctrl+k"></command-panel>

<!-- Cmd+Shift+K (Mac) -->
<command-panel open-keys="cmd+shift+k"></command-panel>

<!-- Alt+Space -->
<command-panel open-keys="alt+space"></command-panel>
```

### Listening to Events

Listen for command execution events:

```javascript
commandPanel.on('COMMAND-EXECUTED', (data) => {
  console.log('Command executed:', data.name);
  console.log('Icon:', data.icon);
});
```

### Multiple Command Panels

You can have multiple command panels with different shortcuts:

```html
<!-- Main command panel -->
<command-panel id="mainPanel" open-keys="ctrl+shift+p"></command-panel>

<!-- Quick actions panel -->
<command-panel id="quickPanel" open-keys="alt+k"></command-panel>
```

```javascript
const mainPanel = document.getElementById('mainPanel');
mainPanel.addCommand('Main Action 1', '📋', () => { /* ... */ });

const quickPanel = document.getElementById('quickPanel');
quickPanel.addCommand('Quick Action 1', '⚡', () => { /* ... */ });
```

## Keyboard Controls

When the command panel is open:

- **Type** - Filter commands with fuzzy search
- **↑/↓ Arrow Keys** - Navigate through filtered commands
- **Enter** - Execute the selected command
- **Escape** - Close the panel
- **Click backdrop** - Close the panel

## Styling

The component uses CSS variables for easy customization. Override these in your CSS:

```css
:root {
  --background-color: #ffffff;
  --foreground-color: #000000;
  --secondary-color: #f5f5f5;
  --trinary-color: #999999;
  --highlight-color: #0066cc;
}
```

### Custom Styling Example

```css
/* Dark theme */
command-panel dialog {
  --background-color: #1e1e1e;
  --foreground-color: #ffffff;
  --secondary-color: #2d2d2d;
  --trinary-color: #666666;
  --highlight-color: #007acc;
}

/* Custom dialog size */
command-panel dialog {
  width: 800px;
  top: 10%;
}

/* Custom command item styling */
command-panel .command-item {
  padding: 14px 20px;
  font-size: 16px;
}
```

## Complete Example

```html
<!DOCTYPE html>
<html>
<head>
  <title>Command Panel Demo</title>
  <script type="module">
    import '@lnsy/command-panel';
    
    // Wait for component to be ready
    window.addEventListener('DOMContentLoaded', () => {
      const commandPanel = document.getElementById('commandPanel');
      
      // Add commands
      commandPanel.addCommand('Create New File', '📄', () => {
        alert('New file created!');
      });
      
      commandPanel.addCommand('Open Settings', '⚙️', () => {
        alert('Settings opened!');
      });
      
      commandPanel.addCommand('Search Project', '🔍', () => {
        alert('Search initiated!');
      });
      
      commandPanel.addCommand('Run Build', '🔨', () => {
        alert('Build started!');
      });
      
      // Listen for events
      commandPanel.on('COMMAND-EXECUTED', (data) => {
        console.log('Executed:', data.name);
      });
    });
  </script>
</head>
<body>
  <h1>My Application</h1>
  <p>Press <kbd>Ctrl+Shift+P</kbd> to open the command panel</p>
  
  <command-panel id="commandPanel"></command-panel>
</body>
</html>
```

## Development

### Getting Started

Install dependencies:

```bash
npm install
```

### Running the Development Server

To run the project in development mode:

```bash
npm start
```

This will start a development server on port 3000 (configurable via `.env`).

### Building for Production

To build the project for production:

```bash
npm run build
```

This will create a `dist` folder with the bundled and optimized files.

## Customizing the Build

You can customize the build output by creating a `.env` file in the root of the project.

### Output Filename

To change the name of the output file, set the `OUTPUT_FILE_NAME` variable in your `.env` file.

**.env**
```
OUTPUT_FILE_NAME=my-custom-filename.js
```

If this variable is not set, the output file will default to `dist/main.min.js`.

### Development Server Port

You can also change the development server port by setting the `PORT` variable in your `.env` file.

**.env**
```
PORT=8080
```

If this variable is not set, the port will default to `3000`.

## Project Structure

- `src/` - Your JavaScript source files
- `styles/` - CSS files
- `scripts/` - Build scripts (including Web Worker transformation)
- `index.html` - Main HTML file
- `index.js` - Main JavaScript entry point
- `index.css` - Main CSS file
- `rspack.config.js` - Rspack configuration

## Rspack Build Configuration

### Features

The project uses Rspack with the following features configured:

#### Module Processing

- **CSS Processing Pipeline**
  - `style-loader` - Injects CSS into the DOM
  - `css-loader` - Resolves CSS imports and URLs
  - `postcss-loader` with cssnano - Minifies and optimizes CSS
  - Source maps enabled in development mode
  - Automatic comment removal in production builds

- **JavaScript Processing**
  - `builtin:swc-loader` - Fast JavaScript transpilation
  - Custom `transform-workers.js` loader - Transforms web worker imports
  - Dynamic imports forced to eager mode for web worker compatibility
  - Source maps enabled in development mode

#### Web Workers

The build system includes special handling for web workers:

- Custom loader (`scripts/transform-workers.js`) transforms worker imports
- Dynamic imports are eagerly evaluated for worker compatibility
- Workers are properly bundled and can be imported in your code

#### Assets Directory

The `assets/` folder receives special treatment:

- **Development Server**: Assets are served from the root path (`/`) if the directory exists and contains files
- **Production Build**: Assets are copied to the dist root (not in a subdirectory) via `CopyRspackPlugin`
- **Conditional Loading**: Assets are only processed if the directory exists and has files

Place any static files (images, fonts, etc.) in the `assets/` directory and they will be accessible from the root path in both dev and production.

#### Optimization

- `splitChunks: false` - Bundles everything into a single file
- `runtimeChunk: false` - No separate runtime chunk
- `clean: true` - Automatically cleans the dist directory before each build

#### Development Server

- Serves static files from project root
- Conditionally serves assets directory
- Gzip compression enabled
- Cache-Control headers set to `no-store` for development
- Configurable port via environment variable

#### Environment Configuration

- `.env` file support via dotenv
- `OUTPUT_FILE_NAME` - Customize output filename (default: `main.min.js`)
- `PORT` - Configure dev server port (default: `3000`)
- `NODE_ENV` - Set to `production` for production builds

## API Reference

### Methods

#### `addCommand(name, icon, callback)`

Registers a new command with the command panel.

**Parameters:**
- `name` (string) - Command name (required)
- `icon` (string|null) - Icon/emoji to display (optional)
- `callback` (function) - Function to execute (required)

**Returns:** `void`

**Example:**
```javascript
commandPanel.addCommand('My Command', '🎯', () => {
  console.log('Command executed!');
});
```

#### `on(eventName, callback)`

Listens for component events.

**Parameters:**
- `eventName` (string) - Event name (e.g., 'COMMAND-EXECUTED')
- `callback` (function) - Event handler function

**Example:**
```javascript
commandPanel.on('COMMAND-EXECUTED', (data) => {
  console.log(data.name, data.icon);
});
```

### Attributes

#### `open-keys`

Defines the keyboard shortcut to open the command panel.

**Type:** `string`  
**Default:** `"ctrl+shift+p"`

**Example:**
```html
<command-panel open-keys="alt+k"></command-panel>
```

### Events

#### `COMMAND-EXECUTED`

Fired when a command is executed.

**Event Data:**
```javascript
{
  name: string,  // Command name
  icon: string   // Command icon (or null)
}
```

## Browser Support

- Chrome/Edge 90+
- Firefox 88+
- Safari 15.4+

Requires support for:
- Custom Elements (Web Components)
- Dialog element
- ES6+ JavaScript

## Technologies

- **Rspack** - Fast bundler for development and production
- **dataroom-js** - Custom HTML elements framework
- **PostCSS** - CSS processing with cssnano optimization
- **SWC** - Fast JavaScript/TypeScript compiler

## License

MIT

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Publishing to npm

This project is configured for publishing to npm. Follow these steps to publish:

### Before First Publish

1. **Update package metadata** in `package.json`:
   - Set the package `name` (must be unique on npm)
   - Update `author` with your name and email
   - Update `repository`, `bugs`, and `homepage` URLs with your actual repository
   - Set the initial `version` (recommend starting with `0.1.0`)

2. **Verify the package contents**:
   ```bash
   npm pack --dry-run
   ```
   This shows what files will be included in the package.

3. **Test the build**:
   ```bash
   npm run build
   ```
   Ensure the `dist/` directory is created successfully.

### Publishing

1. **Login to npm** (first time only):
   ```bash
   npm login
   ```

2. **Publish the package**:
   ```bash
   npm publish
   ```
   
   The `prepublishOnly` script will automatically run the build before publishing.

### Updating the Package

1. **Update the version** using npm's version command:
   ```bash
   npm version patch  # For bug fixes (1.0.0 -> 1.0.1)
   npm version minor  # For new features (1.0.0 -> 1.1.0)
   npm version major  # For breaking changes (1.0.0 -> 2.0.0)
   ```

2. **Publish the update**:
   ```bash
   npm publish
   ```

### What Gets Published

The package includes:
- `dist/` - Built production files
- `src/` - Source JavaScript files
- `styles/` - CSS files
- `index.js`, `index.css`, `index.html` - Entry files
- `package.json` and related metadata

Development files (rspack config, build scripts, tests, etc.) are excluded via `.npmignore`.