Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
create-powergrid-plugin
power-components/livewire-powergrid
claude-code
powergrid
alpinejs
livewire
blade-views
service-provider
theme-tokens
plugins

Create a complete PowerGrid plugin from scratch, including PHP class, Column macro, Blade view, Alpine.js component, and registration.

Install
php artisan boost:add-skill power-components/livewire-powergrid

Save this content to: .claude/skills/create-powergrid-plugin/SKILL.md

## What I do

Scaffold a complete external PowerGrid plugin in the user's project (NOT in the package).

## When to use me

- A new interactive column behavior is needed (e.g., selectable, colorpicker, rating)
- The behavior requires its own Blade view and/or Alpine.js component
- The plugin needs to respond to user interactions via Livewire events

## Quick Overview

Plugins are created in the user's project at `app/PowerGrid/Plugins/{PluginName}/`.
They do NOT require modifying the PowerGrid package.

### Files to create:

1. `app/PowerGrid/Plugins/{PluginName}/{PluginName}Plugin.php` - Plugin class
2. `app/PowerGrid/Plugins/{PluginName}/index.blade.php` - Blade template
3. `app/PowerGrid/Plugins/{PluginName}/index.js` - Alpine.js component
4. `app/Providers/PowerGridPluginServiceProvider.php` - ServiceProvider

### Files to modify:

1. `bootstrap/providers.php` - Register the ServiceProvider
2. `app/Providers/AppServiceProvider.php` - Add plugin to `PowerGrid::plugins([...])`
3. User's PowerGrid component - Add column + hook method

## Critical Rules

1. **Create plugins in user's project**, never in the powergrid package
2. **ServiceProvider must call `boot()`** and register view namespace with `loadViewsFrom()`
3. **Alpine.js dispatch must use array format**: `[field, id, value]` (NOT object `{field, id, value}`)
4. **Render initial values server-side** with `@foreach`/`@selected()` - do NOT use `x-model` for initial state
5. **Model `$fillable` must include** the field being updated
6. **No proxy method needed** - `pgPluginListener` in Listeners.php handles routing generically
7. **Theme-aware markup uses tokens, not `instanceof`.** Contribute classes via `PluginBase::themeTokens()`; resolve views with `theme_view($alias)` and fall back to `powergrid-plugins::{PluginName}.themes.*`.

## Theme-aware plugins

Plugins can inject CSS-class tokens and ship theme-aware Blade without theme conditionals.

**`PluginBase::themeTokens()`** is merged into every theme in `Theme::resolveTokens()` (after the theme's own section methods, before `config('livewire-powergrid.theme_overrides')`). It is a raw array (not run through `HasProperties::toArray()`), so keys must already be snake_cased. The `tabs` group (`list` / `tab` / `tab_active` / `tab_inactive` / `badge` / `badge_active` / `badge_inactive` / optional `view`) is the first real example of a plugin-shaped token surface:

```php
public static function themeTokens(): array
{
    return [
        'my_plugin' => [
            'wrapper' => 'flex items-center gap-2',
            'button'  => 'rounded-md px-2 py-1 text-sm',
        ],
    ];
}
```

**View resolution** follows `src/Plugins/FilterBuilder/FilterBuilderPlugin.php::resolveThemeView()` (and `HasTabs::tabsView()`): try `theme_view($alias)`, then fall back to a packaged `powergrid-plugins::` view. Flux-style themes select a different blade by setting a `*.view` token (e.g. Flux `tabs.view` → `powergrid-plugins::Tabs.themes.flux`); do not branch on `instanceof DaisyUI` / `instanceof Flux` in new plugins.

```php
private function resolveThemeView(): string
{
    $tokenView = theme_view('header.my_plugin'); // or 'tabs', 'header.export', ...

    if ($tokenView !== '' && view()->exists($tokenView)) {
        return $tokenView;
    }

    $fallback = 'powergrid-plugins::{PluginName}.themes.index';

    return view()->exists($fallback) ? $fallback : '';
}
```

Ship one shared token-driven blade (Tabs: `resources/views/components/themes/tailwind/tabs.blade.php` reads `theme('tabs.*')`) and only add a `themes/flux.blade.php` (etc.) when the HTML genuinely differs.

See `REFERENCE.md` for the full `themeTokens()` / `resolveThemeView()` templates.

## Workflow

1. Gather requirements (plugin name, macro signature, interaction type, hook name)
2. Read `REFERENCE.md` in this skill directory for templates and full details
3. Create the plugin files following the templates
4. Register ServiceProvider and plugin
5. Add column + hook to user's component
6. Verify it works

For complete templates, architecture details, and troubleshooting, see:
`REFERENCE.md`

What I do

Scaffold a complete external PowerGrid plugin in the user's project (NOT in the package).

When to use me

  • A new interactive column behavior is needed (e.g., selectable, colorpicker, rating)
  • The behavior requires its own Blade view and/or Alpine.js component
  • The plugin needs to respond to user interactions via Livewire events

Quick Overview

Plugins are created in the user's project at app/PowerGrid/Plugins/{PluginName}/. They do NOT require modifying the PowerGrid package.

Files to create:

  1. app/PowerGrid/Plugins/{PluginName}/{PluginName}Plugin.php - Plugin class
  2. app/PowerGrid/Plugins/{PluginName}/index.blade.php - Blade template
  3. app/PowerGrid/Plugins/{PluginName}/index.js - Alpine.js component
  4. app/Providers/PowerGridPluginServiceProvider.php - ServiceProvider

Files to modify:

  1. bootstrap/providers.php - Register the ServiceProvider
  2. app/Providers/AppServiceProvider.php - Add plugin to PowerGrid::plugins([...])
  3. User's PowerGrid component - Add column + hook method

Critical Rules

  1. Create plugins in user's project, never in the powergrid package
  2. ServiceProvider must call boot() and register view namespace with loadViewsFrom()
  3. Alpine.js dispatch must use array format: [field, id, value] (NOT object {field, id, value})
  4. Render initial values server-side with @foreach/@selected() - do NOT use x-model for initial state
  5. Model $fillable must include the field being updated
  6. No proxy method needed - pgPluginListener in Listeners.php handles routing generically
  7. Theme-aware markup uses tokens, not instanceof. Contribute classes via PluginBase::themeTokens(); resolve views with theme_view($alias) and fall back to powergrid-plugins::{PluginName}.themes.*.

Theme-aware plugins

Plugins can inject CSS-class tokens and ship theme-aware Blade without theme conditionals.

PluginBase::themeTokens() is merged into every theme in Theme::resolveTokens() (after the theme's own section methods, before config('livewire-powergrid.theme_overrides')). It is a raw array (not run through HasProperties::toArray()), so keys must already be snake_cased. The tabs group (list / tab / tab_active / tab_inactive / badge / badge_active / badge_inactive / optional view) is the first real example of a plugin-shaped token surface:

public static function themeTokens(): array
{
    return [
        'my_plugin' => [
            'wrapper' => 'flex items-center gap-2',
            'button'  => 'rounded-md px-2 py-1 text-sm',
        ],
    ];
}

View resolution follows src/Plugins/FilterBuilder/FilterBuilderPlugin.php::resolveThemeView() (and HasTabs::tabsView()): try theme_view($alias), then fall back to a packaged powergrid-plugins:: view. Flux-style themes select a different blade by setting a *.view token (e.g. Flux tabs.view → powergrid-plugins::Tabs.themes.flux); do not branch on instanceof DaisyUI / instanceof Flux in new plugins.

private function resolveThemeView(): string
{
    $tokenView = theme_view('header.my_plugin'); // or 'tabs', 'header.export', ...

    if ($tokenView !== '' && view()->exists($tokenView)) {
        return $tokenView;
    }

    $fallback = 'powergrid-plugins::{PluginName}.themes.index';

    return view()->exists($fallback) ? $fallback : '';
}

Ship one shared token-driven blade (Tabs: resources/views/components/themes/tailwind/tabs.blade.php reads theme('tabs.*')) and only add a themes/flux.blade.php (etc.) when the HTML genuinely differs.

See REFERENCE.md for the full themeTokens() / resolveThemeView() templates.

Workflow

  1. Gather requirements (plugin name, macro signature, interaction type, hook name)
  2. Read REFERENCE.md in this skill directory for templates and full details
  3. Create the plugin files following the templates
  4. Register ServiceProvider and plugin
  5. Add column + hook to user's component
  6. Verify it works

For complete templates, architecture details, and troubleshooting, see: REFERENCE.md

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
takashato/laravel-vietqr
aitor24/laralang
kraenzle-ritter/entity-relations
dindigital/din-image
pomirleanu/image-colors
sawmainek/laravel-api-generator
delatbabel/jsonresponses
mouhamedfd/permissions-generator
eduplus/qr
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json