@arronqzy/vue-view 0.1.0 → 0.1.2
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/package.json +9 -6
- package/src/panel/VueViewOnlinePreview.vue +15 -7
- package/src/panel/VueViewPanel.vue +81 -55
- package/src/panel/components/ConfigHintIcon.vue +4 -2
- package/src/panel/components/ElementsLayer.vue +15 -0
- package/src/panel/components/MaterialPreview.vue +19 -1
- package/src/panel/components/MaterialSidebar.vue +35 -31
- package/src/panel/components/MaterialSidebarTreeNode.vue +27 -26
- package/src/panel/components/MoveableLayer.vue +7 -4
- package/src/panel/components/PanelConfigSidebar.vue +57 -39
- package/src/panel/components/ViewElementScopePanel.vue +6 -4
- package/src/panel/components/WorkspaceConfigSidebar.vue +7 -1
- package/src/panel/components/WorkspaceProjectNav.vue +23 -16
- package/src/panel/components/WorkspaceStageSplit.vue +10 -7
- package/src/panel/components/config/ConfigColorField.vue +3 -1
- package/src/panel/components/config/PanelConfigAudioSection.vue +44 -43
- package/src/panel/components/config/PanelConfigChartSection.vue +79 -76
- package/src/panel/components/config/PanelConfigGeometrySection.vue +21 -19
- package/src/panel/components/config/PanelConfigGridChildSpan.vue +7 -5
- package/src/panel/components/config/PanelConfigGridSection.vue +10 -8
- package/src/panel/components/config/PanelConfigImageSection.vue +22 -21
- package/src/panel/components/config/PanelConfigMultiSelect.vue +42 -40
- package/src/panel/components/config/PanelConfigNodeInfo.vue +19 -16
- package/src/panel/components/config/PanelConfigReferenceSection.vue +11 -9
- package/src/panel/components/config/PanelConfigStyleSections.vue +27 -26
- package/src/panel/components/config/PanelConfigTextSection.vue +20 -17
- package/src/panel/components/config/PanelConfigVideoSection.vue +15 -14
- package/src/panel/components/config/shared.ts +0 -3
- package/src/panel/components/elementsLayerNodes.ts +37 -18
- package/src/panel/components/materialSidebarData.ts +73 -54
- package/src/panel/components/scope-config/ScopeTemplatePreviewHost.vue +7 -2
- package/src/panel/components/scope-config/ScopeTemplatePreviewPanel.vue +6 -3
- package/src/panel/components/scope-config/ScopeTemplateUsageHint.vue +7 -16
- package/src/panel/components/scope-config/ScopeTemplateWarningsPanel.vue +4 -2
- package/src/panel/components/table/ConditionEditor.vue +181 -0
- package/src/panel/components/table/JsonCodeEditor.vue +148 -0
- package/src/panel/components/table/PanelConfigTableSection.vue +2033 -0
- package/src/panel/components/table/TableNodeContent.vue +557 -0
- package/src/panel/constants/messages.ts +76 -34
- package/src/panel/hooks/usePanelElements.ts +54 -41
- package/src/panel/hooks/useWorkspaceProjects.ts +8 -5
- package/src/panel/types.ts +4 -0
- package/src/panel/utils/panelElementDefaults.ts +73 -39
- package/src/panel/utils/scope-field-labels.ts +53 -39
- package/src/panel/utils/scope-template-spread.ts +57 -24
- package/src/panel/utils/scope-template-warnings.ts +23 -22
- package/src/panel/utils/scope-template.ts +80 -0
- package/src/tailwind.css +18 -10
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { computed, ref } from "vue";
|
|
3
4
|
import { Card, Empty, Input, Switch, Tabs } from "ant-design-vue";
|
|
4
5
|
import type { PanelElement, PanelLayer, ReferenceCopyMode } from "../types";
|
|
5
|
-
import {
|
|
6
|
+
import { getPanelMessages } from "../constants/messages";
|
|
6
7
|
import {
|
|
7
8
|
concreteGridParentIdForLayer,
|
|
8
9
|
logicalGridParentIdFromConcrete,
|
|
@@ -10,13 +11,16 @@ import {
|
|
|
10
11
|
import MaterialPreview from "./MaterialPreview.vue";
|
|
11
12
|
import MaterialSidebarTreeNode from "./MaterialSidebarTreeNode.vue";
|
|
12
13
|
import {
|
|
13
|
-
|
|
14
|
+
getDefaultCategories,
|
|
14
15
|
getNodeDisplayName,
|
|
15
16
|
themedScrollbarClass,
|
|
16
17
|
type MaterialCategoryId,
|
|
17
18
|
type MaterialItem,
|
|
18
19
|
} from "./materialSidebarData";
|
|
19
20
|
|
|
21
|
+
const { t, locale } = useI18n();
|
|
22
|
+
const msgs = () => getPanelMessages(t);
|
|
23
|
+
|
|
20
24
|
export type MaterialSidebarProps = {
|
|
21
25
|
class?: string;
|
|
22
26
|
onDragMaterialStart?: (material: MaterialItem) => void;
|
|
@@ -50,20 +54,20 @@ const draggingTreeNodeId = ref<string | null>(null);
|
|
|
50
54
|
const dragOverLayerId = ref<string | null>(null);
|
|
51
55
|
const expandedKeys = ref<Record<string, boolean>>({ root: true });
|
|
52
56
|
|
|
53
|
-
const categories =
|
|
57
|
+
const categories = computed(() => { void locale.value; return getDefaultCategories(t); });
|
|
54
58
|
const normalizedKeyword = computed(() => keyword.value.trim().toLowerCase());
|
|
55
59
|
const isSearching = computed(() => normalizedKeyword.value.length > 0);
|
|
56
60
|
const normalizedTreeKeyword = computed(() => treeKeyword.value.trim().toLowerCase());
|
|
57
61
|
const isTreeSearching = computed(() => normalizedTreeKeyword.value.length > 0);
|
|
58
62
|
|
|
59
63
|
const activeCategory = computed(
|
|
60
|
-
() => categories.find((c) => c.id === activeCategoryId.value) ?? categories[0]
|
|
64
|
+
() => categories.value.find((c) => c.id === activeCategoryId.value) ?? categories.value[0]
|
|
61
65
|
);
|
|
62
66
|
|
|
63
67
|
const matchedItems = computed(() => {
|
|
64
68
|
if (!isSearching.value) return [];
|
|
65
69
|
const result: Array<MaterialItem & { categoryTitle: string }> = [];
|
|
66
|
-
categories.forEach((category) => {
|
|
70
|
+
categories.value.forEach((category) => {
|
|
67
71
|
category.items.forEach((item) => {
|
|
68
72
|
const haystack = `${item.title} ${item.id} ${category.title}`.toLowerCase();
|
|
69
73
|
if (haystack.includes(normalizedKeyword.value)) {
|
|
@@ -168,7 +172,7 @@ function hasRefInSubtree(node: PanelElement, visited: Set<string>): boolean {
|
|
|
168
172
|
|
|
169
173
|
function nodeMatchesTreeSearch(node: PanelElement, visited: Set<string>): boolean {
|
|
170
174
|
if (!isTreeSearching.value) return true;
|
|
171
|
-
const selfText = `${getNodeDisplayName(node)} ${node.materialType ?? ""} ${node.id}`.toLowerCase();
|
|
175
|
+
const selfText = `${getNodeDisplayName(node, t)} ${node.materialType ?? ""} ${node.id}`.toLowerCase();
|
|
172
176
|
if (selfText.includes(normalizedTreeKeyword.value)) return true;
|
|
173
177
|
if (visited.has(node.id)) return false;
|
|
174
178
|
const nextVisited = new Set(visited);
|
|
@@ -206,13 +210,13 @@ function getLayerDropState(layer: PanelLayer) {
|
|
|
206
210
|
const dropBlockReason = !draggingNode
|
|
207
211
|
? ""
|
|
208
212
|
: draggingNode.locked
|
|
209
|
-
?
|
|
213
|
+
? msgs().nodeMoveLocked
|
|
210
214
|
: draggingSourceLayer?.locked
|
|
211
|
-
?
|
|
215
|
+
? msgs().nodeMoveSourceLayerLocked
|
|
212
216
|
: layer.locked
|
|
213
|
-
?
|
|
217
|
+
? msgs().nodeMoveTargetLayerLocked
|
|
214
218
|
: draggingNode.layerId === layer.id
|
|
215
|
-
?
|
|
219
|
+
? msgs().nodeMoveSameLayer
|
|
216
220
|
: "";
|
|
217
221
|
const canDropIntoLayer = Boolean(draggingNode) && !dropBlockReason;
|
|
218
222
|
return { draggingNode, dropBlockReason, canDropIntoLayer };
|
|
@@ -278,13 +282,13 @@ const treeSearchEmpty = computed(
|
|
|
278
282
|
<Input
|
|
279
283
|
v-model:value="keyword"
|
|
280
284
|
size="small"
|
|
281
|
-
placeholder="
|
|
285
|
+
:placeholder="t('panel.material.searchPlaceholder')"
|
|
282
286
|
class="text-xs"
|
|
283
287
|
/>
|
|
284
288
|
</div>
|
|
285
289
|
|
|
286
290
|
<Tabs v-model:active-key="leftTab" class="flex min-h-0 h-full flex-col">
|
|
287
|
-
<Tabs.TabPane key="materials" tab="
|
|
291
|
+
<Tabs.TabPane key="materials" :tab="t('panel.material.tabMaterials')" class="min-h-0 flex-1">
|
|
288
292
|
<div class="grid h-full min-h-0 grid-cols-[110px_1fr]">
|
|
289
293
|
<div :class="`overflow-auto border-r border-border ${themedScrollbarClass}`">
|
|
290
294
|
<button
|
|
@@ -305,7 +309,7 @@ const treeSearchEmpty = computed(
|
|
|
305
309
|
|
|
306
310
|
<div :class="`overflow-auto ${themedScrollbarClass}`">
|
|
307
311
|
<div class="px-2.5 py-2.5 text-xs font-semibold">
|
|
308
|
-
{{ isSearching ?
|
|
312
|
+
{{ isSearching ? t("panel.material.searchResults", { count: matchedItems.length }) : activeCategory.title }}
|
|
309
313
|
</div>
|
|
310
314
|
<div class="grid gap-2 px-2.5 pb-3">
|
|
311
315
|
<button
|
|
@@ -332,12 +336,12 @@ const treeSearchEmpty = computed(
|
|
|
332
336
|
<Empty
|
|
333
337
|
v-if="isSearching && matchedItems.length === 0"
|
|
334
338
|
class="py-5"
|
|
335
|
-
description="
|
|
339
|
+
:description="t('panel.material.emptyMaterialsTitle')"
|
|
336
340
|
>
|
|
337
341
|
<template #description>
|
|
338
|
-
<span class="text-xs"
|
|
342
|
+
<span class="text-xs">{{ t("panel.material.emptyMaterialsTitle") }}</span>
|
|
339
343
|
<div class="text-[11px] text-muted-foreground">
|
|
340
|
-
|
|
344
|
+
{{ t("panel.material.emptyMaterialsDesc") }}
|
|
341
345
|
</div>
|
|
342
346
|
</template>
|
|
343
347
|
</Empty>
|
|
@@ -346,19 +350,19 @@ const treeSearchEmpty = computed(
|
|
|
346
350
|
</div>
|
|
347
351
|
</Tabs.TabPane>
|
|
348
352
|
|
|
349
|
-
<Tabs.TabPane key="tree" tab="
|
|
353
|
+
<Tabs.TabPane key="tree" :tab="t('panel.material.tabTree')" class="min-h-0 flex-1">
|
|
350
354
|
<div :class="`h-full overflow-auto px-2 py-2 text-xs ${themedScrollbarClass}`">
|
|
351
355
|
<div class="mb-2">
|
|
352
356
|
<Input
|
|
353
357
|
v-model:value="treeKeyword"
|
|
354
358
|
size="small"
|
|
355
|
-
placeholder="
|
|
359
|
+
:placeholder="t('panel.material.treeSearchPlaceholder')"
|
|
356
360
|
class="text-xs"
|
|
357
361
|
/>
|
|
358
362
|
</div>
|
|
359
363
|
<div class="mb-2 flex items-center justify-between rounded border border-border bg-card px-2 py-1.5">
|
|
360
|
-
<span class="text-[11px] text-muted-foreground"
|
|
361
|
-
<Switch v-model:checked="referenceOnlyTree" size="small" aria-label="
|
|
364
|
+
<span class="text-[11px] text-muted-foreground">{{ t("panel.material.referenceOnlyTree") }}</span>
|
|
365
|
+
<Switch v-model:checked="referenceOnlyTree" size="small" :aria-label="t('panel.material.referenceOnlyTree')" />
|
|
362
366
|
</div>
|
|
363
367
|
|
|
364
368
|
<div class="rounded border border-border bg-card">
|
|
@@ -402,7 +406,7 @@ const treeSearchEmpty = computed(
|
|
|
402
406
|
]"
|
|
403
407
|
:title="
|
|
404
408
|
getLayerDropState(layer).canDropIntoLayer
|
|
405
|
-
? '
|
|
409
|
+
? t('panel.material.targetLayer')
|
|
406
410
|
: getLayerDropState(layer).dropBlockReason
|
|
407
411
|
"
|
|
408
412
|
>
|
|
@@ -429,7 +433,7 @@ const treeSearchEmpty = computed(
|
|
|
429
433
|
v-if="layer.isMapping"
|
|
430
434
|
class="shrink-0 rounded-md border-2 border-violet-600 bg-violet-500/22 px-1.5 py-0.5 text-[10px] font-semibold text-violet-950 dark:border-violet-400 dark:bg-violet-500/35 dark:text-violet-50"
|
|
431
435
|
>
|
|
432
|
-
|
|
436
|
+
{{ t("panel.material.mappingLayer") }}
|
|
433
437
|
</span>
|
|
434
438
|
<span
|
|
435
439
|
v-if="dragOverLayerId === layer.id"
|
|
@@ -442,7 +446,7 @@ const treeSearchEmpty = computed(
|
|
|
442
446
|
>
|
|
443
447
|
{{
|
|
444
448
|
getLayerDropState(layer).canDropIntoLayer
|
|
445
|
-
? "
|
|
449
|
+
? t("panel.material.willMoveToLayer")
|
|
446
450
|
: getLayerDropState(layer).dropBlockReason
|
|
447
451
|
}}
|
|
448
452
|
</span>
|
|
@@ -457,7 +461,7 @@ const treeSearchEmpty = computed(
|
|
|
457
461
|
: 'border-destructive/50 bg-destructive/10 text-destructive'
|
|
458
462
|
: 'border-border/50 bg-muted/20 text-muted-foreground hover:border-border hover:bg-muted/35',
|
|
459
463
|
]"
|
|
460
|
-
title="
|
|
464
|
+
:title="t('panel.material.dragToThisLayer')"
|
|
461
465
|
@dragover="onLayerDragOver($event, layer)"
|
|
462
466
|
@dragleave="dragOverLayerId === layer.id && (dragOverLayerId = null)"
|
|
463
467
|
@drop="onLayerDrop($event, layer)"
|
|
@@ -465,9 +469,9 @@ const treeSearchEmpty = computed(
|
|
|
465
469
|
{{
|
|
466
470
|
draggingTreeNodeId
|
|
467
471
|
? getLayerDropState(layer).canDropIntoLayer
|
|
468
|
-
? "
|
|
469
|
-
: getLayerDropState(layer).dropBlockReason || "
|
|
470
|
-
: "
|
|
472
|
+
? t("panel.material.releaseToMove")
|
|
473
|
+
: getLayerDropState(layer).dropBlockReason || t("panel.material.cannotMoveToLayer")
|
|
474
|
+
: t("panel.material.dragToLayer")
|
|
471
475
|
}}
|
|
472
476
|
</div>
|
|
473
477
|
|
|
@@ -476,7 +480,7 @@ const treeSearchEmpty = computed(
|
|
|
476
480
|
v-if="getRootNodes(layer.id).length === 0"
|
|
477
481
|
class="rounded border border-border/40 bg-muted/15 py-2 pl-3 text-[11px] text-muted-foreground"
|
|
478
482
|
>
|
|
479
|
-
|
|
483
|
+
{{ t("panel.material.emptyLayer") }}
|
|
480
484
|
</div>
|
|
481
485
|
<MaterialSidebarTreeNode
|
|
482
486
|
v-for="node in getRootNodes(layer.id)"
|
|
@@ -509,11 +513,11 @@ const treeSearchEmpty = computed(
|
|
|
509
513
|
</div>
|
|
510
514
|
</template>
|
|
511
515
|
|
|
512
|
-
<Empty v-if="treeSearchEmpty" class="mx-2 my-2 py-5" description="
|
|
516
|
+
<Empty v-if="treeSearchEmpty" class="mx-2 my-2 py-5" :description="t('panel.material.emptyNodesTitle')">
|
|
513
517
|
<template #description>
|
|
514
|
-
<span class="text-xs"
|
|
518
|
+
<span class="text-xs">{{ t("panel.material.emptyNodesTitle") }}</span>
|
|
515
519
|
<div class="text-[11px] text-muted-foreground">
|
|
516
|
-
|
|
520
|
+
{{ t("panel.material.emptyNodesDesc") }}
|
|
517
521
|
</div>
|
|
518
522
|
</template>
|
|
519
523
|
</Empty>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import { computed } from "vue";
|
|
3
4
|
import { Card, Tooltip } from "ant-design-vue";
|
|
4
5
|
import type { PanelElement, PanelLayer, ReferenceCopyMode } from "../types";
|
|
@@ -7,6 +8,8 @@ import {
|
|
|
7
8
|
getNodeDisplayName,
|
|
8
9
|
} from "./materialSidebarData";
|
|
9
10
|
|
|
11
|
+
const { t, locale } = useI18n();
|
|
12
|
+
|
|
10
13
|
const props = defineProps<{
|
|
11
14
|
node: PanelElement;
|
|
12
15
|
level: number;
|
|
@@ -148,7 +151,7 @@ function onDragStart(e: DragEvent) {
|
|
|
148
151
|
@dragstart="onDragStart"
|
|
149
152
|
@dragend="emit('dragEnd')"
|
|
150
153
|
>
|
|
151
|
-
{{ getNodeDisplayName(node) }}
|
|
154
|
+
{{ getNodeDisplayName(node, t) }}
|
|
152
155
|
</button>
|
|
153
156
|
|
|
154
157
|
<span
|
|
@@ -156,30 +159,28 @@ function onDragStart(e: DragEvent) {
|
|
|
156
159
|
class="inline-flex shrink-0 items-center rounded-md border-2 border-violet-600 bg-violet-500/20 px-1.5 py-0.5 text-[10px] font-semibold text-violet-950 shadow-sm dark:border-violet-400 dark:bg-violet-500/35 dark:text-violet-50"
|
|
157
160
|
:title="
|
|
158
161
|
nodeHomeLayer.mappingBaseLayerId
|
|
159
|
-
?
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
? t('panel.material.mappingLayerWithBase', {
|
|
163
|
+
name: nodeHomeLayer.name,
|
|
164
|
+
base:
|
|
165
|
+
layerById.get(nodeHomeLayer.mappingBaseLayerId)?.name ??
|
|
166
|
+
nodeHomeLayer.mappingBaseLayerId,
|
|
167
|
+
})
|
|
168
|
+
: t('panel.material.mappingLayerTitle', { name: nodeHomeLayer.name })
|
|
164
169
|
"
|
|
165
170
|
>
|
|
166
|
-
|
|
171
|
+
{{ t("panel.material.mappingLayerNode") }}
|
|
167
172
|
</span>
|
|
168
173
|
<span
|
|
169
174
|
v-if="node.mappingSourceNodeId"
|
|
170
175
|
class="inline-flex shrink-0 items-center rounded border border-primary/40 bg-primary/10 px-1 text-[10px] text-primary"
|
|
171
|
-
:title="
|
|
172
|
-
node.mappingSourceLayerId
|
|
173
|
-
? ` · ${layerById.get(node.mappingSourceLayerId)?.name ?? node.mappingSourceLayerId}`
|
|
174
|
-
: ''
|
|
175
|
-
}`"
|
|
176
|
+
:title="t('panel.material.sameSourceTitle', { id: node.mappingSourceNodeId })"
|
|
176
177
|
>
|
|
177
|
-
|
|
178
|
+
{{ t("panel.material.sameSource") }}
|
|
178
179
|
</span>
|
|
179
180
|
<span
|
|
180
181
|
v-if="node.locked"
|
|
181
182
|
class="inline-flex h-5 w-5 items-center justify-center rounded border border-border/80 bg-background/80 text-muted-foreground"
|
|
182
|
-
title="
|
|
183
|
+
:title="t('panel.config.nodeLockedTitle')"
|
|
183
184
|
>
|
|
184
185
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" class="h-3.5 w-3.5">
|
|
185
186
|
<rect x="4.5" y="10.5" width="15" height="10" rx="2.5" />
|
|
@@ -196,15 +197,15 @@ function onDragStart(e: DragEvent) {
|
|
|
196
197
|
? 'border-violet-500/50 bg-violet-500/15 text-violet-300'
|
|
197
198
|
: 'border-sky-500/40 bg-sky-500/10 text-sky-300',
|
|
198
199
|
]"
|
|
199
|
-
:title="isDeepRef ? '
|
|
200
|
+
:title="isDeepRef ? t('panel.material.deepCopyTitle') : t('panel.material.shallowCopyTitle')"
|
|
200
201
|
>
|
|
201
|
-
{{ isDeepRef ? "
|
|
202
|
+
{{ isDeepRef ? t("panel.material.deepCopy") : t("panel.material.shallowCopy") }}
|
|
202
203
|
</span>
|
|
203
|
-
<Tooltip title="
|
|
204
|
+
<Tooltip :title="t('panel.material.shallowCopy')">
|
|
204
205
|
<button
|
|
205
206
|
type="button"
|
|
206
207
|
class="inline-flex h-5 w-5 items-center justify-center rounded border border-border hover:bg-accent"
|
|
207
|
-
aria-label="
|
|
208
|
+
:aria-label="t('panel.material.shallowCopy')"
|
|
208
209
|
@click.stop="emit('copyNode', node.id, 'shallow')"
|
|
209
210
|
>
|
|
210
211
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" class="h-3.5 w-3.5">
|
|
@@ -214,11 +215,11 @@ function onDragStart(e: DragEvent) {
|
|
|
214
215
|
</svg>
|
|
215
216
|
</button>
|
|
216
217
|
</Tooltip>
|
|
217
|
-
<Tooltip title="
|
|
218
|
+
<Tooltip :title="t('panel.material.deepCopy')">
|
|
218
219
|
<button
|
|
219
220
|
type="button"
|
|
220
221
|
class="inline-flex h-5 w-5 items-center justify-center rounded border border-border hover:bg-accent"
|
|
221
|
-
aria-label="
|
|
222
|
+
:aria-label="t('panel.material.deepCopy')"
|
|
222
223
|
@click.stop="emit('copyNode', node.id, 'deep')"
|
|
223
224
|
>
|
|
224
225
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" class="h-3.5 w-3.5">
|
|
@@ -229,11 +230,11 @@ function onDragStart(e: DragEvent) {
|
|
|
229
230
|
</button>
|
|
230
231
|
</Tooltip>
|
|
231
232
|
</template>
|
|
232
|
-
<Tooltip v-else title="
|
|
233
|
+
<Tooltip v-else :title="t('panel.material.duplicateNode')">
|
|
233
234
|
<button
|
|
234
235
|
type="button"
|
|
235
236
|
class="inline-flex h-5 w-5 items-center justify-center rounded border border-border hover:bg-accent"
|
|
236
|
-
aria-label="
|
|
237
|
+
:aria-label="t('panel.material.duplicateNode')"
|
|
237
238
|
@click.stop="emit('copyNode', node.id)"
|
|
238
239
|
>
|
|
239
240
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" class="h-3.5 w-3.5">
|
|
@@ -242,12 +243,12 @@ function onDragStart(e: DragEvent) {
|
|
|
242
243
|
</svg>
|
|
243
244
|
</button>
|
|
244
245
|
</Tooltip>
|
|
245
|
-
<Tooltip :title="node.locked ? '
|
|
246
|
+
<Tooltip :title="node.locked ? t('panel.material.lockedNodeCannotDelete') : t('panel.material.deleteNode')">
|
|
246
247
|
<button
|
|
247
248
|
type="button"
|
|
248
249
|
:disabled="node.locked"
|
|
249
250
|
class="inline-flex h-5 w-5 items-center justify-center rounded border border-border hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40"
|
|
250
|
-
:aria-label="node.locked ? '
|
|
251
|
+
:aria-label="node.locked ? t('panel.material.lockedNodeCannotDelete') : t('panel.material.deleteNode')"
|
|
251
252
|
@click.stop="!node.locked && emit('deleteNode', node.id)"
|
|
252
253
|
>
|
|
253
254
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" class="h-3.5 w-3.5">
|
|
@@ -266,9 +267,9 @@ function onDragStart(e: DragEvent) {
|
|
|
266
267
|
v-if="nextVisited.has(child.id)"
|
|
267
268
|
class="py-1 text-[10px] text-muted-foreground/80"
|
|
268
269
|
:style="{ paddingLeft: `${6 + (level + 1) * 14}px` }"
|
|
269
|
-
title="
|
|
270
|
+
:title="t('panel.material.circularRefStopped')"
|
|
270
271
|
>
|
|
271
|
-
{{ getNodeDisplayName(child) }}
|
|
272
|
+
{{ getNodeDisplayName(child, t) }}{{ t("panel.material.circularRefSuffix") }}
|
|
272
273
|
</div>
|
|
273
274
|
<MaterialSidebarTreeNode
|
|
274
275
|
v-else
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "@arronqzy/i18n/vue";
|
|
2
3
|
import {
|
|
3
4
|
computed,
|
|
4
5
|
onMounted,
|
|
@@ -12,6 +13,8 @@ import type { PanelElement } from "../types";
|
|
|
12
13
|
import { uniformViewportZoom } from "../viewportZoom";
|
|
13
14
|
import { notifyPreviewLayoutChanged } from "../utils/panelStateIO";
|
|
14
15
|
|
|
16
|
+
const { t, locale } = useI18n();
|
|
17
|
+
|
|
15
18
|
const props = defineProps<{
|
|
16
19
|
zoomX: number;
|
|
17
20
|
zoomY: number;
|
|
@@ -814,7 +817,7 @@ const showPartialLockBadge = computed(
|
|
|
814
817
|
<div
|
|
815
818
|
class="pointer-events-none absolute z-[80] inline-flex select-none items-center gap-1 rounded border border-border bg-background/95 px-1.5 py-0.5 text-[11px] text-foreground shadow-sm"
|
|
816
819
|
:style="{ left: `${lockBadgeScreen!.x + 6}px`, top: `${lockBadgeScreen!.y - 22}px` }"
|
|
817
|
-
title="
|
|
820
|
+
:title="t('panel.config.nodeLockedTitle')"
|
|
818
821
|
>
|
|
819
822
|
<svg
|
|
820
823
|
viewBox="0 0 24 24"
|
|
@@ -830,14 +833,14 @@ const showPartialLockBadge = computed(
|
|
|
830
833
|
<path d="M8 10.5V8a4 4 0 0 1 8 0v2.5" />
|
|
831
834
|
<circle cx="12" cy="15.5" r="1.2" />
|
|
832
835
|
</svg>
|
|
833
|
-
<span
|
|
836
|
+
<span>{{ t("panel.config.nodeLockedBadge") }}</span>
|
|
834
837
|
</div>
|
|
835
838
|
</Teleport>
|
|
836
839
|
<Teleport v-else-if="pointerRoot && showPartialLockBadge" :to="pointerRoot">
|
|
837
840
|
<div
|
|
838
841
|
class="pointer-events-none absolute z-[80] inline-flex select-none items-center gap-1 rounded border border-border bg-background/95 px-1.5 py-0.5 text-[11px] text-foreground shadow-sm"
|
|
839
842
|
:style="{ left: `${lockBadgeScreen!.x + 6}px`, top: `${lockBadgeScreen!.y - 22}px` }"
|
|
840
|
-
title="
|
|
843
|
+
:title="t('panel.config.lockedExcludedTitle')"
|
|
841
844
|
>
|
|
842
845
|
<svg
|
|
843
846
|
viewBox="0 0 24 24"
|
|
@@ -853,7 +856,7 @@ const showPartialLockBadge = computed(
|
|
|
853
856
|
<path d="M8 10.5V8a4 4 0 0 1 8 0v2.5" />
|
|
854
857
|
<circle cx="12" cy="15.5" r="1.2" />
|
|
855
858
|
</svg>
|
|
856
|
-
<span
|
|
859
|
+
<span>{{ t("panel.config.lockedExcludedBadge") }}</span>
|
|
857
860
|
</div>
|
|
858
861
|
</Teleport>
|
|
859
862
|
</template>
|