From c0e0003460f82948d2d172f252a662944d8ae874 Mon Sep 17 00:00:00 2001 From: Josh Knapp Date: Wed, 7 Oct 2026 11:52:32 -0700 Subject: [PATCH] feat(site-builder): asset search/filter, stock photo tab and background focal point Search + type chips in the Assets panel and picker library; Stock photos entry in the picker (feature-detected, hidden when stock_disabled/absent); bgPosition focal point for Hero and Background Section. Refs #55 --- .../layout/BackgroundSection.toHtml.test.ts | 16 ++ .../components/layout/BackgroundSection.tsx | 10 +- .../sections/HeroSimple.toHtml.test.ts | 17 +++ craft/src/components/sections/HeroSimple.tsx | 8 +- craft/src/hooks/useStockPhotos.test.ts | 121 +++++++++++++++ craft/src/hooks/useStockPhotos.ts | 143 ++++++++++++++++++ craft/src/panels/left/AssetsPanel.test.tsx | 71 +++++++++ craft/src/panels/left/AssetsPanel.tsx | 20 ++- .../styles/BackgroundSectionStylePanel.tsx | 5 + .../panels/right/styles/HeroStylePanel.tsx | 5 + .../panels/right/styles/ImageStylePanel.tsx | 4 + craft/src/styles/editor.css | 31 ++++ craft/src/ui/AssetFilter.tsx | 89 +++++++++++ craft/src/ui/AssetPicker.test.tsx | 87 +++++++++++ craft/src/ui/AssetPicker.tsx | 65 +++++++- craft/src/ui/StockPhotoTab.test.tsx | 103 +++++++++++++ craft/src/ui/StockPhotoTab.tsx | 142 +++++++++++++++++ 17 files changed, 928 insertions(+), 9 deletions(-) create mode 100644 craft/src/hooks/useStockPhotos.test.ts create mode 100644 craft/src/hooks/useStockPhotos.ts create mode 100644 craft/src/panels/left/AssetsPanel.test.tsx create mode 100644 craft/src/ui/AssetFilter.tsx create mode 100644 craft/src/ui/StockPhotoTab.test.tsx create mode 100644 craft/src/ui/StockPhotoTab.tsx diff --git a/craft/src/components/layout/BackgroundSection.toHtml.test.ts b/craft/src/components/layout/BackgroundSection.toHtml.test.ts index bdbcb91..ef52c98 100644 --- a/craft/src/components/layout/BackgroundSection.toHtml.test.ts +++ b/craft/src/components/layout/BackgroundSection.toHtml.test.ts @@ -56,3 +56,19 @@ describe('BackgroundSection.toHtml style-value XSS hardening', () => { expect(html).toContain('child'); }); }); + +describe('BackgroundSection.toHtml bgPosition focal point (#55)', () => { + test('bgPosition is emitted as background-position', () => { + const { html } = toHtml({ bgImage: 'assets/a.jpg', bgPosition: 'left top' }, 'child'); + expect(html).toContain('background-position:left top'); + expect(html).not.toContain('background-position:center'); + }); + test('blank or missing bgPosition keeps center', () => { + expect(toHtml({ bgImage: 'assets/a.jpg', bgPosition: '' }, '').html).toContain('background-position:center'); + expect(toHtml({ bgImage: 'assets/a.jpg' }, '').html).toContain('background-position:center'); + }); + test('a malicious bgPosition cannot break out of the style attribute', () => { + const { html } = toHtml({ bgImage: 'x', bgPosition: 'left";}' }, ''); + expect(html).not.toContain('' }, ''); + expect(html).not.toContain('