feat(widgets): buttons/text-title/yiyan depth + batch15 CSS
Buttons gain zibll but/hollow/color + obs animation; text-title supports per-char entrance; yiyan wraps main-bg shell with affix/animate options.
This commit is contained in:
1 parent
a54bbee80b
commit
66ee624cb9
4 files changed
+457
-98
No files matched your search
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
/**
|
||||
* Yiyan / Hitokoto widget (zibll widget_ui_yiyan shell + aksrt_render_yiyan_block).
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
@@ -10,8 +12,6 @@ defined('ABSPATH') || exit;
|
||||
class WidgetYiyan extends \WP_Widget {
|
||||
|
||||
/**
|
||||
* Hitokoto category codes → labels (API `c` param).
|
||||
*
|
||||
* @return array<string,string>
|
||||
*/
|
||||
private static function type_labels(): array {
|
||||
@@ -32,9 +32,6 @@ class WidgetYiyan extends \WP_Widget {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize stored type to a valid Hitokoto category letter or empty.
|
||||
*/
|
||||
private static function sanitize_type(string $type): string {
|
||||
$type = strtolower(trim($type));
|
||||
return preg_match('/^[a-l]$/', $type) ? $type : '';
|
||||
@@ -44,35 +41,54 @@ class WidgetYiyan extends \WP_Widget {
|
||||
parent::__construct(
|
||||
'aksrt_yiyan',
|
||||
__('一言轮播', 'aksrt'),
|
||||
['description' => __('显示随机一言/每日语录,支持自动轮播。', 'aksrt')]
|
||||
[
|
||||
'description' => __('显示随机一言/每日语录,支持自动轮播。', 'aksrt'),
|
||||
'classname' => 'widget_aksrt_yiyan yiyan-box',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $args
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function widget($args, $instance): void {
|
||||
$title = !empty($instance['title']) ? $instance['title'] : '';
|
||||
$title = !empty($instance['title']) ? (string) $instance['title'] : '';
|
||||
$count = !empty($instance['count']) ? max(1, min(10, (int) $instance['count'])) : 5;
|
||||
$interval = !empty($instance['interval']) ? max(3, min(30, (int) $instance['interval'])) : 5;
|
||||
$type = self::sanitize_type((string) ($instance['type'] ?? ''));
|
||||
$icon = !empty($instance['icon']) ? $instance['icon'] : 'fas fa-quote-left';
|
||||
$icon = !empty($instance['icon']) ? (string) $instance['icon'] : 'fas fa-quote-left';
|
||||
$in_affix = !empty($instance['in_affix']);
|
||||
$anim = sanitize_key((string) ($instance['obs_animation'] ?? ''));
|
||||
$anim_repeat = !empty($instance['animation_repeat']);
|
||||
|
||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
if ($title) {
|
||||
if ($title !== '') {
|
||||
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
// zibll shell: theme-box + yiyan-box main-bg text-center box-body radius8 main-shadow.
|
||||
$pack = function_exists('aksrt_obs_animate_attrs')
|
||||
? aksrt_obs_animate_attrs($anim, $anim_repeat, 0)
|
||||
: ['class' => '', 'attr' => ''];
|
||||
$affix = $in_affix ? ' data-affix="true"' : '';
|
||||
$box_class = 'theme-box yiyan-box-wrap' . $pack['class'];
|
||||
|
||||
echo '<div' . $affix . ' class="' . esc_attr(trim($box_class)) . '"' . $pack['attr'] . '>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="yiyan-box main-bg text-center box-body radius8 main-shadow">';
|
||||
|
||||
if (function_exists('aksrt_render_yiyan_block')) {
|
||||
aksrt_render_yiyan_block([
|
||||
'class' => 'aksrt-yiyan',
|
||||
'class' => 'aksrt-yiyan yiyan',
|
||||
'type' => $type,
|
||||
'count' => $count,
|
||||
'interval' => $interval,
|
||||
'icon' => $icon,
|
||||
]);
|
||||
} else {
|
||||
// Fallback if single-render helpers are not loaded.
|
||||
?>
|
||||
<div class="aksrt-yiyan"
|
||||
<div class="aksrt-yiyan yiyan"
|
||||
data-aksrt-yiyan
|
||||
data-count="<?php echo esc_attr((string) $count); ?>"
|
||||
data-interval="<?php echo esc_attr((string) $interval); ?>"
|
||||
@@ -87,17 +103,21 @@ class WidgetYiyan extends \WP_Widget {
|
||||
<?php
|
||||
}
|
||||
|
||||
echo '</div></div>';
|
||||
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $instance
|
||||
*/
|
||||
public function form($instance): void {
|
||||
$title = !empty($instance['title']) ? $instance['title'] : '一言';
|
||||
$title = !empty($instance['title']) ? (string) $instance['title'] : '一言';
|
||||
$count = !empty($instance['count']) ? (int) $instance['count'] : 5;
|
||||
$interval = !empty($instance['interval']) ? (int) $instance['interval'] : 5;
|
||||
$type = self::sanitize_type((string) ($instance['type'] ?? ''));
|
||||
$icon = !empty($instance['icon']) ? $instance['icon'] : 'fas fa-quote-left';
|
||||
$icon = !empty($instance['icon']) ? (string) $instance['icon'] : 'fas fa-quote-left';
|
||||
$labels = self::type_labels();
|
||||
// Curated subset for the form (full map still used for sanitization).
|
||||
$form_types = ['', 'a', 'd', 'i', 'k', 'h', 'j'];
|
||||
?>
|
||||
<p>
|
||||
@@ -135,16 +155,37 @@ class WidgetYiyan extends \WP_Widget {
|
||||
name="<?php echo esc_attr($this->get_field_name('icon')); ?>" type="text"
|
||||
value="<?php echo esc_attr($icon); ?>">
|
||||
</p>
|
||||
<p>
|
||||
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('in_affix')); ?>" value="1" <?php checked(!empty($instance['in_affix'])); ?>> <?php esc_html_e('侧栏随动', 'aksrt'); ?></label>
|
||||
</p>
|
||||
<p>
|
||||
<label><?php esc_html_e('入场动画', 'aksrt'); ?>
|
||||
<select name="<?php echo esc_attr($this->get_field_name('obs_animation')); ?>">
|
||||
<option value="" <?php selected(($instance['obs_animation'] ?? ''), ''); ?>><?php esc_html_e('无', 'aksrt'); ?></option>
|
||||
<option value="fade" <?php selected(($instance['obs_animation'] ?? ''), 'fade'); ?>><?php esc_html_e('淡入', 'aksrt'); ?></option>
|
||||
<option value="slideup" <?php selected(($instance['obs_animation'] ?? ''), 'slideup'); ?>><?php esc_html_e('上滑', 'aksrt'); ?></option>
|
||||
<option value="zoomin" <?php selected(($instance['obs_animation'] ?? ''), 'zoomin'); ?>><?php esc_html_e('放大', 'aksrt'); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,mixed> $new_instance
|
||||
* @param array<string,mixed> $old_instance
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function update($new_instance, $old_instance): array {
|
||||
$instance = [];
|
||||
$instance['title'] = sanitize_text_field($new_instance['title'] ?? '');
|
||||
$instance['count'] = max(1, min(10, absint($new_instance['count'] ?? 5)));
|
||||
$instance['interval'] = max(3, min(30, absint($new_instance['interval'] ?? 5)));
|
||||
$instance['type'] = self::sanitize_type((string) ($new_instance['type'] ?? ''));
|
||||
$instance['icon'] = sanitize_text_field($new_instance['icon'] ?? 'fas fa-quote-left');
|
||||
return $instance;
|
||||
return [
|
||||
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
||||
'count' => max(1, min(10, absint($new_instance['count'] ?? 5))),
|
||||
'interval' => max(3, min(30, absint($new_instance['interval'] ?? 5))),
|
||||
'type' => self::sanitize_type((string) ($new_instance['type'] ?? '')),
|
||||
'icon' => sanitize_text_field((string) ($new_instance['icon'] ?? 'fas fa-quote-left')),
|
||||
'in_affix' => !empty($new_instance['in_affix']) ? 1 : 0,
|
||||
'obs_animation' => sanitize_key((string) ($new_instance['obs_animation'] ?? '')),
|
||||
'animation_repeat' => !empty($new_instance['animation_repeat']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user