feat(editor): partner board sections (Seeed, DFRobot, Pimoroni, Espressif) in the starter dialog

Below M5Stack, same pro() mechanics: each section lists only the boards the
overlay registered, so OSS builds and launch-embargoed kits render nothing.
Preferred first-run examples wired for every partner kind; Stellar/Badger
entries are required, their gallery examples use boards[] + boardFilter and
the generic blink search never matches them.
This commit is contained in:
David Montero 2026-08-28 04:19:24 +02:00
parent 34162e2de1
commit e4c87ac7bb
2 changed files with 83 additions and 3 deletions

View File

@ -2,9 +2,10 @@
* NewProjectDialog starter sections — display order and overlay cards.
*
* The dialog hardcodes its sections; overlay-registered kinds (M5Stack,
* XIAO C6, XIAO RP2040) surface only when the private overlay registered
* them. Guards the operator's requested order: M5Stack (Cardputer ADV, then
* Core) sits ahead of STM32, and an OSS build shows no empty M5Stack block.
* the partner sections, XIAO C6, XIAO RP2040) surface only when the private
* overlay registered them. Guards the operator's requested order: the
* partner sections (M5Stack, Seeed Studio, DFRobot, Pimoroni, Espressif)
* sit between ESP32 and STM32, and an OSS build shows none of them empty.
*/
import { describe, it, expect } from 'vitest';
import { buildStarterSections } from '../components/editor/NewProjectDialog';
@ -45,6 +46,45 @@ describe('NewProjectDialog starter sections', () => {
expect(m5.entries[0].blurb).toBe('ESP32-S3 card computer');
});
it('full partner overlay: sections sit between M5Stack and STM32, catalog order', () => {
const defs = [
def('cardputer-adv', 'M5 Cardputer ADV', 'x'),
def('m5stack-core', 'M5Stack Core', 'x'),
def('xiao-esp32s3-sense', 'XIAO ESP32-S3 Sense', 'x'),
def('unihiker-m10', 'UNIHIKER M10', 'x'),
def('pimoroni-pico-plus-2w', 'Pico Plus 2 W', 'x'),
def('badger-2350', 'Badger 2350', 'x'),
def('stellar-unicorn', 'Stellar Unicorn', 'x'),
def('esp32-c3-lcdkit', 'ESP32-C3-LCDkit', 'x'),
];
expect(titles(defs)).toEqual([
'Arduino',
'ESP32',
'M5Stack',
'Seeed Studio',
'DFRobot',
'Pimoroni',
'Espressif',
'STM32',
'Raspberry Pi',
]);
const pim = buildStarterSections(defs).find((s) => s.title === 'Pimoroni')!;
expect(pim.entries.map((e) => e.kind)).toEqual([
'pimoroni-pico-plus-2w',
'badger-2350',
'stellar-unicorn',
]);
});
it('embargoed partner boards (not registered) leave their section unrendered', () => {
// Pimoroni launched, Espressif still under embargo: no Espressif block.
const defs = [
def('pimoroni-pico-plus-2w', 'Pico Plus 2 W', 'x'),
def('badger-2350', 'Badger 2350', 'x'),
];
expect(titles(defs)).toEqual(['Arduino', 'ESP32', 'Pimoroni', 'STM32', 'Raspberry Pi']);
});
it('a partial overlay (only one M5 kind) still renders the section with that card', () => {
const m5 = buildStarterSections([def('m5stack-core', 'M5Stack Core', 'x')]).find(
(s) => s.title === 'M5Stack',

View File

@ -156,6 +156,21 @@ const PREFERRED_BLINK_EXAMPLE: Record<string, string> = {
// is the first run. Both ids carry a captured gallery thumb.
'cardputer-adv': 'cardputer-adv-hello',
'm5stack-core': 'm5stack-core-m5-helloworld',
// Partner boards (overlay kinds), one representative first-run each. The
// Stellar/Badger entries are REQUIRED, not just preferred: their gallery
// examples use `boards[]` + boardFilter, which the generic single-board
// search above never matches.
'xiao-esp32s3-sense': 'xiao-esp32s3-sense-hello',
'unihiker-m10': 'unihiker-blink-p2',
'pimoroni-pico-plus-2w': 'pimoroni-pico-plus-2w-blink',
'badger-2350': 'badger-2350-badgeos',
'stellar-unicorn': 'stellar-unicorn-rainbow',
// Espressif devkits — launch-embargoed; cards appear when the boards do.
'esp32-c3-lcdkit': 'esp32-c3-lcdkit-knob-dial',
'esp32-s3-eye': 'esp32-s3-eye-camera-lcd',
'esp-vocat': 'esp-vocat-face',
'esp-sensairshuttle': 'esp-sensair-lcd-dash',
'esp32-p4': 'esp32-p4-blink',
};
/** Dynamic import keeps the (large) gallery data out of the editor bundle
@ -255,6 +270,31 @@ export function buildStarterSections(defs: ProBoardDef[]): StarterSection[] {
// they run on Free and are a friendlier first pick than the Pro-gated
// STM32 family. Cardputer first, then the Core.
{ title: 'M5Stack', entries: [...pro('cardputer-adv'), ...pro('m5stack-core')] },
// Hardware partners (overlay kinds, same shape as M5Stack): each section
// lists only the boards the overlay actually registered, so an OSS build
// and launch-embargoed items (e.g. the Espressif devkits pre-launch)
// simply render nothing. The XIAO S3/C3/C6 and XIAO RP2040 stay in the
// chip-family sections above as the generation representatives.
{ title: 'Seeed Studio', entries: [...pro('xiao-esp32s3-sense')] },
{ title: 'DFRobot', entries: [...pro('unihiker-m10')] },
{
title: 'Pimoroni',
entries: [
...pro('pimoroni-pico-plus-2w'),
...pro('badger-2350'),
...pro('stellar-unicorn'),
],
},
{
title: 'Espressif',
entries: [
...pro('esp32-c3-lcdkit'),
...pro('esp32-s3-eye'),
...pro('esp-vocat'),
...pro('esp32-p4'),
...pro('esp-sensairshuttle'),
],
},
{ title: 'STM32', entries: STM32_BOARDS.map(oss) },
{
title: 'Raspberry Pi',