2025-04-21 18:57:21 +02:00
< ? php
2025-07-11 14:41:34 +02:00
use Kirby\Cms\Helpers ;
2025-04-21 18:57:21 +02:00
use Kirby\Exception\InvalidArgumentException ;
use Kirby\Field\FieldOptions ;
use Kirby\Toolkit\A ;
use Kirby\Toolkit\Escape ;
use Kirby\Toolkit\Str ;
return [
'props' => [
/**
* Unset inherited props
*/
'after' => null ,
'before' => null ,
/**
* Whether to allow alpha transparency in the color
*/
'alpha' => function ( bool $alpha = false ) {
return $alpha ;
},
/**
* The CSS format ( hex , rgb , hsl ) to display and store the value
*/
'format' => function ( string $format = 'hex' ) : string {
2025-07-11 14:41:34 +02:00
if ( in_array ( $format , [ 'hex' , 'hsl' , 'rgb' ], true ) === false ) {
throw new InvalidArgumentException (
message : 'Unsupported format for color field (supported: hex, rgb, hsl)'
);
2025-04-21 18:57:21 +02:00
}
return $format ;
},
/**
* Change mode to disable the color picker ( `input` ) or to only
* show the `options` as toggles
*/
'mode' => function ( string $mode = 'picker' ) : string {
2025-07-11 14:41:34 +02:00
if ( in_array ( $mode , [ 'picker' , 'input' , 'options' ], true ) === false ) {
throw new InvalidArgumentException (
message : 'Unsupported mode for color field (supported: picker, input, options)'
);
2025-04-21 18:57:21 +02:00
}
return $mode ;
},
/**
* List of colors that will be shown as buttons
* to directly select them
*/
'options' => function ( array $options = []) : array {
return $options ;
}
],
'computed' => [
'default' => function () : string {
return Str :: lower ( $this -> default );
},
'options' => function () : array {
// resolve options to support manual arrays
// alongside api and query options
$props = FieldOptions :: polyfill ( $this -> props );
$options = FieldOptions :: factory ([
'text' => '{{ item.value }}' ,
'value' => '{{ item.key }}' ,
... $props [ 'options' ]
]);
$options = $options -> render ( $this -> model ());
if ( empty ( $options ) === true ) {
return [];
}
2025-07-11 14:41:34 +02:00
if (
2025-04-21 18:57:21 +02:00
is_numeric ( $options [ 0 ][ 'value' ]) ||
$options [ 0 ][ 'value' ] === $options [ 0 ][ 'text' ]
2025-07-11 14:41:34 +02:00
) {
// simple array of values
// or value=text (from Options class)
$options = A :: map ( $options , fn ( $option ) => [
'value' => $option [ 'text' ]
]);
} elseif ( $this -> isColor ( $options [ 0 ][ 'text' ])) {
// @deprecated 4.0.0
// TODO: Remove in Kirby 6
2025-04-21 18:57:21 +02:00
2025-07-11 14:41:34 +02:00
Helpers :: deprecated ( 'Color field "' . $this -> name . '": the text => value notation for options has been deprecated and will be removed in Kirby 6. Please rewrite your options as value => text.' );
2025-04-21 18:57:21 +02:00
2025-07-11 14:41:34 +02:00
$options = A :: map ( $options , fn ( $option ) => [
'value' => $option [ 'text' ],
// ensure that any HTML in the new text is escaped
'text' => Escape :: html ( $option [ 'value' ])
]);
} else {
$options = A :: map ( $options , fn ( $option ) => [
2025-04-21 18:57:21 +02:00
'value' => $option [ 'value' ],
'text' => $option [ 'text' ]
2025-07-11 14:41:34 +02:00
]);
}
2025-04-21 18:57:21 +02:00
return $options ;
}
],
'methods' => [
'isColor' => function ( string $value ) : bool {
return
$this -> isHex ( $value ) ||
$this -> isRgb ( $value ) ||
$this -> isHsl ( $value );
},
'isHex' => function ( string $value ) : bool {
return preg_match ( '/^#([\da-f]{3,4}){1,2}$/i' , $value ) === 1 ;
},
'isHsl' => function ( string $value ) : bool {
return preg_match ( '/^hsla?\(\s*(\d{1,3}\.?\d*)(deg|rad|grad|turn)?(?:,|\s)+(\d{1,3})%(?:,|\s)+(\d{1,3})%(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i' , $value ) === 1 ;
},
'isRgb' => function ( string $value ) : bool {
return preg_match ( '/^rgba?\(\s*(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s)+(\d{1,3})(%?)(?:,|\s|\/)*(\d*(?:\.\d+)?)(%?)\s*\)?$/i' , $value ) === 1 ;
},
],
'validations' => [
'color' => function ( $value ) {
if ( empty ( $value ) === true ) {
return true ;
}
if ( $this -> format === 'hex' && $this -> isHex ( $value ) === false ) {
2025-07-11 14:41:34 +02:00
throw new InvalidArgumentException (
key : 'validation.color' ,
data : [ 'format' => 'hex' ]
);
2025-04-21 18:57:21 +02:00
}
if ( $this -> format === 'rgb' && $this -> isRgb ( $value ) === false ) {
2025-07-11 14:41:34 +02:00
throw new InvalidArgumentException (
key : 'validation.color' ,
data : [ 'format' => 'rgb' ]
);
2025-04-21 18:57:21 +02:00
}
if ( $this -> format === 'hsl' && $this -> isHsl ( $value ) === false ) {
2025-07-11 14:41:34 +02:00
throw new InvalidArgumentException (
key : 'validation.color' ,
data : [ 'format' => 'hsl' ]
);
2025-04-21 18:57:21 +02:00
}
}
]
];