@arronqzy/react-view 1.0.20 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/styles.css +45 -0
- package/package.json +5 -5
- package/readme.md +6 -1
- package/src/panel/I18nRoot.tsx +14 -2
- package/src/panel/ReactViewOnlinePreview.tsx +29 -18
- package/src/panel/ReactViewPanel.tsx +65 -59
- package/src/panel/ai/applyAssistantAction.ts +1 -0
- package/src/panel/components/ElementsLayer.tsx +67 -16
- package/src/panel/components/MaterialSidebar.tsx +18 -11
- package/src/panel/components/PanelConfigSidebar.tsx +139 -1
- package/src/panel/components/WorkspaceConfigSidebar.tsx +1 -0
- package/src/panel/hooks/usePanelElements.ts +10 -4
- package/src/panel/hooks/useWorkspaceProjects.ts +112 -34
- package/src/panel/index.tsx +15 -1
- package/src/panel/library/capture-preview-snapshot.ts +4 -2
- package/src/panel/library/parse-workspace-data.ts +142 -0
- package/src/panel/library/workspace-project-cache.ts +13 -4
- package/src/panel/library/workspace-project-db.ts +24 -13
- package/src/panel/library/workspace-project-sync.ts +17 -6
- package/src/panel/types.ts +4 -0
- package/src/panel/utils/outputScale.ts +9 -4
- package/src/panel/utils/panelElementDefaults.ts +10 -0
- package/src/panel/utils/panelElementNodes.ts +5 -3
- package/src/panel/utils/panelStateIO.ts +18 -0
- package/src/panel/utils/viewportPlacement.ts +73 -0
package/src/panel/types.ts
CHANGED
|
@@ -54,6 +54,8 @@ export type PanelElementStyle = {
|
|
|
54
54
|
|
|
55
55
|
export type ReferenceCopyMode = "shallow" | "deep";
|
|
56
56
|
|
|
57
|
+
export type ViewportOverflowMode = "scroll-x" | "scroll-y" | "scroll" | "clip";
|
|
58
|
+
|
|
57
59
|
import type { PanelTableConfig } from "@arronqzy/view-table";
|
|
58
60
|
import type { Scene3dConfig } from "@arronqzy/view-scene3d";
|
|
59
61
|
|
|
@@ -83,6 +85,8 @@ export type PanelElement = {
|
|
|
83
85
|
gridPadding?: number;
|
|
84
86
|
gridSnapThreshold?: number;
|
|
85
87
|
parentGridId?: string;
|
|
88
|
+
/** 视窗节点:只显示自身尺寸内的引用图层内容,超出部分滚动或裁剪 */
|
|
89
|
+
viewportOverflow?: ViewportOverflowMode;
|
|
86
90
|
gridSlotIndex?: number;
|
|
87
91
|
gridColSpan?: number;
|
|
88
92
|
gridRowSpan?: number;
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
/** 产物预览是否缩放内部内容(字体等)。默认 false:块仍按视口撑满,内容保持原尺寸以免失真。 */
|
|
2
|
+
import { appStorageKey } from "@arronqzy/blueprint-dsl";
|
|
3
|
+
|
|
2
4
|
export const OUTPUT_SCALE_STORAGE_KEY = "panel:outputScale";
|
|
3
5
|
|
|
4
|
-
export function readOutputScale(): boolean {
|
|
6
|
+
export function readOutputScale(nameSpace?: string | null): boolean {
|
|
5
7
|
try {
|
|
6
|
-
return localStorage.getItem(OUTPUT_SCALE_STORAGE_KEY) === "1";
|
|
8
|
+
return localStorage.getItem(appStorageKey(OUTPUT_SCALE_STORAGE_KEY, nameSpace)) === "1";
|
|
7
9
|
} catch {
|
|
8
10
|
return false;
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
export function writeOutputScale(enabled: boolean) {
|
|
14
|
+
export function writeOutputScale(enabled: boolean, nameSpace?: string | null) {
|
|
13
15
|
try {
|
|
14
|
-
localStorage.setItem(
|
|
16
|
+
localStorage.setItem(
|
|
17
|
+
appStorageKey(OUTPUT_SCALE_STORAGE_KEY, nameSpace),
|
|
18
|
+
enabled ? "1" : "0"
|
|
19
|
+
);
|
|
15
20
|
} catch {
|
|
16
21
|
// ignore storage errors
|
|
17
22
|
}
|
|
@@ -17,6 +17,7 @@ const DEFAULT_NODE_NAME_KEYS: Record<string, string> = {
|
|
|
17
17
|
funnel: "panel.defaults.funnel",
|
|
18
18
|
text: "panel.defaults.text",
|
|
19
19
|
grid: "panel.defaults.grid",
|
|
20
|
+
viewport: "panel.defaults.viewport",
|
|
20
21
|
image: "panel.defaults.image",
|
|
21
22
|
video: "panel.defaults.video",
|
|
22
23
|
audio: "panel.defaults.audio",
|
|
@@ -70,6 +71,8 @@ export function getDefaultSizeByMaterial(materialType: string) {
|
|
|
70
71
|
return { width: 180, height: 120 };
|
|
71
72
|
case "grid":
|
|
72
73
|
return { width: 320, height: 220 };
|
|
74
|
+
case "viewport":
|
|
75
|
+
return { width: 360, height: 240 };
|
|
73
76
|
case "image":
|
|
74
77
|
return { width: 220, height: 140 };
|
|
75
78
|
case "video":
|
|
@@ -141,6 +144,13 @@ export function getDefaultGridConfig(materialType: string) {
|
|
|
141
144
|
} as const;
|
|
142
145
|
}
|
|
143
146
|
|
|
147
|
+
export function getDefaultViewportConfig(materialType: string) {
|
|
148
|
+
if (materialType !== "viewport") return {};
|
|
149
|
+
return {
|
|
150
|
+
viewportOverflow: "clip" as const,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
144
154
|
export function getDefaultChartConfig(
|
|
145
155
|
materialType: string,
|
|
146
156
|
t: TranslateFn = tFallback
|
|
@@ -26,9 +26,11 @@ export function buildDeepReferenceSnapshot(
|
|
|
26
26
|
const layerNodes = allElements.filter((el) => el.layerId === layerId);
|
|
27
27
|
return layerNodes.map((el) => {
|
|
28
28
|
const cloned = clonePanelElement(el);
|
|
29
|
-
if (cloned.materialType === "reference"
|
|
30
|
-
cloned.
|
|
31
|
-
|
|
29
|
+
if (cloned.materialType === "reference" || cloned.materialType === "viewport") {
|
|
30
|
+
if (cloned.refLayerId) {
|
|
31
|
+
cloned.refCopyMode = "deep";
|
|
32
|
+
cloned.refSnapshot = buildDeepReferenceSnapshot(allElements, cloned.refLayerId, nextVisited);
|
|
33
|
+
}
|
|
32
34
|
}
|
|
33
35
|
return cloned;
|
|
34
36
|
});
|
|
@@ -26,6 +26,24 @@ export function normalizeImportedPanelState(state: unknown): State | null {
|
|
|
26
26
|
return next;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export function createEmptyPanelState(): State {
|
|
30
|
+
return {
|
|
31
|
+
root: {
|
|
32
|
+
id: "root",
|
|
33
|
+
type: "root",
|
|
34
|
+
props: {},
|
|
35
|
+
children: [],
|
|
36
|
+
},
|
|
37
|
+
selectedIds: [],
|
|
38
|
+
variables: {
|
|
39
|
+
counter: 0,
|
|
40
|
+
isOpen: false,
|
|
41
|
+
layers: [DEFAULT_LAYER],
|
|
42
|
+
activeLayerId: DEFAULT_LAYER_ID,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
export function parseAllPanelElements(state: State): PanelElement[] {
|
|
30
48
|
return (state.root.children ?? [])
|
|
31
49
|
.filter((node) => {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export const VIEWPORT_OVERFLOW_MODES = [
|
|
2
|
+
"scroll-x",
|
|
3
|
+
"scroll-y",
|
|
4
|
+
"scroll",
|
|
5
|
+
"clip",
|
|
6
|
+
] as const;
|
|
7
|
+
|
|
8
|
+
export type ViewportOverflowMode = (typeof VIEWPORT_OVERFLOW_MODES)[number];
|
|
9
|
+
|
|
10
|
+
export const DEFAULT_VIEWPORT_OVERFLOW: ViewportOverflowMode = "clip";
|
|
11
|
+
|
|
12
|
+
export function isViewportOverflowMode(
|
|
13
|
+
value: unknown
|
|
14
|
+
): value is ViewportOverflowMode {
|
|
15
|
+
return (
|
|
16
|
+
value === "scroll-x" ||
|
|
17
|
+
value === "scroll-y" ||
|
|
18
|
+
value === "scroll" ||
|
|
19
|
+
value === "clip"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function normalizeViewportOverflow(
|
|
24
|
+
value: unknown
|
|
25
|
+
): ViewportOverflowMode {
|
|
26
|
+
return isViewportOverflowMode(value) ? value : DEFAULT_VIEWPORT_OVERFLOW;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function viewportOverflowStyle(mode: ViewportOverflowMode): {
|
|
30
|
+
overflowX: "hidden" | "auto";
|
|
31
|
+
overflowY: "hidden" | "auto";
|
|
32
|
+
} {
|
|
33
|
+
switch (mode) {
|
|
34
|
+
case "scroll-x":
|
|
35
|
+
return { overflowX: "auto", overflowY: "hidden" };
|
|
36
|
+
case "scroll-y":
|
|
37
|
+
return { overflowX: "hidden", overflowY: "auto" };
|
|
38
|
+
case "scroll":
|
|
39
|
+
return { overflowX: "auto", overflowY: "auto" };
|
|
40
|
+
default:
|
|
41
|
+
return { overflowX: "hidden", overflowY: "hidden" };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function isViewportNode(
|
|
46
|
+
el: { materialType?: string } | undefined
|
|
47
|
+
): boolean {
|
|
48
|
+
return el?.materialType === "viewport";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** 引用节点与视窗节点都通过选择图层来预览内容 */
|
|
52
|
+
export function isLayerPreviewNode(
|
|
53
|
+
el: { materialType?: string } | undefined
|
|
54
|
+
): boolean {
|
|
55
|
+
return el?.materialType === "reference" || el?.materialType === "viewport";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 视窗按自身宽高开窗;预览里节点会被整体拉满视口,
|
|
60
|
+
* 内部引用内容必须用同一套缩放,滚动比例才和编辑态一致。
|
|
61
|
+
*/
|
|
62
|
+
export function viewportWindowContentScale(
|
|
63
|
+
current: { id: string; width: number; height: number },
|
|
64
|
+
originals: ReadonlyArray<{ id: string; width: number; height: number }>
|
|
65
|
+
): { scaleX: number; scaleY: number } {
|
|
66
|
+
const original = originals.find((n) => n.id === current.id);
|
|
67
|
+
const ow = Math.max(1, original?.width ?? current.width);
|
|
68
|
+
const oh = Math.max(1, original?.height ?? current.height);
|
|
69
|
+
return {
|
|
70
|
+
scaleX: Math.max(1, current.width) / ow,
|
|
71
|
+
scaleY: Math.max(1, current.height) / oh,
|
|
72
|
+
};
|
|
73
|
+
}
|