fix(widget): powered toggle persistence, copy buttons, version dates, showLessonsCount, color pickers, and loading spinner

This commit is contained in:
Rotimi Best
2026-06-13 11:24:20 +01:00
parent 094683b551
commit 0975f82c8b
14 changed files with 153 additions and 74 deletions
@@ -50,7 +50,7 @@
{:else}
<span></span>
{/if}
<span class="cio-cg-meta">{formatLessonsLine(course)}</span>
<span class="cio-cg-meta">{formatLessonsLine(course, payload.design.content.showLessonsCount)}</span>
</div>
</div>
</a>
@@ -91,7 +91,7 @@
<TypeBadge courseType={course.courseType} />
</div>
{/if}
<div class="cio-cr-meta">{formatLessonsLine(course)}</div>
<div class="cio-cr-meta">{formatLessonsLine(course, payload.design.content.showLessonsCount)}</div>
</div>
</a>
{/each}
@@ -3,6 +3,7 @@
import Stars from './atoms/stars.svelte';
import TypeBadge from './atoms/type-badge.svelte';
import Thumb from './atoms/thumb.svelte';
import { formatLessonsLine } from './utils';
let { payload }: { payload: TWidgetPayload } = $props();
@@ -25,7 +26,7 @@
<div class="cio-cl-top">
<span class="cio-cl-title">{course.title}</span>
{#if payload.design.content.showLessonsCount}
<span class="cio-cl-lessons">{course.lessonCount} lessons</span>
<span class="cio-cl-lessons">{formatLessonsLine(course, payload.design.content.showLessonsCount)}</span>
{/if}
</div>
<div class="cio-cl-mid">
@@ -22,15 +22,23 @@
if (!payload || !rootEl) return;
ensureWidgetGoogleFontsLoaded(rootEl, payload.design);
});
$effect(() => {
if (!rootEl) return;
const existing = rootEl.querySelector<HTMLStyleElement>('[data-cio-widget-custom-css]');
if (existing) existing.remove();
if (!customCss) return;
const styleEl = document.createElement('style');
styleEl.setAttribute('data-cio-widget-custom-css', '');
styleEl.textContent = customCss;
rootEl.appendChild(styleEl);
});
</script>
{#if !payload}
<div class="cio-widget cio-widget--empty">No widget payload provided.</div>
{:else}
<div bind:this={rootEl} class="cio-widget" style={cssVars} data-cio-layout={payload.layoutType}>
{#if customCss}
<svelte:element this={'style'} data-cio-widget-custom-css="">{customCss}</svelte:element>
{/if}
{#if payload.layoutType === 'card_grid'}
<CardGrid {payload} />
{:else if payload.layoutType === 'tag_filter'}
@@ -31,7 +31,7 @@
{/if}
<span class="cio-ph-sep">·</span>
{/if}
<span class="cio-ph-meta">{formatLessonsLine(featured)}</span>
<span class="cio-ph-meta">{formatLessonsLine(featured, payload.design.content.showLessonsCount)}</span>
</div>
{#if payload.design.content.showCourseTypeBadge || featured.tags.length > 0}
<div class="cio-ph-badges">
@@ -56,7 +56,8 @@ export function getCourseExcerpt(course: TWidgetPayloadCourse, maxLength = 160):
return `${flat.slice(0, maxLength - 1).trim()}…`;
}
export function formatLessonsLine(course: TWidgetPayloadCourse): string {
export function formatLessonsLine(course: TWidgetPayloadCourse, showLessonsCount?: boolean): string {
if (showLessonsCount === false) return '';
const parts: string[] = [];
if (course.lessonCount) parts.push(`${course.lessonCount} lessons`);
if (course.exerciseCount) parts.push(`${course.exerciseCount} exercises`);