99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
import React from 'react';
|
|
import type { WidgetSlot as WidgetSlotModel } from '../../types/widgetDashboard';
|
|
import type { WidgetZoneId } from '../../types/widgetDashboard';
|
|
import { getWidgetDefinition, widgetLabel } from '../../widgets/widgetRegistry';
|
|
|
|
interface Props {
|
|
slot: WidgetSlotModel;
|
|
zoneId: WidgetZoneId;
|
|
onPickWidget: (slotId: string) => void;
|
|
onClearWidget?: (slotId: string) => void;
|
|
}
|
|
|
|
const WidgetSlotView: React.FC<Props> = ({
|
|
slot,
|
|
zoneId,
|
|
onPickWidget,
|
|
onClearWidget,
|
|
}) => {
|
|
const def = getWidgetDefinition(slot.widgetType);
|
|
const category = zoneId === 'center' ? 'center' : 'side';
|
|
const Host = def?.Host;
|
|
const filledEmbed = Boolean(Host);
|
|
|
|
return (
|
|
<div
|
|
className={[
|
|
'wd-slot',
|
|
filledEmbed ? 'wd-slot--filled' : '',
|
|
filledEmbed && zoneId === 'center' ? 'wd-slot--filled-center' : '',
|
|
].filter(Boolean).join(' ')}
|
|
>
|
|
{!filledEmbed && (
|
|
<header className="wd-slot-head">
|
|
<span className="wd-slot-title">{widgetLabel(slot.widgetType)}</span>
|
|
<div className="wd-slot-actions">
|
|
{slot.widgetType && onClearWidget && (
|
|
<button
|
|
type="button"
|
|
className="wd-slot-action"
|
|
title="위젯 제거"
|
|
aria-label="위젯 제거"
|
|
onClick={() => onClearWidget(slot.id)}
|
|
>
|
|
✕
|
|
</button>
|
|
)}
|
|
</div>
|
|
</header>
|
|
)}
|
|
<div className={['wd-slot-body', Host && onClearWidget ? 'wd-slot-body--has-clear' : ''].filter(Boolean).join(' ')}>
|
|
{Host ? (
|
|
<Host config={slot.config} />
|
|
) : (
|
|
<div className="wd-slot-empty">
|
|
<button
|
|
type="button"
|
|
className="wd-slot-add"
|
|
title="위젯 추가"
|
|
aria-label="위젯 추가"
|
|
onClick={() => onPickWidget(slot.id)}
|
|
>
|
|
<span className="wd-slot-add-icon">+</span>
|
|
</button>
|
|
<p className="wd-slot-empty-hint">
|
|
{category === 'center' ? '메인 위젯을 추가하세요' : '패널 위젯을 추가하세요'}
|
|
</p>
|
|
</div>
|
|
)}
|
|
{Host && (
|
|
<>
|
|
{filledEmbed && onClearWidget && (
|
|
<button
|
|
type="button"
|
|
className="wd-slot-overlay-clear"
|
|
title="위젯 제거"
|
|
aria-label="위젯 제거"
|
|
onClick={() => onClearWidget(slot.id)}
|
|
>
|
|
✕
|
|
</button>
|
|
)}
|
|
<button
|
|
type="button"
|
|
className="wd-slot-change"
|
|
title="위젯 변경"
|
|
aria-label="위젯 변경"
|
|
onClick={() => onPickWidget(slot.id)}
|
|
>
|
|
+
|
|
</button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default WidgetSlotView;
|