x
This commit is contained in:
1 parent
e349ef5b84
commit
8d415ecef7
14 files changed
+372
-119
No files matched your search
@@ -265,6 +265,10 @@ export default function CategoryHeroCarouselBlockForm({
|
||||
mobilePosition={getString(slide.mobileButtonPosition) || undefined}
|
||||
onChangeDesktop={(pos) => updateSlide(slideIndex, { buttonPosition: pos })}
|
||||
onChangeMobile={(pos) => updateSlide(slideIndex, { mobileButtonPosition: pos || '' })}
|
||||
contentWidth={getString(slide.contentWidth, 'standard')}
|
||||
onChangeContentWidth={(w) => updateSlide(slideIndex, { contentWidth: w })}
|
||||
textColorScheme={getString(slide.textColorScheme, 'light')}
|
||||
onChangeTextColorScheme={(scheme) => updateSlide(slideIndex, { textColorScheme: scheme })}
|
||||
title="ตำแหน่งปุ่ม & ข้อความของสไลด์นี้ (Slide Content Position)"
|
||||
/>
|
||||
</article>
|
||||
|
||||
@@ -106,6 +106,10 @@ export default function BannerForm({
|
||||
mobilePosition={editingSection.payload?.mobileButtonPosition}
|
||||
onChangeDesktop={(pos) => updatePayloadValue('buttonPosition', pos)}
|
||||
onChangeMobile={(pos) => updatePayloadValue('mobileButtonPosition', pos)}
|
||||
contentWidth={editingSection.payload?.contentWidth}
|
||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||
textColorScheme={editingSection.payload?.textColorScheme}
|
||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Monitor, Smartphone, RotateCcw } from 'lucide-react';
|
||||
import { Monitor, Smartphone, RotateCcw, Maximize2, Sun, Moon, Palette } from 'lucide-react';
|
||||
|
||||
export const GRID_POSITIONS = [
|
||||
{ id: 'top-left', label: 'Top Left (บนซ้าย)', short: 'TL', icon: '↖' },
|
||||
@@ -12,12 +12,39 @@ export const GRID_POSITIONS = [
|
||||
{ id: 'bottom-right', label: 'Bottom Right (ล่างขวา)', short: 'BR', icon: '↘' },
|
||||
];
|
||||
|
||||
export const WIDTH_OPTIONS = [
|
||||
{ id: 'full', label: 'ขอบนอกสุด (Full Bleed)', desc: 'เต็มความกว้างจอ ชิดขอบซ้าย/ขวา' },
|
||||
{ id: 'standard', label: 'กรอบมาตรฐาน (1400px)', desc: 'ตามระยะเว็บหลัก max-w-7xl (แนะนำ)' },
|
||||
{ id: 'compact', label: 'กรอบกระชับ (768px)', desc: 'กล่องกะทัดรัด max-w-3xl' },
|
||||
] as const;
|
||||
|
||||
export const COLOR_SCHEME_OPTIONS = [
|
||||
{
|
||||
id: 'light',
|
||||
label: 'สว่าง (Light / ตัวอักษรสีขาว)',
|
||||
desc: 'สำหรับภาพพื้นหลังโทนเข้ม หรือมี Overlay มืด (ค่าเริ่มต้น)',
|
||||
icon: Sun,
|
||||
badgeBg: 'bg-white/10 text-white border-white/20',
|
||||
},
|
||||
{
|
||||
id: 'dark',
|
||||
label: 'มืด (Dark / ตัวอักษรสีเข้ม)',
|
||||
desc: 'สำหรับภาพพื้นหลังโทนขาว หรือภาพสว่างสดใส',
|
||||
icon: Moon,
|
||||
badgeBg: 'bg-neutral-800 text-slate-200 border-white/10',
|
||||
},
|
||||
] as const;
|
||||
|
||||
export interface ContentPositionPickerProps {
|
||||
desktopPosition?: string;
|
||||
mobilePosition?: string;
|
||||
defaultDesktop?: string;
|
||||
onChangeDesktop: (position: string) => void;
|
||||
onChangeMobile: (position: string | undefined) => void;
|
||||
contentWidth?: string;
|
||||
onChangeContentWidth?: (width: string) => void;
|
||||
textColorScheme?: 'light' | 'dark' | string;
|
||||
onChangeTextColorScheme?: (scheme: 'light' | 'dark') => void;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
compact?: boolean;
|
||||
@@ -29,6 +56,10 @@ export default function ContentPositionPicker({
|
||||
defaultDesktop = 'center',
|
||||
onChangeDesktop,
|
||||
onChangeMobile,
|
||||
contentWidth,
|
||||
onChangeContentWidth,
|
||||
textColorScheme,
|
||||
onChangeTextColorScheme,
|
||||
title = 'ตำแหน่งปุ่ม & เนื้อหา (Button & Content Position)',
|
||||
subtitle = 'สามารถแยกตำแหน่งระหว่าง Desktop (PC) และ Mobile (มือถือ) ได้อิสระ',
|
||||
compact = false,
|
||||
@@ -148,6 +179,82 @@ export default function ContentPositionPicker({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Container Width / Outer Boundary Selection */}
|
||||
{onChangeContentWidth && (
|
||||
<div className="bg-night-950/40 border border-white/5 p-3 rounded-2xl space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[11px] font-bold uppercase tracking-wider text-slate-300 flex items-center gap-1.5">
|
||||
<Maximize2 className="w-3.5 h-3.5 text-cyan-glow" />
|
||||
ความกว้างกรอบเนื้อหา (Content Width / Boundary)
|
||||
</span>
|
||||
<span className="px-2 py-0.5 rounded-md bg-cyan-glow/10 text-cyan-glow font-mono font-bold text-[10px] border border-cyan-glow/20">
|
||||
{contentWidth || 'standard'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||
{WIDTH_OPTIONS.map((opt) => {
|
||||
const isSelected = (contentWidth || 'standard') === opt.id;
|
||||
return (
|
||||
<button
|
||||
key={opt.id}
|
||||
type="button"
|
||||
onClick={() => onChangeContentWidth(opt.id)}
|
||||
className={`px-3 py-2 rounded-xl text-left transition-all border cursor-pointer ${
|
||||
isSelected
|
||||
? 'bg-cyan-glow/15 border-cyan-glow/50 text-white shadow-sm ring-1 ring-cyan-glow/30'
|
||||
: 'bg-night-900 border-white/5 text-slate-400 hover:text-white hover:border-white/10'
|
||||
}`}
|
||||
>
|
||||
<div className="text-xs font-bold leading-tight">{opt.label}</div>
|
||||
<div className="text-[9px] text-slate-500 mt-0.5 leading-tight">{opt.desc}</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Text Color Scheme Preset Selection */}
|
||||
{onChangeTextColorScheme && (
|
||||
<div className="bg-night-950/40 border border-white/5 p-3 rounded-2xl space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[11px] font-bold uppercase tracking-wider text-slate-300 flex items-center gap-1.5">
|
||||
<Palette className="w-3.5 h-3.5 text-pop-pink" />
|
||||
โทนสีตัวอักษร (Text Color Scheme Preset)
|
||||
</span>
|
||||
<span className={`px-2 py-0.5 rounded-md font-mono font-bold text-[10px] border ${(textColorScheme || 'light') === 'dark' ? 'bg-amber-400/10 text-amber-300 border-amber-400/20' : 'bg-cyan-glow/10 text-cyan-glow border-cyan-glow/20'}`}>
|
||||
{(textColorScheme || 'light').toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
{COLOR_SCHEME_OPTIONS.map((opt) => {
|
||||
const isSelected = (textColorScheme || 'light') === opt.id;
|
||||
const Icon = opt.icon;
|
||||
return (
|
||||
<button
|
||||
key={opt.id}
|
||||
type="button"
|
||||
onClick={() => onChangeTextColorScheme(opt.id as 'light' | 'dark')}
|
||||
className={`px-3 py-2.5 rounded-xl text-left transition-all border cursor-pointer flex items-start gap-2.5 ${
|
||||
isSelected
|
||||
? 'bg-pop-pink/15 border-pop-pink/50 text-white shadow-sm ring-1 ring-pop-pink/30'
|
||||
: 'bg-night-900 border-white/5 text-slate-400 hover:text-white hover:border-white/10'
|
||||
}`}
|
||||
>
|
||||
<div className={`p-1.5 rounded-lg border shrink-0 mt-0.5 ${opt.badgeBg}`}>
|
||||
<Icon className="w-4 h-4" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs font-bold leading-tight">{opt.label}</div>
|
||||
<div className="text-[9px] text-slate-500 mt-0.5 leading-tight">{opt.desc}</div>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -381,6 +381,10 @@ export default function HeroCarouselForm({
|
||||
mobilePosition={slide.mobileButtonPosition}
|
||||
onChangeDesktop={(pos) => updateSlidePayloadValue(idx, 'buttonPosition', pos)}
|
||||
onChangeMobile={(pos) => updateSlidePayloadValue(idx, 'mobileButtonPosition', pos || '')}
|
||||
contentWidth={slide.contentWidth}
|
||||
onChangeContentWidth={(w) => updateSlidePayloadValue(idx, 'contentWidth', w)}
|
||||
textColorScheme={slide.textColorScheme}
|
||||
onChangeTextColorScheme={(scheme) => updateSlidePayloadValue(idx, 'textColorScheme', scheme)}
|
||||
title="ตำแหน่งปุ่ม & ข้อความของสไลด์นี้ (Slide Content Position)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -225,13 +225,17 @@ export default function HeroForm({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 9-Box Grid Button Position Selector (Desktop & Mobile) */}
|
||||
{/* 9-Box Grid Button Position & Content Width & Text Color Scheme Selector */}
|
||||
<div className="md:col-span-2">
|
||||
<ContentPositionPicker
|
||||
desktopPosition={editingSection.payload?.buttonPosition}
|
||||
mobilePosition={editingSection.payload?.mobileButtonPosition}
|
||||
onChangeDesktop={(pos) => updatePayloadValue('buttonPosition', pos)}
|
||||
onChangeMobile={(pos) => updatePayloadValue('mobileButtonPosition', pos)}
|
||||
contentWidth={editingSection.payload?.contentWidth}
|
||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||
textColorScheme={editingSection.payload?.textColorScheme}
|
||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -293,12 +293,16 @@ export default function HeroVideoForm({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Button & Content Position (9-Box Grid for Desktop & Mobile) */}
|
||||
{/* Button & Content Position (9-Box Grid for Desktop & Mobile) & Color Scheme */}
|
||||
<ContentPositionPicker
|
||||
desktopPosition={payload.buttonPosition}
|
||||
mobilePosition={payload.mobileButtonPosition}
|
||||
onChangeDesktop={(pos) => updatePayloadValue('buttonPosition', pos)}
|
||||
onChangeMobile={(pos) => updatePayloadValue('mobileButtonPosition', pos)}
|
||||
contentWidth={payload.contentWidth}
|
||||
onChangeContentWidth={(w) => updatePayloadValue('contentWidth', w)}
|
||||
textColorScheme={payload.textColorScheme}
|
||||
onChangeTextColorScheme={(scheme) => updatePayloadValue('textColorScheme', scheme)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -265,6 +265,10 @@ export default function ProductHeroCarouselBlockForm({
|
||||
mobilePosition={getString(slide.mobileButtonPosition) || undefined}
|
||||
onChangeDesktop={(pos) => updateSlide(slideIndex, { buttonPosition: pos })}
|
||||
onChangeMobile={(pos) => updateSlide(slideIndex, { mobileButtonPosition: pos || '' })}
|
||||
contentWidth={getString(slide.contentWidth, 'standard')}
|
||||
onChangeContentWidth={(w) => updateSlide(slideIndex, { contentWidth: w })}
|
||||
textColorScheme={getString(slide.textColorScheme, 'light')}
|
||||
onChangeTextColorScheme={(scheme) => updateSlide(slideIndex, { textColorScheme: scheme })}
|
||||
title="ตำแหน่งปุ่ม & ข้อความของสไลด์นี้ (Slide Content Position)"
|
||||
/>
|
||||
</article>
|
||||
|
||||
Reference in new issue
Block a user