Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
c2e23a2
initial commit
AzGasim Jun 15, 2026
574b043
Fix styling
AzGasim Jun 15, 2026
5b2926e
validation
AzGasim Jun 15, 2026
dcbd5ca
Fix styling
AzGasim Jun 15, 2026
ff28baf
new fieldtypes
AzGasim Jun 16, 2026
429b88a
Fix styling
AzGasim Jun 16, 2026
3486439
Purge custom field values when a field group is deleted
AzGasim Jun 17, 2026
727ebe0
new fields
AzGasim Jun 17, 2026
9cab163
repeater, groups, tabs
AzGasim Jun 17, 2026
a36b14b
validation
AzGasim Jun 17, 2026
97afebe
Fix styling
AzGasim Jun 17, 2026
52b89ee
Fix styling
AzGasim Jun 17, 2026
b08e27d
flexible layout
AzGasim Jun 17, 2026
63efaef
Fix styling
AzGasim Jun 17, 2026
4f241d0
Update README
AzGasim Jun 23, 2026
fef75f3
mprove builder MVP: tabs, validation, value migration, and admin UX
AzGasim Jun 24, 2026
4a6e0b5
fix fields
AzGasim Jun 24, 2026
58b7861
fix color field
AzGasim Jun 24, 2026
0cc18c7
fix date picker
AzGasim Jun 24, 2026
10f3b11
fix date time picker
AzGasim Jun 24, 2026
f82b9b1
fix email field
AzGasim Jun 24, 2026
1144d5d
fix flexible content field
AzGasim Jun 24, 2026
29e9d8c
fix group field
AzGasim Jun 24, 2026
0c260ba
Fix styling
AzGasim Jun 24, 2026
79799cc
fix link field
AzGasim Jun 24, 2026
8e92acf
Fix styling
AzGasim Jun 24, 2026
d9a8a14
fix message field
AzGasim Jun 24, 2026
c648789
fix number field
AzGasim Jun 24, 2026
cd260fd
fix password field
AzGasim Jun 24, 2026
5b2af05
fix radio button field
AzGasim Jun 24, 2026
f9a4dc3
fix range field
AzGasim Jun 24, 2026
7012c6a
fix repeater field
AzGasim Jun 24, 2026
ac03fb0
Fix styling
AzGasim Jun 24, 2026
041cf44
fix rich text field
AzGasim Jun 24, 2026
194e8e9
fix select field
AzGasim Jun 24, 2026
6c3a6f4
fix tab field
AzGasim Jun 24, 2026
6599d32
fix time field
AzGasim Jun 25, 2026
f202cd4
Fix styling
AzGasim Jun 25, 2026
8a43c3b
fix toggle field
AzGasim Jun 25, 2026
a574504
fix embed field
AzGasim Jun 25, 2026
b21b47f
Fix styling
AzGasim Jun 25, 2026
fe853ea
fix default value
AzGasim Jun 25, 2026
7071947
Add InteractsWithCustomFields for native model custom field access an…
AzGasim Jun 25, 2026
1222633
Fix styling
AzGasim Jun 25, 2026
044fad6
Add image custom field with media picker and usage tracking
AzGasim Jun 26, 2026
4e5f4ff
Fix styling
AzGasim Jun 26, 2026
e84a14e
Add gallery custom field with scoped media validation and picker isol…
AzGasim Jun 26, 2026
4e62f90
Fix styling
AzGasim Jun 26, 2026
7d78245
Add file custom field and scope media picker lists by mime type
AzGasim Jun 26, 2026
4e3351e
update README
AzGasim Jun 26, 2026
dc81b81
update readme
AzGasim Jun 29, 2026
f1a2111
Add locale-aware translations for builder field definitions and values.
AzGasim Jul 1, 2026
824a865
Wire admin locale automatically for HasCustomFields resources.
AzGasim Jul 1, 2026
34aaacb
Gate custom field value locales by entity translatability
AzGasim Jul 2, 2026
6dc6bea
Fix styling
AzGasim Jul 2, 2026
c3edc17
Make moox/builder integration optional via core bridge traits Consum…
AzGasim Jul 2, 2026
76645b2
make builder optional
AzGasim Jul 2, 2026
d668945
Add configurable custom field table columns
AzGasim Jul 2, 2026
b6b18a1
Add per-context visibility for builder fields and groups
AzGasim Jul 2, 2026
22dc979
Add field group placement, layout widths and section markers
AzGasim Jul 2, 2026
59e1d23
Improve field builder UX in FieldGroupResource
AzGasim Jul 2, 2026
400888b
Add per-group column layout for field groups
AzGasim Jul 2, 2026
ac53f41
Add relation field type with entity linking, validation, and table co…
AzGasim Jul 3, 2026
0960cf4
Add conditional logic for builder field visibility
AzGasim Jul 3, 2026
07fc79a
Fix narrow tab rendering in compiled custom field forms
AzGasim Jul 3, 2026
d603721
Harden builder custom fields and trim dead code
AzGasim Jul 6, 2026
8c2c37c
update readme
AzGasim Jul 6, 2026
46cac70
Sanitize TipTap JSON rich text on persist via Filament
AzGasim Jul 6, 2026
2cd3c74
Add field group definition import/export in admin
AzGasim Jul 6, 2026
8fd913c
Fix styling
AzGasim Jul 6, 2026
c7979d1
Add sortable and searchable relation field table columns
AzGasim Jul 6, 2026
858ca1a
Align field hint icons beside labels in admin forms
AzGasim Jul 6, 2026
4b712f9
Refine builder location conditions
AzGasim Jul 7, 2026
007d8c9
Improve builder field validation
AzGasim Jul 7, 2026
6b57253
Fix styling
AzGasim Jul 7, 2026
eeaf3d8
improve color field
AzGasim Jul 7, 2026
710a4c1
Fix styling
AzGasim Jul 7, 2026
369116c
Refine builder table columns
AzGasim Jul 7, 2026
a581a1e
Fix stale assignment conditions when target entities change
AzGasim Jul 7, 2026
d25f33a
Harden builder definition imports
AzGasim Jul 7, 2026
2726f27
Improve builder condition editor feedback
AzGasim Jul 7, 2026
f761944
Fix styling
AzGasim Jul 7, 2026
9c33649
Refine builder conditions and validation workflows
AzGasim Jul 7, 2026
b2535fd
Fix styling
AzGasim Jul 7, 2026
e47d334
Reduce builder query load for field groups and custom field resources.
AzGasim Jul 8, 2026
ec6cb0e
Fix location rules when record params are missing
AzGasim Jul 8, 2026
5cc939e
Harden builder validation rules and remove dead field-type APIs
AzGasim Jul 9, 2026
e3ac62c
Add Quick Start onboarding section to builder README
AzGasim Jul 9, 2026
2a13ced
Remove deprecated ReflectionProperty::setAccessible call
AzGasim Jul 9, 2026
bdcfd6e
Skip Swiss German (gsw) variant during static data import
AzGasim Jul 9, 2026
b160f0b
Clean up user-session install defaults
AzGasim Jul 9, 2026
23ea5e2
Add comprehensive builder test suite for custom fields runtime
AzGasim Jul 9, 2026
be03462
Fix styling
AzGasim Jul 9, 2026
3170e90
Fix relation picker labels for translation-backed targets
AzGasim Jul 9, 2026
b41948c
Document relation label resolution in builder README
AzGasim Jul 9, 2026
df26ecc
Fix relation column search for translation-backed targets
AzGasim Jul 9, 2026
45ddf1e
Fix styling
AzGasim Jul 9, 2026
272045a
fix data import job
AzGasim Jul 9, 2026
344e97a
Add record_status location rule for custom field groups
AzGasim Jul 10, 2026
6318ad0
Fix styling
AzGasim Jul 10, 2026
ff66403
Fix empty taxonomy term options in location rule value select
AzGasim Jul 10, 2026
6cd0e18
Add opt-in table filters for custom field list views
AzGasim Jul 13, 2026
c139365
Fix styling
AzGasim Jul 13, 2026
bb4f2bc
update readme and use more name field options
AzGasim Jul 14, 2026
16c607f
Fix styling
AzGasim Jul 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/builder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor
.phpunit.result.cache
composer.lock
1,180 changes: 1,180 additions & 0 deletions packages/builder/README.md

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions packages/builder/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"name": "moox/builder",
"description": "Runtime custom field groups for Filament resources with typed value storage.",
"keywords": [
"Moox",
"Laravel",
"Filament",
"Moox package",
"Laravel package",
"Custom fields"
],
"homepage": "https://moox.org/docs/builder",
"license": "MIT",
"authors": [
{
"name": "Moox Developer",
"email": "dev@moox.org",
"role": "Developer"
}
],
"require": {
"moox/core": "dev-main"
},
"autoload": {
"psr-4": {
"Moox\\Builder\\": "src",
"Moox\\Builder\\Database\\Seeders\\": "database/seeders"
}
},
"autoload-dev": {
"psr-4": {
"Moox\\Builder\\Tests\\": "tests/",
"Moox\\Builder\\Tests\\Support\\": "tests/Support/"
}
},
"extra": {
"laravel": {
"providers": [
"Moox\\Builder\\BuilderServiceProvider"
]
},
"moox": {
"name": "Moox Builder",
"stability": "stable",
"type": "moox-plugin",
"install": {
"auto_migrate": "database/migrations",
"seed": "database/seeders/BuilderSeeder.php",
"auto_publish": "builder-config",
"plugins": [
"Moox\\Builder\\Plugins\\BuilderPlugin"
]
},
"update": {
"migrate": "database/migrations",
"merge": "builder-config"
},
"uninstall": {
"migrate": "database/migrations",
"remove": "builder-config"
}
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"moox/devtools": "dev-main",
"pestphp/pest": "^4.7",
"pestphp/pest-plugin-livewire": "^4.0"
},
"scripts": {
"test": [
"@php ../../vendor/bin/pest"
],
"format": [
"@php ../../vendor/bin/pint"
]
},
"config": {
"allow-plugins": {
"pestphp/pest-plugin": true
}
}
}
8 changes: 8 additions & 0 deletions packages/builder/config/builder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

declare(strict_types=1);

return [
'navigation_group' => env('BUILDER_NAVIGATION_GROUP', 'Felder'),
'default_locale' => env('BUILDER_DEFAULT_LOCALE', 'en_US'),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_group_translations', function (Blueprint $table): void {
$table->id();
$table->foreignId('field_group_id')->constrained('builder_field_groups')->cascadeOnDelete();
$table->string('locale');
$table->string('name');
$table->timestamps();

$table->unique(['field_group_id', 'locale']);
$table->index('locale');
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_group_translations');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_groups', function (Blueprint $table): void {
$table->id();
$table->ulid('ulid')->unique();
$table->string('name');
$table->string('slug')->unique();
$table->json('location_rules');
$table->string('placement')->default('default');
$table->json('settings')->nullable();
$table->integer('sort')->default(0);
$table->boolean('active')->default(true);
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_groups');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_option_translations', function (Blueprint $table): void {
$table->id();
$table->foreignId('field_option_id')->constrained('builder_field_options')->cascadeOnDelete();
$table->string('locale');
$table->string('label');
$table->timestamps();

$table->unique(['field_option_id', 'locale']);
$table->index('locale');
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_option_translations');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_options', function (Blueprint $table): void {
$table->id();
$table->ulid('ulid')->unique();
$table->foreignId('field_id')->constrained('builder_fields')->cascadeOnDelete();
$table->string('label');
$table->string('value');
$table->integer('sort')->default(0);
$table->timestamps();
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_options');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_translations', function (Blueprint $table): void {
$table->id();
$table->foreignId('field_id')->constrained('builder_fields')->cascadeOnDelete();
$table->string('locale');
$table->string('label');
$table->json('config')->nullable();
$table->timestamps();

$table->unique(['field_id', 'locale']);
$table->index('locale');
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_translations');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_field_values', function (Blueprint $table): void {
$table->id();
$table->string('entity');
$table->unsignedBigInteger('record_id');
$table->string('field_name');
$table->string('locale')->default('en_US');
$table->string('value_string')->nullable();
$table->text('value_text')->nullable();
$table->decimal('value_decimal', 20, 6)->nullable();
$table->date('value_date')->nullable();
$table->dateTime('value_datetime')->nullable();
$table->boolean('value_boolean')->nullable();
$table->json('value_json')->nullable();
$table->timestamps();

$table->unique(['entity', 'record_id', 'field_name', 'locale']);
$table->index(['entity', 'record_id', 'locale']);
$table->index(['entity', 'field_name', 'value_decimal']);
$table->index(['entity', 'field_name', 'value_date']);
$table->index(['entity', 'field_name', 'value_datetime']);
$table->index(['entity', 'record_id']);
});
}

public function down(): void
{
Schema::dropIfExists('builder_field_values');
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::create('builder_fields', function (Blueprint $table): void {
$table->id();
$table->ulid('ulid')->unique();
$table->foreignId('field_group_id')->constrained('builder_field_groups')->cascadeOnDelete();
$table->foreignId('parent_field_id')->nullable()->constrained('builder_fields')->nullOnDelete();
$table->string('name');
$table->string('label');
$table->string('type');
$table->json('config')->nullable();
$table->json('validation')->nullable();
$table->json('conditional_logic')->nullable();
$table->json('settings')->nullable();
$table->integer('sort')->default(0);
$table->timestamps();

$table->unique(['field_group_id', 'name']);
});
}

public function down(): void
{
Schema::dropIfExists('builder_fields');
}
};
Loading
Loading