wip
This commit is contained in:
@@ -1,11 +1,19 @@
|
||||
"use client";
|
||||
import "@/app/globals.css";
|
||||
import { useRef } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import ComponentsStore from "@/stores/componentStore";
|
||||
import { componentsLibrary } from "./Draggable/Draggable";
|
||||
import { useDynamicWidgets } from "@/hooks/useDynamicWidgets";
|
||||
|
||||
export default function ComponentPaletteDrawer() {
|
||||
const checkboxRef = useRef<HTMLInputElement>(null);
|
||||
const [componentsId, setComponentsId] = useState("logo");
|
||||
const [data, setData] = useState("");
|
||||
const {widgets} = useDynamicWidgets();
|
||||
|
||||
const onSubmit = (e: SubmitEvent) => {
|
||||
e.preventDefault();
|
||||
ComponentsStore.addComponent(componentsId, data && JSON.parse(data));
|
||||
checkboxRef.current?.click();
|
||||
};
|
||||
return (
|
||||
@@ -25,7 +33,7 @@ export default function ComponentPaletteDrawer() {
|
||||
Add Component
|
||||
</label>
|
||||
</div>
|
||||
<div className="drawer-side">
|
||||
<div className="drawer-side z-50">
|
||||
<label
|
||||
htmlFor="ComponentPaletteDrawer"
|
||||
aria-label="close sidebar"
|
||||
@@ -37,7 +45,7 @@ export default function ComponentPaletteDrawer() {
|
||||
</div>
|
||||
|
||||
<div className="p-4">
|
||||
<div role="alert" className="alert alert-warning">
|
||||
<div role="alert" className="alert alert-warning mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="h-6 w-6 shrink-0 stroke-current"
|
||||
@@ -53,13 +61,31 @@ export default function ComponentPaletteDrawer() {
|
||||
</svg>
|
||||
<span>Warning: 内容处于开发阶段仅供参考!</span>
|
||||
</div>
|
||||
|
||||
<div className="resize-y border overflow-hidden max-w-full h-64 ">
|
||||
{
|
||||
componentsId && componentsLibrary[componentsId](data)
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
JSON.stringify(widgets)
|
||||
}
|
||||
|
||||
<form onSubmit={onSubmit} className="w-full">
|
||||
<fieldset className="fieldset w-full">
|
||||
<legend className="fieldset-legend">小部件</legend>
|
||||
<select defaultValue="请选择小部件" className="select w-full">
|
||||
<select
|
||||
value={componentsId}
|
||||
onChange={(e) => setComponentsId(e.target.value)}
|
||||
className="select w-full"
|
||||
>
|
||||
<option disabled={true}>请选择小部件</option>
|
||||
<option>文本</option>
|
||||
<option>Logo</option>
|
||||
{
|
||||
widgets.map(item => {
|
||||
return (<option value={item.id}>{item.name}</option>)
|
||||
})
|
||||
}
|
||||
</select>
|
||||
<p className="fieldset-label">你可以选择一款你喜欢的小部件</p>
|
||||
</fieldset>
|
||||
@@ -67,9 +93,11 @@ export default function ComponentPaletteDrawer() {
|
||||
<fieldset className="fieldset w-full">
|
||||
<legend className="fieldset-legend">配置信息</legend>
|
||||
<textarea
|
||||
onChange={(e) => setData(e.target.value)}
|
||||
className="textarea h-24 w-full"
|
||||
placeholder="请输入 JSON 格式的配置信息"
|
||||
></textarea>
|
||||
|
||||
<p className="fieldset-label">JSON格式的配置信息</p>
|
||||
</fieldset>
|
||||
<button className="btn w-full btn-primary">确认</button>
|
||||
|
||||
@@ -6,8 +6,8 @@ import { useDraggable } from "@dnd-kit/core";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { nearestMultiple } from "./utils";
|
||||
import PreviewStore from "@/stores/previewStore";
|
||||
import Logo from "../Logo";
|
||||
import Text from "../Text";
|
||||
import Logo from "../../widgets/Logo";
|
||||
import Text from "../../widgets/Text";
|
||||
|
||||
export default function Draggable(props: DraggablePropsType) {
|
||||
const targetRef = useRef<HTMLDivElement>(null);
|
||||
@@ -78,7 +78,7 @@ export default function Draggable(props: DraggablePropsType) {
|
||||
...style,
|
||||
}} {...attributes}>
|
||||
<button
|
||||
className="btn absolute top-1 right-1 z-50 btn-square btn-soft"
|
||||
className="btn absolute top-1 right-1 z-40 btn-square btn-soft"
|
||||
{...listeners}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
|
||||
@@ -28,12 +28,12 @@ export default function Preview(props: PreviewPropsType) {
|
||||
<span
|
||||
className="absolute text-2xl bg-emerald-500 border-emerald-500 text-white top-0 p-0.5"
|
||||
>
|
||||
{width * height === 0 || `${width} * ${height}`}
|
||||
{width + height === 0 || `${width} * ${height}`}
|
||||
</span>
|
||||
<span
|
||||
className="absolute text-2xl bg-emerald-500 border-emerald-500 text-white bottom-0 p-0.5"
|
||||
>
|
||||
{x * y === 0 || `${x}, ${y}`}
|
||||
{x + y === 0 || `${x}, ${y}`}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
* @param [x=16] 推荐使用偶数
|
||||
* @returns 最近的 x 的倍数
|
||||
*/
|
||||
export function nearestMultiple(n: number, x: number = 32): number {
|
||||
export function nearestMultiple(n: number, x: number = 18): number {
|
||||
return Math.floor((n + x/2) / x) * x;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function DraggablePanel(props: DraggablePanelType) {
|
||||
PreviewStore.clearPreview();
|
||||
ComponentStore.changeComponent({
|
||||
id: event?.active?.data?.current?.id,
|
||||
component: event?.active?.data?.current?.component,
|
||||
componentsId: event?.active?.data?.current?.componentsId,
|
||||
x,
|
||||
y,
|
||||
width: nearestMultiple(width),
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
"use client";
|
||||
import "@/app/globals.css";
|
||||
|
||||
export default function Logo() {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center text-5xl bg-base-200 font-bold">
|
||||
<span className="whitespace-nowrap text-primary">
|
||||
NEXUSHUB
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
import React, { CSSProperties } from 'react';
|
||||
import { DraggablePropsType } from '../Draggable/Draggable';
|
||||
|
||||
type FontData = {
|
||||
content: string;
|
||||
fontSize?: number; // 字体大小(px)
|
||||
fontFamily?: string; // 字体类型
|
||||
color?: string; // 字体颜色
|
||||
fontWeight?: number; // 字重
|
||||
lineHeight?: number; // 行高比例
|
||||
textAlign?: 'left' | 'center' | 'right'; // 对齐方式
|
||||
letterSpacing?: number; // 字间距(px)
|
||||
customStyles?: CSSProperties; // 自定义CSS扩展
|
||||
};
|
||||
|
||||
interface ResponsiveTextProps {
|
||||
data: DraggablePropsType["data"] & FontData;
|
||||
className?: string; // 外部容器类名
|
||||
}
|
||||
|
||||
const Text: React.FC<ResponsiveTextProps> = ({
|
||||
data,
|
||||
className
|
||||
}) => {
|
||||
// 合并默认样式与传入样式
|
||||
const textStyles: CSSProperties = {
|
||||
fontSize: `${data.fontSize || 16}px`,
|
||||
fontFamily: data.fontFamily || 'Arial, sans-serif',
|
||||
color: data.color || '#333',
|
||||
fontWeight: data.fontWeight || 400,
|
||||
lineHeight: data.lineHeight ? `${data.lineHeight}em` : '1.5',
|
||||
textAlign: data.textAlign || 'left',
|
||||
letterSpacing: `${data.letterSpacing || 0}px`,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: data.textAlign === 'center' ? 'center' :
|
||||
data.textAlign === 'right' ? 'flex-end' : 'flex-start',
|
||||
...data.customStyles
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
style={{
|
||||
position: 'relative',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
minWidth: '50px', // 防止容器坍缩
|
||||
minHeight: '1em' // 最小高度保障
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
...textStyles,
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word',
|
||||
padding: '0.2em' // 防止文本贴边
|
||||
}}
|
||||
title={data.content} // 添加tooltip
|
||||
>
|
||||
{data.content}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Text;
|
||||
Reference in New Issue
Block a user