|
3 | 3 | namespace SolutionForest\InspireCms\Fields\Configs; |
4 | 4 |
|
5 | 5 | use Filament\Forms; |
6 | | -use Illuminate\Support\Str; |
7 | 6 | use SolutionForest\FilamentFieldGroup\FieldTypes\Configs\Attributes\ConfigName; |
8 | 7 | use SolutionForest\FilamentFieldGroup\FieldTypes\Configs\Attributes\DbType; |
9 | 8 | use SolutionForest\FilamentFieldGroup\FieldTypes\Configs\Attributes\FormComponent; |
10 | 9 | use SolutionForest\FilamentFieldGroup\FieldTypes\Configs\Contracts\FieldTypeConfig; |
11 | 10 | use SolutionForest\FilamentFieldGroup\FieldTypes\Configs\FieldTypeBaseConfig; |
12 | 11 | use SolutionForest\InspireCms\Fields\Configs\Attributes\Converter; |
| 12 | +use SolutionForest\InspireCms\Fields\Configs\Attributes\Translatable; |
| 13 | +use SolutionForest\InspireCms\Fields\Configs\Concerns\HasInnerField; |
13 | 14 | use SolutionForest\InspireCms\Fields\Converters\RepeaterConverter; |
14 | 15 | use SolutionForest\InspireCms\Helpers\FieldTypeHelper; |
15 | 16 |
|
|
18 | 19 | #[DbType('mysql', 'text')] |
19 | 20 | #[DbType('sqlite', 'text')] |
20 | 21 | #[Converter(RepeaterConverter::class)] |
| 22 | +#[Translatable(false)] |
21 | 23 | class Repeater extends FieldTypeBaseConfig implements FieldTypeConfig |
22 | 24 | { |
23 | | - public array $fields = []; |
24 | | - |
25 | | - public function getFormSchema(): array |
26 | | - { |
27 | | - $exceptsInnerFields = [ |
28 | | - 'repeater', |
29 | | - ]; |
| 25 | + use HasInnerField; |
30 | 26 |
|
31 | | - $getItemKeyForRepeaterAction = fn (array $arguments): string => $arguments['item']; |
32 | | - |
33 | | - $getItemStateForRepeaterAction = fn (array $arguments, Forms\Components\Repeater $component): array => $component->getRawItemState($getItemKeyForRepeaterAction($arguments)); |
| 27 | + public array $fields = []; |
34 | 28 |
|
35 | | - $getFieldForRepeaterAction = fn (array $arguments, Forms\Components\Repeater $component): ?string => $getItemStateForRepeaterAction($arguments, $component)['field'] ?? null; |
| 29 | + public bool $collapsible = false; |
36 | 30 |
|
37 | | - $getFieldIconForRepeaterAction = function (array $arguments, Forms\Components\Repeater $component) use ($getFieldForRepeaterAction): ?string { |
38 | | - if (($field = $getFieldForRepeaterAction($arguments, $component)) && ($icons = FieldTypeHelper::getFieldTypeIcon($field))) { |
39 | | - return is_array($icons) ? $icons[0] : $icons; |
40 | | - } |
41 | | - |
42 | | - return null; |
43 | | - }; |
| 31 | + public bool $cloneable = false; |
44 | 32 |
|
| 33 | + public function getFormSchema(): array |
| 34 | + { |
45 | 35 | return [ |
46 | | - Forms\Components\Repeater::make('fields') |
47 | | - ->columnSpanFull() |
48 | | - ->collapsible() |
49 | | - ->itemLabel(fn (array $state): ?string => $state['name'] ?? null) |
50 | | - ->addActionLabel('Add Field') |
51 | | - ->schema(function ($state) use ($exceptsInnerFields) { |
52 | | - return [ |
53 | | - Forms\Components\Hidden::make('fieldConfig')->dehydrated()->dehydrateStateUsing(fn ($state) => $state ?? []), |
54 | | - Forms\Components\Select::make('field') |
55 | | - ->options(fn () => FieldTypeHelper::getFieldTypeOptions(excepts: $exceptsInnerFields)) |
56 | | - ->getSearchResultsUsing(fn ($search) => FieldTypeHelper::getFieldTypeOptions($search, excepts: $exceptsInnerFields)) |
57 | | - ->searchable()->allowHtml() |
58 | | - ->required() |
59 | | - ->live() |
60 | | - // todo: add translation |
61 | | - ->hintIcon('heroicon-o-information-circle', 'Resetting the field type will clear the field configuration.') |
62 | | - ->afterStateUpdated(function ($old, $state, $set) { |
63 | | - if ($old !== $state) { |
64 | | - $set('fieldConfig', []); |
65 | | - } |
66 | | - }), |
67 | | - Forms\Components\TextInput::make('label') |
68 | | - ->required() |
69 | | - ->helperText('Label for the field') |
70 | | - ->live()->afterStateUpdated(fn ($state, $set) => $state ? $set('name', Str::slug($state)) : null), |
71 | | - Forms\Components\TextInput::make('name') |
72 | | - ->required() |
73 | | - ->helperText('Unique name for the field'), |
74 | | - Forms\Components\TextInput::make('helperText'), |
75 | | - Forms\Components\Toggle::make('isRequired') |
76 | | - ->label('Is Required?') |
77 | | - ->default(false), |
78 | | - ]; |
79 | | - }) |
80 | | - ->defaultItems(1) |
81 | | - ->extraItemActions([ |
82 | | - Forms\Components\Actions\Action::make('editConfig') |
83 | | - ->icon('heroicon-s-cog-8-tooth') |
84 | | - ->slideOver() |
85 | | - // todo: add translation |
86 | | - ->modalHeading(fn (array $arguments, Forms\Components\Repeater $component) => str_replace([':field'], [$getFieldForRepeaterAction($arguments, $component) ?? 'Field'], 'Edit :field configuration')) |
87 | | - ->modalIcon(fn (array $arguments, Forms\Components\Repeater $component) => $getFieldIconForRepeaterAction($arguments, $component)) |
88 | | - ->disabled(fn (array $arguments, Forms\Components\Repeater $component) => empty($getFieldForRepeaterAction($arguments, $component))) |
89 | | - ->form( |
90 | | - fn (Forms\Form $form, array $arguments, Forms\Components\Repeater $component) => $form |
91 | | - ->schema(FieldTypeHelper::getRepeaterFieldConfigSchemaForFieldType($getFieldForRepeaterAction($arguments, $component))) |
92 | | - ) |
93 | | - ->fillForm(function (array $arguments, Forms\Components\Repeater $component) use ($getItemStateForRepeaterAction) { |
94 | | - $existingFieldConfig = $getItemStateForRepeaterAction($arguments, $component)['fieldConfig']; |
95 | | - if (! empty($existingFieldConfig)) { |
96 | | - return $existingFieldConfig; |
97 | | - } |
98 | | - }) |
99 | | - ->action(function (array $data, array $arguments, Forms\Components\Repeater $component) use ($getItemKeyForRepeaterAction) { |
100 | | - |
101 | | - $itemKey = $getItemKeyForRepeaterAction($arguments); |
102 | | - |
103 | | - $itemState = $component->getRawItemState($itemKey); |
104 | | - |
105 | | - $itemState['fieldConfig'] = $data; |
106 | | - |
107 | | - $component->getChildComponentContainer($itemKey)->fill($itemState); |
108 | | - |
109 | | - $component->collapsed(false, shouldMakeComponentCollapsible: false); |
110 | | - |
111 | | - $component->callAfterStateUpdated(); |
112 | | - }), |
| 36 | + Forms\Components\Tabs::make('tabs') |
| 37 | + ->tabs([ |
| 38 | + Forms\Components\Tabs\Tab::make('Presentation') |
| 39 | + ->schema([ |
| 40 | + Forms\Components\Toggle::make('collapsible'), |
| 41 | + Forms\Components\Toggle::make('cloneable'), |
| 42 | + ]), |
| 43 | + Forms\Components\Tabs\Tab::make('Fields') |
| 44 | + ->schema([ |
| 45 | + static::getHasInnerFieldComponent()->hiddenLabel(), |
| 46 | + ]), |
113 | 47 | ]), |
114 | 48 | ]; |
115 | 49 | } |
@@ -140,6 +74,10 @@ public function applyConfig(Forms\Components\Component $component): void |
140 | 74 | ); |
141 | 75 | } |
142 | 76 | $component->schema(array_filter($components)); |
| 77 | + |
| 78 | + $component->collapsible($this->collapsible); |
| 79 | + |
| 80 | + $component->cloneable($this->cloneable); |
143 | 81 | } |
144 | 82 | } |
145 | 83 | } |
0 commit comments