From 35c1324824d4830fd2e4406f0008221f70991dcf Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 4 Jun 2026 20:23:37 -0400 Subject: [PATCH] feat(badges): rainbow animation option for punch-out hole markers Adds left/right/center_rainbow to punch_holes cfg_json. When enabled, applies a CSS hue-rotate animation (2.5s loop) to the marker div using a saturated red base color so the full visible spectrum appears. Template form shows a Rainbow checkbox per slot; hides color pickers when active. Co-Authored-By: Claude Sonnet 4.6 --- .../ae_events/types/ae_badge_template_cfg.ts | 7 +- .../[badge_id]/ae_comp__badge_obj_view.svelte | 34 +++++-- .../ae_comp__badge_template_form.svelte | 89 +++++++++++-------- 3 files changed, 87 insertions(+), 43 deletions(-) diff --git a/src/lib/ae_events/types/ae_badge_template_cfg.ts b/src/lib/ae_events/types/ae_badge_template_cfg.ts index e887f9ad..ac4f4721 100644 --- a/src/lib/ae_events/types/ae_badge_template_cfg.ts +++ b/src/lib/ae_events/types/ae_badge_template_cfg.ts @@ -64,14 +64,17 @@ export interface BadgeTemplateCfg { left?: boolean; right?: boolean; center?: boolean; - fg?: string; // shared fallback stroke/line color - bg?: string; // shared fallback fill color + fg?: string; // shared fallback stroke/line color + bg?: string; // shared fallback fill color left_fg?: string; left_bg?: string; + left_rainbow?: boolean; // animated hue-rotate; overrides fg/bg base color with saturated red right_fg?: string; right_bg?: string; + right_rainbow?: boolean; center_fg?: string; center_bg?: string; + center_rainbow?: boolean; }; // Allow arbitrary extra keys to preserve forward-compatibility. diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte index bfb8b3cb..3e9e5120 100644 --- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte +++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte @@ -333,16 +333,23 @@ let punch_holes_right = $derived(!!template_cfg?.punch_holes?.right); let punch_holes_center = $derived(!!template_cfg?.punch_holes?.center); // Per-slot colors: slot-specific override → shared fallback → component default. -const PH_DEFAULT_FG = '#777777'; -const PH_DEFAULT_BG = 'rgba(255,255,255,0.4)'; +// When rainbow is on and no explicit fg/bg is set, use a saturated base color so +// hue-rotate produces a full visible spectrum (gray has no hue to rotate). +const PH_DEFAULT_FG = '#777777'; +const PH_DEFAULT_BG = 'rgba(255,255,255,0.4)'; +const PH_RAINBOW_FG = '#ff2200'; // saturated red → full spectrum via hue-rotate +const PH_RAINBOW_BG = 'rgba(255,34,0,0.25)'; +let punch_holes_left_rainbow = $derived(!!template_cfg?.punch_holes?.left_rainbow); +let punch_holes_right_rainbow = $derived(!!template_cfg?.punch_holes?.right_rainbow); +let punch_holes_center_rainbow = $derived(!!template_cfg?.punch_holes?.center_rainbow); let punch_holes_colors = $derived.by(() => { const ph = template_cfg?.punch_holes; const shared_fg = ph?.fg || PH_DEFAULT_FG; const shared_bg = ph?.bg || PH_DEFAULT_BG; return { - left: { fg: ph?.left_fg || shared_fg, bg: ph?.left_bg || shared_bg }, - right: { fg: ph?.right_fg || shared_fg, bg: ph?.right_bg || shared_bg }, - center: { fg: ph?.center_fg || shared_fg, bg: ph?.center_bg || shared_bg } + left: { fg: ph?.left_fg || (ph?.left_rainbow ? PH_RAINBOW_FG : shared_fg), bg: ph?.left_bg || (ph?.left_rainbow ? PH_RAINBOW_BG : shared_bg) }, + right: { fg: ph?.right_fg || (ph?.right_rainbow ? PH_RAINBOW_FG : shared_fg), bg: ph?.right_bg || (ph?.right_rainbow ? PH_RAINBOW_BG : shared_bg) }, + center: { fg: ph?.center_fg || (ph?.center_rainbow ? PH_RAINBOW_FG : shared_fg), bg: ph?.center_bg || (ph?.center_rainbow ? PH_RAINBOW_BG : shared_bg) } }; }); @@ -694,6 +701,7 @@ const code_to_icon: { registration variance (slots are only 3mm tall, registration matters). --> {#if punch_holes_left}