PHPackages                             arseno25/filament-privacy-blur - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Security](/categories/security)
4. /
5. arseno25/filament-privacy-blur

ActiveLibrary[Security](/categories/security)

arseno25/filament-privacy-blur
==============================

Visual privacy layer for Filament — blur and mask sensitive data in tables, forms, and infolists

v1.2.0(2mo ago)58151[2 issues](https://github.com/Arseno25/Filament-privacy-blur/issues)MITPHPPHP ^8.2CI passing

Since Mar 26Pushed 2mo agoCompare

[ Source](https://github.com/Arseno25/Filament-privacy-blur)[ Packagist](https://packagist.org/packages/arseno25/filament-privacy-blur)[ Docs](https://github.com/arseno25/filament-privacy-blur)[ GitHub Sponsors](https://github.com/Arseno25)[ RSS](/packages/arseno25-filament-privacy-blur/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (3)Dependencies (22)Versions (5)Used By (0)

 [![Filament Privacy Blur](https://camo.githubusercontent.com/a6b760d9146480d552262b811d17ac27b75cf05138c8f6f46d15eec1bb9be682/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f46696c616d656e7425323050726976616379253230426c75722e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d417273656e6f323525324666696c616d656e742d707269766163792d626c7572267061747465726e3d74656d706c65267374796c653d7374796c655f32266465736372697074696f6e3d266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313030707826696d616765733d6579652d6f6666267769647468733d38303026686569676874733d383030)](https://camo.githubusercontent.com/a6b760d9146480d552262b811d17ac27b75cf05138c8f6f46d15eec1bb9be682/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f46696c616d656e7425323050726976616379253230426c75722e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d417273656e6f323525324666696c616d656e742d707269766163792d626c7572267061747465726e3d74656d706c65267374796c653d7374796c655f32266465736372697074696f6e3d266d643d312673686f7757617465726d61726b3d3026666f6e7453697a653d313030707826696d616765733d6579652d6f6666267769647468733d38303026686569676874733d383030)
===============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#--)

 [ ![Latest Release](https://camo.githubusercontent.com/398a4f1a2e09c23b60666208fe6e83f4b5da59c1d334e72108990d5b2175d573/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f617273656e6f32352f66696c616d656e742d707269766163792d626c75723f7374796c653d666c61742d737175617265) ](https://github.com/arseno25/filament-privacy-blur/releases) [ ![Total Downloads](https://camo.githubusercontent.com/ae987a991e144302ebf4bd1948ab64d63c8aee6a9d622bda485ca4de3b848d61/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f617273656e6f32352f66696c616d656e742d707269766163792d626c75723f7374796c653d666c61742d737175617265) ](https://packagist.org/packages/arseno25/filament-privacy-blur) [ ![License](https://camo.githubusercontent.com/6ead06ca1e5b3d59e3d52c5c4508c2232b98fd902734c00ceac5b275f0ba8190/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f617273656e6f32352f66696c616d656e742d707269766163792d626c75723f7374796c653d666c61742d737175617265) ](https://github.com/arseno25/filament-privacy-blur/blob/main/LICENSE.md)

About
-----

[](#about)

**Filament Privacy Blur** provides visual privacy protection for sensitive data in Filament admin panels. It helps prevent accidental exposure during screen sharing, shoulder surfing, or working in public spaces.

### What It Does

[](#what-it-does)

- **Visual Blur** — CSS-based blur that requires user interaction to reveal
- **Data Masking** — Server-side redaction using configurable strategies (email, phone, NIK, etc.)
- **Interactive Reveal** — Click-to-reveal or hover-to-reveal with automatic re-blur
- **Global Reveal Toggle** — Eye icon in topbar to reveal all authorized fields instantly
- **Authorization-First** — Full integration with Laravel Gates, Policies, and permissions
- **Audit Logging** — Optional tracking of reveal actions with user, IP, and context
- **Export Safety** — Automatic masking during Filament exports

### What It Does NOT Do

[](#what-it-does-not-do)

This is a **visual privacy layer only**. It does NOT provide:

- Data encryption at rest or in transit
- Backend access control or API-level data redaction
- Database-level security
- Protection against determined attackers with developer tools

**Blur modes keep original data in the DOM.** For highly sensitive fields, use **mask mode** (server-side redaction) or implement data masking at your model/API layer.

Why This Package Exists
-----------------------

[](#why-this-package-exists)

When building Filament admin panels, you often need to display sensitive data (emails, salaries, phone numbers) while reducing the risk of accidental exposure during:

- Screen sharing in meetings or presentations
- Working in public spaces (cafes, coworking spaces)
- Pair programming sessions
- Client demonstrations

This package provides a convenient, authorization-aware way to add visual privacy without manually implementing blur logic for every field.

Features
--------

[](#features)

- **🔒 7 Privacy Modes** — `blur`, `blur_click`, `blur_hover`, `blur_auth`, `mask`, `hybrid`, `disabled`
- **👆 Interactive Reveal** — Click-to-reveal (auto re-blurs after 5s) or hover-to-reveal
- **👁️ Global Reveal Toggle** — Topbar button to reveal all authorized fields instantly
- **🎭 8 Mask Strategies** — email, phone, NIK, full name, API key, address, currency, generic
- **🛡️ Authorization-First** — Secure-by-default using Laravel Gates, Policies, and abilities
- **📊 Audit Logging** — Track reveal actions with user, IP address, user agent, and resource context
- **📤 Export Safety** — Automatic masking during Filament exports
- **🎛️ Per-Panel Config** — Exclude specific panels or customize settings per panel

Requirements
------------

[](#requirements)

- **PHP**: 8.2 or higher
- **Laravel**: 11 or higher
- **Filament**: v4.x or v5.x

Installation
------------

[](#installation)

```
composer require arseno25/filament-privacy-blur
```

Publish the configuration file:

```
php artisan vendor:publish --tag="filament-privacy-blur-config"
```

Publish and run the migration (for audit logging):

```
php artisan vendor:publish --tag="filament-privacy-blur-migrations"
php artisan migrate
```

Setup
-----

[](#setup)

Register the plugin in your Filament panel provider:

```
use Arseno25\FilamentPrivacyBlur\FilamentPrivacyBlurPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(
            FilamentPrivacyBlurPlugin::make()
                ->defaultMode('blur_click')
                ->blurAmount(4)
                ->exceptColumns(['id', 'created_at', 'updated_at'])
                ->exceptPanels(['public'])
                ->enableAudit()
        );
}
```

### Plugin Configuration Options

[](#plugin-configuration-options)

MethodDescriptionDefault`defaultMode(string $mode)`Default privacy mode`blur_click``blurAmount(int $amount)`CSS blur intensity (1-10)`4``exceptColumns(array $columns)`Columns to exclude from privacy`[]``exceptResources(array $resources)`Resource classes to exclude`[]``exceptPanels(array $panels)`Panel IDs to exclude`[]``enableAudit()`Enable audit loggingdisabled`showGlobalRevealToggle()`Show global reveal toggleenabled`hideGlobalRevealToggle()`Hide global reveal toggle-Quick Start
-----------

[](#quick-start)

### Blur a Table Column

[](#blur-a-table-column)

```
use Filament\Tables\Columns\TextColumn;

TextColumn::make('email')->private(),
```

### Mask a Table Column

[](#mask-a-table-column)

```
TextColumn::make('email')
    ->private()
    ->privacyMode('mask')
    ->maskUsing('email'),
```

### Reveal with Authorization

[](#reveal-with-authorization)

```
TextColumn::make('salary')
    ->private()
    ->revealIfCan('view_sensitive_data'),
```

### Protect Form Inputs

[](#protect-form-inputs)

```
use Filament\Forms\Components\TextInput;

TextInput::make('email')->private(),
```

### Protect Infolist Entries

[](#protect-infolist-entries)

```
use Filament\Infolists\Components\TextEntry;

TextEntry::make('phone')
    ->private()
    ->maskUsing('phone'),
```

### Never Reveal (Maximum Security)

[](#never-reveal-maximum-security)

```
TextEntry::make('api_key')
    ->private()
    ->revealNever()
    ->privacyMode('mask')
    ->maskUsing('api_key'),
```

How It Works
------------

[](#how-it-works)

The package makes privacy decisions server-side and renders HTML data attributes that guide frontend behavior:

- **Server-side decisions** — Authorization, mode, and reveal capability are determined server-side
- **Client-side execution** — Alpine.js respects server-rendered attributes and cannot override them
- **Secure-by-default** — Fields with `->private()` but no explicit authorization will blur for everyone and allow NO reveal
- **Blur vs Mask** — Blur modes keep original data in DOM (hidden by CSS), mask modes replace data server-side

Authorization
-------------

[](#authorization)

This package is **ability-first** — it prioritizes Laravel's built-in authorization system.

### Recommended: Ability-Based Authorization

[](#recommended-ability-based-authorization)

Use `revealIfCan()` with Laravel Gates or Policies:

```
// Using a Gate ability
Gate::define('view_ssn', function ($user, $record) {
    return $user->isAdmin() || $user->id === $record->user_id;
});

TextColumn::make('ssn')
    ->private()
    ->revealIfCan('view_ssn', $record),
```

### Custom Closure Authorization

[](#custom-closure-authorization)

```
TextColumn::make('salary')
    ->private()
    ->authorizeRevealUsing(function ($user, $record) {
        return $user?->is_admin
            || $user?->department_id === $record?->department_id;
    }),
```

### Permission-Based Authorization

[](#permission-based-authorization)

```
// Single permission
TextColumn::make('data')->private()->permission('view_data'),

// Multiple permissions (any match)
TextColumn::make('admin_field')
    ->private()
    ->visibleToPermissions(['view_admin', 'edit_admin']),
```

### Role-Based Authorization (Optional)

[](#role-based-authorization-optional)

```
// Single role
TextColumn::make('secret')->private()->visibleToRoles(['admin']),

// Multiple roles
TextColumn::make('internal')
    ->private()
    ->visibleToRoles(['admin', 'manager']),
```

### Force Blur for Specific Roles

[](#force-blur-for-specific-roles)

```
TextColumn::make('internal_notes')
    ->private()
    ->revealIfCan('view_internal')
    ->hiddenFromRoles(['guest', 'contractor']),
```

Users in these roles will always see blur, even if authorized via other means.

### Secure-by-Default in Practice

[](#secure-by-default-in-practice)

```
// ❌ This will blur for EVERYONE, NO reveal allowed
TextColumn::make('email')->private()

// ✅ Only admins can reveal
TextColumn::make('email')
    ->private()
    ->visibleToRoles(['admin'])

// ✅ Users with 'view_email' permission can reveal
TextColumn::make('email')
    ->private()
    ->permission('view_email')
```

Privacy Modes
-------------

[](#privacy-modes)

### `blur` — Always Blurred

[](#blur--always-blurred)

- **Authorized**: Plain text
- **Unauthorized**: 🔒 Blurred, no reveal
- **Raw data in DOM**: Yes

```
TextColumn::make('notes')->private()->privacyMode('blur'),
```

### `blur_click` — Click to Reveal (Default)

[](#blur_click--click-to-reveal-default)

- **Authorized**: 🔒 Blurred, click to reveal (auto re-blurs after 5s)
- **Unauthorized**: 🔒 Blurred, no click
- **Raw data in DOM**: Yes

```
TextColumn::make('email')->private()->privacyMode('blur_click'),
```

### `blur_hover` — Hover to Reveal

[](#blur_hover--hover-to-reveal)

- **Authorized**: 🔒 Blurred, hover to reveal
- **Unauthorized**: 🔒 Blurred, no hover
- **Raw data in DOM**: Yes

```
TextColumn::make('address')->private()->revealOnHover(),
```

### `blur_auth` — Blur for Unauthorized Only

[](#blur_auth--blur-for-unauthorized-only)

- **Authorized**: Plain text
- **Unauthorized**: 🔒 Blurred, no reveal
- **Raw data in DOM**: Yes

```
TextColumn::make('internal_notes')
    ->private()
    ->privacyMode('blur_auth')
    ->revealIfCan('view_internal'),
```

### `mask` — Server-Side Masking

[](#mask--server-side-masking)

- **Authorized**: Plain text
- **Unauthorized**: 🎭 Masked text (e.g., `j***e@example.com`)
- **Raw data in DOM**: No

```
TextColumn::make('email')
    ->private()
    ->privacyMode('mask')
    ->maskUsing('email'),
```

### `hybrid` — Maximum Protection

[](#hybrid--maximum-protection)

- **Authorized**: 🎭 Masked text
- **Unauthorized**: 🎭 Masked + 🔒 blurred
- **Raw data in DOM**: Masked only

```
TextColumn::make('ssn')
    ->private()
    ->privacyMode('hybrid')
    ->maskUsing('nik'),
```

### `disabled` — No Privacy

[](#disabled--no-privacy)

- **All users**: Plain text
- **Privacy effect**: None

```
TextColumn::make('public_field')->private()->privacyMode('disabled'),
```

### Mode Behavior Table

[](#mode-behavior-table)

ModeAuthorizedUnauthorizedInteractive RevealGlobal RevealRaw Data in DOM`disabled`PlainPlainN/AN/AYes`blur`Plain🔒 BlurNoNoYes`blur_click`🔒 Blur → Click🔒 BlurYes (auth only)Yes (auth only)Yes`blur_hover`🔒 Blur → Hover🔒 BlurYes (auth only)Yes (auth only)Yes`blur_auth`Plain🔒 BlurNoNoYes`mask`Plain🎭 MaskedNoNoNo`hybrid`🎭 Masked🎭 Masked + 🔒 BlurNoNoMasked onlyGlobal Reveal Toggle
--------------------

[](#global-reveal-toggle)

The global reveal toggle appears as an eye icon button in the Filament topbar.

### When Does the Toggle Appear?

[](#when-does-the-toggle-appear)

- **Shows**: When at least one field on the page can be globally revealed
- **Hides**: When no globally revealable fields exist on the current page

This happens automatically via Alpine.js — no configuration needed.

### What Can Be Globally Revealed?

[](#what-can-be-globally-revealed)

The toggle can only reveal fields that:

1. The current user is authorized to view (via `revealIfCan()`, `permission()`, etc.)
2. The field is NOT marked as `revealNever()`
3. The field is NOT in `hiddenFromRoles()` for the current user
4. The privacy mode supports global reveal (`blur_click`, `blur_hover`)

### What Cannot Be Globally Revealed?

[](#what-cannot-be-globally-revealed)

The toggle will NEVER reveal:

- ❌ Unauthorized fields (user lacks ability/permission)
- ❌ `revealNever()` fields
- ❌ `mask` mode fields (masked server-side, no blur to remove)
- ❌ `hybrid` mode fields
- ❌ Fields where user is in `hiddenFromRoles()`

### Security Guarantee

[](#security-guarantee)

The global reveal toggle **cannot bypass authorization**. Only fields where the server explicitly sets `data-privacy-can-globally-reveal="true"` will be revealed. The frontend Alpine.js code only respects server decisions.

Mask Strategies
---------------

[](#mask-strategies)

StrategyExample OutputDescription`email``j***e@example.com`Shows first char, masks middle, shows domain`phone``0812****7890`Shows prefix, masks middle digits, shows suffix`nik``3173********9012`Shows first 4 and last 4 digits`full_name``Jo** Do*`Shows first 2 and last 2 chars of each word`api_key``sk_***_key`Shows first 3 and last 3 chars`address``Jl. Sudirma***`Shows first 12 characters`currency``***`Masks currency values entirely`generic``J***h`Shows first and last character### Using Mask Strategies

[](#using-mask-strategies)

```
// Built-in strategy
TextColumn::make('email')->private()->maskUsing('email'),

// Custom closure
TextColumn::make('account_number')
    ->private()
    ->maskUsing(fn ($state) => substr($state, 0, 4) . ' ****'),
```

Audit Logging
-------------

[](#audit-logging)

When enabled, the package logs reveal actions to the `privacy_reveal_logs` table.

### When Does Audit Logging Happen?

[](#when-does-audit-logging-happen)

Audit logging occurs when:

1. Audit is enabled at plugin level (`->enableAudit()`)
2. Audit is not disabled for the specific field (`->withoutAuditReveal()`)
3. A reveal action is performed (click, hover, or global toggle)
4. The user is authorized to perform the reveal

### Stored Audit Fields

[](#stored-audit-fields)

FieldDescription`user_id`ID of the user who revealed the data`tenant_id`Tenant ID for multi-tenant apps`panel_id`Filament panel ID`resource`Resource identifier (e.g., `App\Filament\Resources\UserResource`)`page`Full URL of the page where reveal occurred`column_name`Name of the column that was revealed`record_key`Primary key of the record`reveal_mode`Privacy mode used (e.g., `blur_click`)`ip_address`IP address of the user`user_agent`Browser/user agent string`created_at`Timestamp of the reveal action### Enabling Audit Logging

[](#enabling-audit-logging)

```
FilamentPrivacyBlurPlugin::make()->enableAudit(),
```

### Per-Field Audit Control

[](#per-field-audit-control)

```
// Disable audit for specific field
TextColumn::make('public_field')
    ->private()
    ->withoutAuditReveal(),
```

Export Safety
-------------

[](#export-safety)

### Why Visual Blur is Not Safe for Exports

[](#why-visual-blur-is-not-safe-for-exports)

CSS blur only affects visual rendering in the browser. When exporting data to CSV/Excel, the original data is included unless explicitly masked.

### How Export Context is Handled

[](#how-export-context-is-handled)

The package automatically detects Filament export contexts and:

1. **Replaces blur with masking** — `blur_click` fields are masked using the configured strategy
2. **Preserves mask strategies** — Custom masking strategies are applied during export
3. **Protects sensitive data** — Original values are never included in exports

### Export Behavior Examples

[](#export-behavior-examples)

```
// In browser: Shows blurred with click-to-reveal
// In export: Shows as "j***e@example.com"
TextColumn::make('email')->private()->maskUsing('email'),

// In browser: Shows blurred with click-to-reveal
// In export: Shows as "0812****7890"
TextColumn::make('phone')->private()->maskUsing('phone'),
```

Security Limitations
--------------------

[](#security-limitations)

### Important: What This Package Does NOT Provide

[](#important-what-this-package-does-not-provide)

1. **Not Encryption** — Blur modes keep original data in the DOM
2. **Not Backend Access Control** — Does not replace API authentication
3. **Not API-Level Redaction** — Does not protect JSON API endpoints
4. **Not Database Security** — Does not encrypt data at rest

### Recommended Usage by Data Sensitivity

[](#recommended-usage-by-data-sensitivity)

Data TypeRecommended ModeReason**Email**`mask` or `blur_click`Mask for high sensitivity, blur for medium**Phone**`mask` or `blur_click`Mask for high sensitivity, blur for medium**Salary**`blur_click` with authBlur with strict authorization**SSN/Tax ID**`mask` + `revealNever()`Always mask, never reveal**API Keys**`mask` + `revealNever()`Maximum security**Internal Notes**`blur_auth` with authBlur for unauthorized, clear for authorized### For Highly Sensitive Data

[](#for-highly-sensitive-data)

Consider implementing **backend data redaction**:

- Mask data in model accessors
- Use API resources with conditional field inclusion
- Implement field-level encryption in your database
- Use Laravel's `Hidden` attribute on Eloquent models

API Reference
-------------

[](#api-reference)

### Column/Entry/Field Macros

[](#columnentryfield-macros)

#### `private()`

[](#private)

Enable privacy with default settings (equivalent to `privacyMode('blur_click')`):

```
TextColumn::make('email')->private()
```

#### `privacyMode(string $mode)`

[](#privacymodestring-mode)

Set the privacy mode:

```
TextColumn::make('salary')
    ->private()
    ->privacyMode('blur_click'),
```

Available modes: `'blur'`, `'blur_click'`, `'blur_hover'`, `'blur_auth'`, `'mask'`, `'hybrid'`, `'disabled'`

#### `revealOnClick()` / `revealOnHover()`

[](#revealonclick--revealonhover)

Convenience methods for common modes:

```
TextColumn::make('email')->revealOnClick(),
TextColumn::make('address')->revealOnHover(),
```

#### `revealNever()`

[](#revealnever)

Prevent all reveal methods:

```
TextColumn::make('api_key')->private()->revealNever(),
```

#### `blurAmount(int $amount)`

[](#bluramountint-amount)

Set CSS blur intensity (1-10):

```
TextColumn::make('salary')->private()->blurAmount(8),
```

#### `maskUsing(string|Closure $strategy)`

[](#maskusingstringclosure-strategy)

Set masking strategy:

```
TextColumn::make('email')->private()->maskUsing('email'),
TextColumn::make('custom')->private()->maskUsing(fn ($s) => $s[0] . '***'),
```

### Authorization Methods

[](#authorization-methods)

#### `revealIfCan(string $ability, Model $record = null)`

[](#revealifcanstring-ability-model-record--null)

Authorize via Laravel Gate or Policy (recommended):

```
TextColumn::make('ssn')->private()->revealIfCan('view_ssn', $record),
```

#### `authorizeRevealWith(string $ability, Model $record = null)`

[](#authorizerevealwithstring-ability-model-record--null)

Alias for `revealIfCan()` with explicit semantics:

```
TextColumn::make('notes')->private()->authorizeRevealWith('view_notes', $record),
```

#### `authorizeRevealUsing(Closure $callback)`

[](#authorizerevealusingclosure-callback)

Custom authorization closure:

```
TextColumn::make('salary')
    ->private()
    ->authorizeRevealUsing(fn ($user, $record) => $user?->id === $record->manager_id),
```

#### `permission(string $permission)`

[](#permissionstring-permission)

Require specific permission:

```
TextColumn::make('data')->private()->permission('view_data'),
```

#### `visibleToPermissions(array $permissions)`

[](#visibletopermissionsarray-permissions)

Require any of the specified permissions:

```
TextColumn::make('admin_field')
    ->private()
    ->visibleToPermissions(['view_admin', 'edit_admin']),
```

#### `visibleToRoles(array $roles)`

[](#visibletorolesarray-roles)

Require any of the specified roles:

```
TextColumn::make('secret')->private()->visibleToRoles(['admin']),
```

#### `hiddenFromRoles(array $roles)`

[](#hiddenfromrolesarray-roles)

Force blur for specific roles:

```
TextColumn::make('internal')->private()->hiddenFromRoles(['guest']),
```

### Audit Methods

[](#audit-methods)

#### `auditReveal(bool $enabled = true)`

[](#auditrevealbool-enabled--true)

Enable audit for this field:

```
TextColumn::make('salary')->private()->auditReveal(true),
```

#### `withoutAuditReveal()`

[](#withoutauditreveal)

Disable audit for this field:

```
TextColumn::make('public_field')->private()->withoutAuditReveal(),
```

### Plugin Configuration Methods

[](#plugin-configuration-methods)

#### `defaultMode(string $mode)`

[](#defaultmodestring-mode)

Set default privacy mode:

```
FilamentPrivacyBlurPlugin::make()->defaultMode('blur_click'),
```

#### `blurAmount(int $amount)`

[](#bluramountint-amount-1)

Set default blur intensity:

```
FilamentPrivacyBlurPlugin::make()->blurAmount(6),
```

#### `exceptColumns(array $columns)`

[](#exceptcolumnsarray-columns)

Exclude specific columns:

```
FilamentPrivacyBlurPlugin::make()->exceptColumns(['id', 'created_at']),
```

#### `exceptResources(array $resources)`

[](#exceptresourcesarray-resources)

Exclude specific resources:

```
FilamentPrivacyBlurPlugin::make()->exceptResources([App\Filament\Resources\PublicResource::class]),
```

#### `exceptPanels(array $panels)`

[](#exceptpanelsarray-panels)

Exclude specific panels:

```
FilamentPrivacyBlurPlugin::make()->exceptPanels(['public', 'reports']),
```

#### `enableAudit()`

[](#enableaudit)

Enable audit logging globally:

```
FilamentPrivacyBlurPlugin::make()->enableAudit(),
```

#### `showGlobalRevealToggle()` / `hideGlobalRevealToggle()`

[](#showglobalrevealtoggle--hideglobalrevealtoggle)

Control toggle visibility:

```
FilamentPrivacyBlurPlugin::make()->showGlobalRevealToggle(),
FilamentPrivacyBlurPlugin::make()->hideGlobalRevealToggle(),
```

Configuration
-------------

[](#configuration)

After publishing, edit `config/filament-privacy-blur.php`:

```
return [
    'default_mode' => 'blur_click',
    'default_blur_amount' => 4,
    'default_mask_strategy' => 'generic',
    'except_columns' => ['id', 'created_at', 'updated_at'],
    'except_resources' => [],
    'except_panels' => [],
    'audit_enabled' => false,
    'icon_trigger_enabled' => true,
];
```

Compatibility
-------------

[](#compatibility)

ComponentSupported Versions**PHP**8.2, 8.3, 8.4**Laravel**11, 12**Filament**v4.x, v5.x**Alpine.js**Bundled with Filament### Package Integration

[](#package-integration)

PackageStatusNotes**Filament Shield**✅ CompatibleWorks via Laravel Gates**Spatie Laravel Permission**✅ CompatibleWorks via `can()` method**Spatie Tenancy**✅ CompatibleTenant ID captured in audit logsContributing
------------

[](#contributing)

1. **Install dependencies**:

    ```
    composer install
    ```
2. **Run tests**:

    ```
    composer test
    ```
3. **Run static analysis**:

    ```
    composer analyse
    ```
4. **Run code style checks**:

    ```
    composer test:lint
    ```
5. **Fix code style**:

    ```
    composer lint
    ```

### Development Standards

[](#development-standards)

- **PHPStan** — Static analysis at Level 4
- **Laravel Pint** — Laravel code style fixer
- **Pest** — Testing framework

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for recent changes.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

---

**Made with ❤️ for the Filament community**

###  Health Score

43

—

FairBetter than 90% of packages

Maintenance79

Regular maintenance activity

Popularity25

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

4

Last Release

70d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/85e02cfc526f93493a12b87cc4f5f22861e7eb2a88cff97137d284d789ae700a?d=identicon)[Arseno25](/maintainers/Arseno25)

---

Top Contributors

[![Arseno25](https://avatars.githubusercontent.com/u/77256511?v=4)](https://github.com/Arseno25 "Arseno25 (70 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (3 commits)")

---

Tags

filamentfilament-pluginprivacylaravelBlurfilamentfilament-plugingdprprivacydata-maskingSensitive datafilament-privacy-blur

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/arseno25-filament-privacy-blur/health.svg)

```
[![Health](https://phpackages.com/badges/arseno25-filament-privacy-blur/health.svg)](https://phpackages.com/packages/arseno25-filament-privacy-blur)
```

###  Alternatives

[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3913.7k](/packages/rawilk-profile-filament-plugin)[croustibat/filament-jobs-monitor

Background Jobs monitoring like Horizon for all drivers for FilamentPHP

271298.4k8](/packages/croustibat-filament-jobs-monitor)[stephenjude/filament-jetstream

A Laravel starter kit built with Filament inspired by Jetstream.

17758.9k2](/packages/stephenjude-filament-jetstream)[stephenjude/filament-two-factor-authentication

Filament Two Factor Authentication: Google 2FA + Passkey Authentication

84192.9k8](/packages/stephenjude-filament-two-factor-authentication)[marcelweidum/filament-passkeys

Use passkeys in your filamentphp app

6643.3k1](/packages/marcelweidum-filament-passkeys)[wsmallnews/filament-nestedset

Filament nestedset tree builder powered by kalnoy/nestedset with Filament v4 and v5 support

196.5k14](/packages/wsmallnews-filament-nestedset)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
