@selvajs/ui 6.6.0-beta.14 → 6.6.0-beta.16
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/README.md +0 -3
- package/dist/components/compute/AppLayout.svelte +10 -5
- package/dist/components/compute/CollapsedPanelStrip.svelte +1 -1
- package/dist/components/compute/ParameterPresetManager.svelte +1 -1
- package/dist/components/compute/SolveMessages.svelte +2 -2
- package/dist/components/layout/FooterItemRenderer.svelte +1 -1
- package/dist/components/layout/PageFooter.svelte +2 -2
- package/dist/components/layout/PageHeader.svelte +1 -1
- package/dist/components/layout/SideNav.svelte +3 -3
- package/dist/components/layout/SubNav.svelte +2 -2
- package/dist/components/preview/ChartOutput.svelte +3 -3
- package/dist/components/preview/Group.svelte +7 -7
- package/dist/components/preview/ImageOutput.svelte +6 -6
- package/dist/components/preview/InputControl.svelte +1 -0
- package/dist/components/preview/OutputDisplay.svelte +8 -6
- package/dist/components/preview/TabBar.svelte +6 -4
- package/dist/components/preview/TabBar.svelte.d.ts +2 -0
- package/dist/components/preview/TabContent.svelte +1 -1
- package/dist/components/preview/TabLayout.svelte +3 -4
- package/dist/components/preview/inputs/ChecklistInput.svelte +3 -3
- package/dist/components/preview/inputs/ColorInput.svelte +356 -14
- package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
- package/dist/components/preview/inputs/FileInput.svelte +3 -3
- package/dist/components/preview/inputs/SegmentedInput.svelte +2 -1
- package/dist/components/preview/inputs/TileInput.svelte +3 -2
- package/dist/components/primitives/CalculateButton.svelte +2 -2
- package/dist/components/primitives/Callout.svelte +7 -5
- package/dist/components/primitives/Callout.svelte.d.ts +4 -4
- package/dist/components/primitives/DataTable.svelte +1 -1
- package/dist/components/primitives/ImageUploadField.svelte +1 -1
- package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/components/primitives/badge/badge.svelte +2 -2
- package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
- package/dist/components/primitives/button/button.svelte +6 -7
- package/dist/components/primitives/button/button.svelte.d.ts +18 -18
- package/dist/components/primitives/card/card.svelte +1 -1
- package/dist/components/primitives/card/card.svelte.d.ts +1 -1
- package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
- package/dist/components/primitives/command/command-input.svelte +1 -1
- package/dist/components/primitives/command/command-item.svelte +1 -1
- package/dist/components/primitives/command/command-link-item.svelte +1 -1
- package/dist/components/primitives/command/command.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/dialog/dialog-content.svelte +2 -2
- package/dist/components/primitives/drawer/Drawer.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
- package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
- package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.js +1 -1
- package/dist/components/primitives/input/input.svelte +2 -2
- package/dist/components/primitives/input-group/input-group.svelte +1 -1
- package/dist/components/primitives/popover/popover-content.svelte +1 -1
- package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
- package/dist/components/primitives/search/search.svelte +1 -1
- package/dist/components/primitives/select/select-content.svelte +1 -1
- package/dist/components/primitives/select/select-item.svelte +1 -1
- package/dist/components/primitives/select/select-trigger.svelte +1 -1
- package/dist/components/primitives/slider/slider.svelte +1 -1
- package/dist/components/primitives/switch/switch.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-list.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +3 -3
- package/dist/components/primitives/tabs/tabs-trigger.svelte +1 -1
- package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +3 -3
- package/dist/components/primitives/textarea/textarea.svelte +1 -1
- package/dist/components/primitives/toggle/toggle.svelte +8 -2
- package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -4
- package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
- package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
- package/dist/components/primitives/tooltip/index.d.ts +6 -0
- package/dist/components/primitives/tooltip/index.js +8 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
- package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/components/viewer/MeshMetadataPanel.svelte +1 -1
- package/dist/components/viewer/SceneManager.svelte +19 -19
- package/dist/components/viewer/Viewer.svelte +90 -164
- package/dist/components/viewer/Viewer.svelte.d.ts +3 -1
- package/dist/components/viewer/ViewerDock.svelte +404 -0
- package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
- package/dist/i18n/messages.d.ts +12 -0
- package/dist/i18n/messages.js +20 -0
- package/dist/styles/base.css +81 -80
- package/dist/utils/color-space.d.ts +21 -0
- package/dist/utils/color-space.js +90 -0
- package/package.json +12 -13
- package/src/lib/components/compute/AppLayout.svelte +10 -5
- package/src/lib/components/compute/CollapsedPanelStrip.svelte +1 -1
- package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
- package/src/lib/components/compute/SolveMessages.svelte +2 -2
- package/src/lib/components/layout/FooterItemRenderer.svelte +1 -1
- package/src/lib/components/layout/PageFooter.svelte +2 -2
- package/src/lib/components/layout/PageHeader.svelte +1 -1
- package/src/lib/components/layout/SideNav.svelte +3 -3
- package/src/lib/components/layout/SubNav.svelte +2 -2
- package/src/lib/components/preview/ChartOutput.svelte +3 -3
- package/src/lib/components/preview/Group.svelte +7 -7
- package/src/lib/components/preview/ImageOutput.svelte +6 -6
- package/src/lib/components/preview/InputControl.svelte +1 -0
- package/src/lib/components/preview/OutputDisplay.svelte +8 -6
- package/src/lib/components/preview/TabBar.svelte +6 -4
- package/src/lib/components/preview/TabContent.svelte +1 -1
- package/src/lib/components/preview/TabLayout.svelte +3 -4
- package/src/lib/components/preview/inputs/ChecklistInput.svelte +3 -3
- package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
- package/src/lib/components/preview/inputs/FileInput.svelte +3 -3
- package/src/lib/components/preview/inputs/SegmentedInput.svelte +2 -1
- package/src/lib/components/preview/inputs/TileInput.svelte +3 -2
- package/src/lib/components/primitives/CalculateButton.svelte +2 -2
- package/src/lib/components/primitives/Callout.svelte +7 -5
- package/src/lib/components/primitives/DataTable.svelte +1 -1
- package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
- package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
- package/src/lib/components/primitives/badge/badge.svelte +2 -2
- package/src/lib/components/primitives/button/button.svelte +6 -7
- package/src/lib/components/primitives/card/card.svelte +1 -1
- package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
- package/src/lib/components/primitives/command/command-input.svelte +1 -1
- package/src/lib/components/primitives/command/command-item.svelte +1 -1
- package/src/lib/components/primitives/command/command-link-item.svelte +1 -1
- package/src/lib/components/primitives/command/command.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
- package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
- package/src/lib/components/primitives/dialog/dialog-content.svelte +2 -2
- package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
- package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
- package/src/lib/components/primitives/index.ts +1 -1
- package/src/lib/components/primitives/input/input.svelte +2 -2
- package/src/lib/components/primitives/input-group/input-group.svelte +1 -1
- package/src/lib/components/primitives/popover/popover-content.svelte +1 -1
- package/src/lib/components/primitives/resizable/resizable-handle.svelte +2 -2
- package/src/lib/components/primitives/search/search.svelte +1 -1
- package/src/lib/components/primitives/select/select-content.svelte +1 -1
- package/src/lib/components/primitives/select/select-item.svelte +1 -1
- package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
- package/src/lib/components/primitives/slider/slider.svelte +1 -1
- package/src/lib/components/primitives/switch/switch.svelte +1 -1
- package/src/lib/components/primitives/tabs/tabs-list.svelte +1 -1
- package/src/lib/components/primitives/tabs/tabs-trigger.svelte +1 -1
- package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
- package/src/lib/components/primitives/toggle/toggle.svelte +8 -2
- package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
- package/src/lib/components/primitives/toggle-group/toggle-group.svelte +1 -1
- package/src/lib/components/primitives/tooltip/index.ts +19 -0
- package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
- package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
- package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
- package/src/lib/components/viewer/MeshMetadataPanel.svelte +1 -1
- package/src/lib/components/viewer/SceneManager.svelte +19 -19
- package/src/lib/components/viewer/Viewer.svelte +90 -164
- package/src/lib/components/viewer/ViewerDock.svelte +404 -0
- package/src/lib/i18n/messages.ts +32 -0
- package/src/lib/styles/base.css +81 -80
- package/src/lib/utils/color-space.ts +107 -0
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
- package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
- package/dist/components/primitives/theme-switcher/index.js +0 -1
- package/dist/styles/themes/cyberpunk.css +0 -98
- package/dist/styles/themes/neutral.css +0 -72
- package/dist/styles/themes/ocean.css +0 -75
- package/dist/styles/themes/selva.css +0 -105
- package/dist/theme/themeStore.svelte.d.ts +0 -12
- package/dist/theme/themeStore.svelte.js +0 -40
- package/dist/theme/themes.d.ts +0 -5
- package/dist/theme/themes.js +0 -13
- package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
- package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
- package/src/lib/styles/themes/cyberpunk.css +0 -98
- package/src/lib/styles/themes/neutral.css +0 -72
- package/src/lib/styles/themes/ocean.css +0 -75
- package/src/lib/styles/themes/selva.css +0 -105
- package/src/lib/theme/themeStore.svelte.ts +0 -50
- package/src/lib/theme/themes.ts +0 -18
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
data-size={ctx.size || size}
|
|
24
24
|
data-spacing={ctx.spacing}
|
|
25
25
|
class={cn(
|
|
26
|
-
'group-data-[spacing=0]/toggle-group:px-2 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 shrink-0 group-data-[spacing=0]/toggle-group:rounded-none focus:z-10 focus-visible:z-10 group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:first:rounded-l-
|
|
26
|
+
'group-data-[spacing=0]/toggle-group:px-2 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 shrink-0 group-data-[spacing=0]/toggle-group:rounded-none focus:z-10 focus-visible:z-10 group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:first:rounded-l-md group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:first:rounded-t-md group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:last:rounded-r-md group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:last:rounded-b-md group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:data-[variant=accent]:border-l-0 group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=accent]:border-t-0 group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:data-[variant=accent]:first:border-l group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=accent]:first:border-t group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-[orientation=horizontal]/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t',
|
|
27
27
|
toggleVariants({
|
|
28
28
|
variant: ctx.variant || variant,
|
|
29
29
|
size: ctx.size || size
|
|
@@ -68,7 +68,7 @@ get along, so we shut typescript up by casting `value` to `never`.
|
|
|
68
68
|
data-spacing={spacing}
|
|
69
69
|
style="--gap: calc(var(--spacing) * {spacing})"
|
|
70
70
|
class={cn(
|
|
71
|
-
'group/toggle-group flex w-fit flex-row items-center gap-(--gap) rounded-
|
|
71
|
+
'group/toggle-group data-[variant=segmented]:p-0.5 flex w-fit flex-row items-center gap-(--gap) rounded-md data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch data-[variant=segmented]:border data-[variant=segmented]:border-input data-[variant=segmented]:bg-muted',
|
|
72
72
|
className
|
|
73
73
|
)}
|
|
74
74
|
{...restProps}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Content from './tooltip-content.svelte';
|
|
2
|
+
import Portal from './tooltip-portal.svelte';
|
|
3
|
+
import Provider from './tooltip-provider.svelte';
|
|
4
|
+
import Trigger from './tooltip-trigger.svelte';
|
|
5
|
+
import Root from './tooltip.svelte';
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
Root,
|
|
9
|
+
Content,
|
|
10
|
+
Provider,
|
|
11
|
+
Portal,
|
|
12
|
+
Trigger,
|
|
13
|
+
//
|
|
14
|
+
Root as Tooltip,
|
|
15
|
+
Content as TooltipContent,
|
|
16
|
+
Provider as TooltipProvider,
|
|
17
|
+
Portal as TooltipPortal,
|
|
18
|
+
Trigger as TooltipTrigger
|
|
19
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Tooltip as TooltipPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
|
|
4
|
+
import TooltipPortal from './tooltip-portal.svelte';
|
|
5
|
+
import type { ComponentProps } from 'svelte';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
ref = $bindable(null),
|
|
9
|
+
class: className,
|
|
10
|
+
sideOffset = 6,
|
|
11
|
+
side = 'top',
|
|
12
|
+
children,
|
|
13
|
+
portalProps,
|
|
14
|
+
...restProps
|
|
15
|
+
}: TooltipPrimitive.ContentProps & {
|
|
16
|
+
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof TooltipPortal>>;
|
|
17
|
+
} = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<TooltipPortal {...portalProps}>
|
|
21
|
+
<TooltipPrimitive.Content
|
|
22
|
+
bind:ref
|
|
23
|
+
data-slot="tooltip-content"
|
|
24
|
+
{sideOffset}
|
|
25
|
+
{side}
|
|
26
|
+
class={cn(
|
|
27
|
+
'data-[state=delayed-open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=delayed-open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=delayed-open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 px-2.5 py-1.5 text-xs font-medium z-50 w-fit origin-(--bits-tooltip-content-transform-origin) rounded-md bg-foreground text-balance text-background',
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
{...restProps}
|
|
31
|
+
>
|
|
32
|
+
{@render children?.()}
|
|
33
|
+
</TooltipPrimitive.Content>
|
|
34
|
+
</TooltipPortal>
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
<table class="text-xs w-full border-collapse">
|
|
66
66
|
<tbody>
|
|
67
67
|
{#each Object.entries(filteredMetadata) as [key, value] (key)}
|
|
68
|
-
<tr class="border-b border-border
|
|
68
|
+
<tr class="border-b border-border last:border-b-0">
|
|
69
69
|
<th
|
|
70
70
|
scope="row"
|
|
71
71
|
class="px-4 py-2 font-normal text-left align-top whitespace-nowrap text-muted-foreground"
|
|
@@ -225,16 +225,16 @@
|
|
|
225
225
|
onmousedown={() => outliner.selection.clear()}
|
|
226
226
|
>
|
|
227
227
|
<div class="px-3 py-2 gap-2 flex items-center border-b border-border">
|
|
228
|
-
<Search class="h-3.5 w-3.5 shrink-0 text-
|
|
228
|
+
<Search class="h-3.5 w-3.5 shrink-0 text-faint-foreground" />
|
|
229
229
|
<input
|
|
230
|
-
class="min-w-0 text-xs flex-1 bg-transparent text-foreground outline-none placeholder:text-
|
|
230
|
+
class="min-w-0 text-xs flex-1 bg-transparent text-foreground outline-none placeholder:text-faint-foreground"
|
|
231
231
|
placeholder={t.searchObjects}
|
|
232
232
|
bind:value={searchQuery}
|
|
233
233
|
/>
|
|
234
234
|
{#if searchQuery}
|
|
235
235
|
<button onclick={() => (searchQuery = '')} aria-label={t.clearSearch}>
|
|
236
236
|
<X
|
|
237
|
-
class="h-3.5 w-3.5 text-
|
|
237
|
+
class="h-3.5 w-3.5 text-faint-foreground transition-colors hover:text-muted-foreground"
|
|
238
238
|
/>
|
|
239
239
|
</button>
|
|
240
240
|
{/if}
|
|
@@ -247,11 +247,11 @@
|
|
|
247
247
|
>
|
|
248
248
|
{#if allCollapsed}
|
|
249
249
|
<ChevronsUpDown
|
|
250
|
-
class="h-3.5 w-3.5 text-
|
|
250
|
+
class="h-3.5 w-3.5 text-faint-foreground transition-colors hover:text-muted-foreground"
|
|
251
251
|
/>
|
|
252
252
|
{:else}
|
|
253
253
|
<ChevronsDownUp
|
|
254
|
-
class="h-3.5 w-3.5 text-
|
|
254
|
+
class="h-3.5 w-3.5 text-faint-foreground transition-colors hover:text-muted-foreground"
|
|
255
255
|
/>
|
|
256
256
|
{/if}
|
|
257
257
|
</button>
|
|
@@ -285,10 +285,10 @@
|
|
|
285
285
|
{@const isCollapsed = collapsed.has(row.layerName)}
|
|
286
286
|
|
|
287
287
|
<div
|
|
288
|
-
class="gap-1 pl-1 pr-2 group flex h-full items-center transition-colors hover:bg-
|
|
288
|
+
class="gap-1 pl-1 pr-2 group flex h-full items-center transition-colors hover:bg-hover"
|
|
289
289
|
>
|
|
290
290
|
<button
|
|
291
|
-
class="
|
|
291
|
+
class="p-0.5 shrink-0 rounded-sm text-muted-foreground transition-colors hover:text-muted-foreground"
|
|
292
292
|
onclick={() => outliner.toggleCollapsed(row.layerName)}
|
|
293
293
|
aria-label={isCollapsed ? t.expandLayer : t.collapseLayer}
|
|
294
294
|
>
|
|
@@ -300,15 +300,15 @@
|
|
|
300
300
|
</button>
|
|
301
301
|
|
|
302
302
|
<button
|
|
303
|
-
class="
|
|
303
|
+
class="p-1 shrink-0 rounded-sm transition-colors hover:bg-hover"
|
|
304
304
|
onclick={() => toggleLayer(entries)}
|
|
305
305
|
title={layerHidden ? t.showLayer : t.hideLayer}
|
|
306
306
|
aria-label={layerHidden ? t.showLayer : t.hideLayer}
|
|
307
307
|
>
|
|
308
308
|
{#if layerHidden}
|
|
309
|
-
<EyeOff class="h-3.5 w-3.5 text-
|
|
309
|
+
<EyeOff class="h-3.5 w-3.5 text-faint-foreground" />
|
|
310
310
|
{:else if layerPartial}
|
|
311
|
-
<Eye class="h-3.5 w-3.5 text-
|
|
311
|
+
<Eye class="h-3.5 w-3.5 text-faint-foreground" />
|
|
312
312
|
{:else}
|
|
313
313
|
<Eye class="h-3.5 w-3.5 text-muted-foreground" />
|
|
314
314
|
{/if}
|
|
@@ -316,13 +316,13 @@
|
|
|
316
316
|
|
|
317
317
|
<span
|
|
318
318
|
class="min-w-0 text-xs font-medium flex-1 truncate {layerHidden
|
|
319
|
-
? 'text-
|
|
319
|
+
? 'text-faint-foreground line-through'
|
|
320
320
|
: 'text-foreground'}"
|
|
321
321
|
>
|
|
322
322
|
{row.layerName}
|
|
323
323
|
</span>
|
|
324
324
|
|
|
325
|
-
<span class="shrink-0 text-2xs text-
|
|
325
|
+
<span class="shrink-0 text-2xs text-faint-foreground tabular-nums">
|
|
326
326
|
{entries.length}
|
|
327
327
|
</span>
|
|
328
328
|
</div>
|
|
@@ -338,7 +338,7 @@
|
|
|
338
338
|
aria-selected={isSelected}
|
|
339
339
|
tabindex="-1"
|
|
340
340
|
class="gap-1.5 pl-5 pr-2 flex h-full cursor-pointer items-center transition-colors
|
|
341
|
-
{isSelected ? 'bg-primary/10 hover:bg-primary/15' : 'hover:bg-
|
|
341
|
+
{isSelected ? 'bg-primary/10 hover:bg-primary/15' : 'hover:bg-hover'}
|
|
342
342
|
{isHidden ? 'opacity-40' : ''}"
|
|
343
343
|
onmouseenter={() => onHover?.(entry)}
|
|
344
344
|
onmouseleave={() => onHover?.(null)}
|
|
@@ -351,7 +351,7 @@
|
|
|
351
351
|
e.key === 'Enter' && selectObject(entry.key, e as unknown as MouseEvent)}
|
|
352
352
|
>
|
|
353
353
|
<button
|
|
354
|
-
class="
|
|
354
|
+
class="p-1 shrink-0 rounded-sm transition-colors hover:bg-hover"
|
|
355
355
|
onclick={(e) => {
|
|
356
356
|
e.stopPropagation();
|
|
357
357
|
toggleEntry(entry);
|
|
@@ -360,7 +360,7 @@
|
|
|
360
360
|
aria-label={isHidden ? t.showObject : t.hideObject}
|
|
361
361
|
>
|
|
362
362
|
{#if isHidden}
|
|
363
|
-
<EyeOff class="h-3 w-3 text-
|
|
363
|
+
<EyeOff class="h-3 w-3 text-faint-foreground" />
|
|
364
364
|
{:else}
|
|
365
365
|
<Eye class="h-3 w-3 text-muted-foreground" />
|
|
366
366
|
{/if}
|
|
@@ -369,13 +369,13 @@
|
|
|
369
369
|
<span
|
|
370
370
|
class="min-w-0 text-xs flex-1 truncate {isHidden
|
|
371
371
|
? 'text-muted-foreground line-through'
|
|
372
|
-
: 'text-foreground
|
|
372
|
+
: 'text-foreground'}"
|
|
373
373
|
>
|
|
374
374
|
{entry.label}
|
|
375
375
|
</span>
|
|
376
376
|
|
|
377
377
|
<span
|
|
378
|
-
class="
|
|
378
|
+
class="px-1 py-0.5 font-medium shrink-0 rounded-sm bg-muted text-2xs text-faint-foreground"
|
|
379
379
|
>
|
|
380
380
|
{getTypeLabel(entry.object)}
|
|
381
381
|
</span>
|
|
@@ -388,12 +388,12 @@
|
|
|
388
388
|
|
|
389
389
|
{#if sceneObjects.length === 0}
|
|
390
390
|
<div class="py-12 flex flex-col items-center justify-center text-center">
|
|
391
|
-
<EyeOff class="mb-2 h-5 w-5 text-
|
|
391
|
+
<EyeOff class="mb-2 h-5 w-5 text-faint-foreground" />
|
|
392
392
|
<p class="text-xs text-muted-foreground">{t.noObjects}</p>
|
|
393
393
|
</div>
|
|
394
394
|
{:else if layerGroups.size === 0}
|
|
395
395
|
<div class="py-12 flex flex-col items-center justify-center text-center">
|
|
396
|
-
<Search class="mb-2 h-5 w-5 text-
|
|
396
|
+
<Search class="mb-2 h-5 w-5 text-faint-foreground" />
|
|
397
397
|
<p class="text-xs text-muted-foreground">
|
|
398
398
|
{t.noResultsFor.replace('{query}', searchQuery)}
|
|
399
399
|
</p>
|
|
@@ -15,30 +15,15 @@
|
|
|
15
15
|
type Grid,
|
|
16
16
|
type ThreeViewer
|
|
17
17
|
} from '@selvajs/visualization/render';
|
|
18
|
-
import {
|
|
19
|
-
Maximize,
|
|
20
|
-
Minimize,
|
|
21
|
-
Camera,
|
|
22
|
-
Layers,
|
|
23
|
-
Settings2,
|
|
24
|
-
Box,
|
|
25
|
-
Square,
|
|
26
|
-
Frame,
|
|
27
|
-
Ruler,
|
|
28
|
-
Grid3x3,
|
|
29
|
-
Palette,
|
|
30
|
-
Spline
|
|
31
|
-
} from '@lucide/svelte';
|
|
32
18
|
import { SvelteSet } from 'svelte/reactivity';
|
|
33
19
|
import type * as THREE from 'three';
|
|
34
20
|
import type { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
35
21
|
import { createSceneOutliner, type SceneOutliner } from '@selvajs/visualization/scene';
|
|
36
22
|
import { clearGeometryCache } from '@selvajs/visualization/parse';
|
|
37
23
|
import SceneManager from './SceneManager.svelte';
|
|
24
|
+
import ViewerDock from './ViewerDock.svelte';
|
|
38
25
|
import MeshMetadataPanel from './MeshMetadataPanel.svelte';
|
|
39
26
|
import * as Resizable from '$lib/components/primitives/resizable/index.js';
|
|
40
|
-
import * as DropdownMenu from '$lib/components/primitives/dropdown-menu/index.js';
|
|
41
|
-
import { Button } from '$lib/components/primitives/button/index.js';
|
|
42
27
|
import type { Locale } from '$lib/i18n/messages';
|
|
43
28
|
import { layerLocaleContext } from '$lib/i18n/localeContext.svelte';
|
|
44
29
|
import { saveBlob } from '$lib/utils/host-files';
|
|
@@ -52,6 +37,8 @@
|
|
|
52
37
|
showDisplayMenu?: boolean;
|
|
53
38
|
enableMeshClick?: boolean;
|
|
54
39
|
backgroundColor?: string;
|
|
40
|
+
/** The look to open in. Default `technical`. */
|
|
41
|
+
look?: Look;
|
|
55
42
|
/** Initial state of the edge overlay and its display-menu checkmark. Default false. */
|
|
56
43
|
showEdges?: boolean;
|
|
57
44
|
}
|
|
@@ -91,6 +78,7 @@
|
|
|
91
78
|
showDisplayMenu: true,
|
|
92
79
|
enableMeshClick: true,
|
|
93
80
|
backgroundColor: '#E6E6E6',
|
|
81
|
+
look: 'technical',
|
|
94
82
|
showEdges: false
|
|
95
83
|
};
|
|
96
84
|
|
|
@@ -124,7 +112,8 @@
|
|
|
124
112
|
let clearEdges: ThreeViewer['clearEdges'] | null = null;
|
|
125
113
|
let invalidate: (() => void) | null = null;
|
|
126
114
|
let captureImage: ThreeViewer['captureImage'] | null = null;
|
|
127
|
-
let setLook:
|
|
115
|
+
let setLook: ThreeViewer['setLook'] | null = null;
|
|
116
|
+
let syncEmissiveLights: (() => void) | null = null;
|
|
128
117
|
let updateGridScale: (() => void) | null = null;
|
|
129
118
|
let updateShadowBounds: (() => void) | null = null;
|
|
130
119
|
let fitToView: (() => void) | null = null;
|
|
@@ -145,9 +134,16 @@
|
|
|
145
134
|
let projection: CameraProjection = $state('perspective');
|
|
146
135
|
let measureActive = $state(false);
|
|
147
136
|
let gridVisible = $state(false);
|
|
148
|
-
|
|
137
|
+
// A saved schema can name a look this build doesn't have, and an unknown look throws on mount.
|
|
138
|
+
const openingLook = untrack(() => {
|
|
139
|
+
const look = viewerConfig.look;
|
|
140
|
+
return look && LOOKS.includes(look) ? look : defaultViewerConfig.look;
|
|
141
|
+
});
|
|
142
|
+
const opensAsLineDrawing = LOOK_PRESETS[openingLook].requiresEdges === true;
|
|
143
|
+
const configuredEdges = untrack(() => viewerConfig.showEdges) ?? defaultViewerConfig.showEdges;
|
|
144
|
+
let renderStyle: Look = $state(openingLook);
|
|
149
145
|
// Seeded once, then owned by the menu toggle.
|
|
150
|
-
let edgesVisible = $state(
|
|
146
|
+
let edgesVisible = $state(opensAsLineDrawing || configuredEdges);
|
|
151
147
|
let selectedMeshMetadata: Record<string, any> | null = $state(null);
|
|
152
148
|
let selectedMeshName: string | null = $state(null);
|
|
153
149
|
|
|
@@ -160,14 +156,19 @@
|
|
|
160
156
|
arctic: t.lookArctic,
|
|
161
157
|
xray: t.lookXray,
|
|
162
158
|
lineart: t.lookLineart,
|
|
163
|
-
wireframe: t.lookWireframe
|
|
159
|
+
wireframe: t.lookWireframe,
|
|
160
|
+
night: t.lookNight
|
|
164
161
|
});
|
|
162
|
+
// Night has its own toggle, so it stays out of the radio list.
|
|
165
163
|
const styleOptions = $derived<{ look: Look; label: string }[]>(
|
|
166
|
-
LOOKS.map((look) => ({
|
|
164
|
+
LOOKS.filter((look) => look !== 'night').map((look) => ({
|
|
167
165
|
look,
|
|
168
166
|
label: lookLabels[look] ?? look.charAt(0).toUpperCase() + look.slice(1)
|
|
169
167
|
}))
|
|
170
168
|
);
|
|
169
|
+
const nightOn = $derived(renderStyle === 'night');
|
|
170
|
+
// What the night toggle returns to.
|
|
171
|
+
let dayLook: Look = $state(openingLook === 'night' ? defaultViewerConfig.look : openingLook);
|
|
171
172
|
|
|
172
173
|
const VIEW_PRESETS: { preset: ViewPreset; label: () => string }[] = [
|
|
173
174
|
{ preset: 'top', label: () => t.viewTop },
|
|
@@ -234,6 +235,7 @@
|
|
|
234
235
|
invalidate = init.invalidate;
|
|
235
236
|
captureImage = init.captureImage;
|
|
236
237
|
setLook = init.setLook;
|
|
238
|
+
syncEmissiveLights = init.syncEmissiveLights;
|
|
237
239
|
updateGridScale = init.updateGridScale;
|
|
238
240
|
updateShadowBounds = init.updateShadowBounds;
|
|
239
241
|
fitToView = init.fitToView;
|
|
@@ -279,12 +281,13 @@
|
|
|
279
281
|
|
|
280
282
|
// Edges the lineart look switched on, so leaving it can put the user's own choice back rather
|
|
281
283
|
// than stranding them with overlays they never asked for.
|
|
282
|
-
let edgesBeforeLineDrawing: boolean | null = null;
|
|
284
|
+
let edgesBeforeLineDrawing: boolean | null = opensAsLineDrawing ? configuredEdges : null;
|
|
283
285
|
|
|
284
286
|
function setRenderStyle(look: Look) {
|
|
285
287
|
if (!setLook || look === renderStyle) return;
|
|
286
288
|
const wasLineDrawing = LOOK_PRESETS[renderStyle].requiresEdges === true;
|
|
287
289
|
renderStyle = look;
|
|
290
|
+
if (look !== 'night') dayLook = look;
|
|
288
291
|
setLook(look);
|
|
289
292
|
|
|
290
293
|
// A look never drives the overlay itself; honouring `requiresEdges` is the host's call. Without
|
|
@@ -350,6 +353,10 @@
|
|
|
350
353
|
else clearEdges?.(scene);
|
|
351
354
|
}
|
|
352
355
|
|
|
356
|
+
function toggleNight() {
|
|
357
|
+
setRenderStyle(nightOn ? dayLook : 'night');
|
|
358
|
+
}
|
|
359
|
+
|
|
353
360
|
function toggleEdges() {
|
|
354
361
|
edgesVisible = !edgesVisible;
|
|
355
362
|
// Toggling by hand inside lineart overrides what that look forced, so the pre-look value is
|
|
@@ -366,7 +373,8 @@
|
|
|
366
373
|
untrack(() => {
|
|
367
374
|
// The new meshes carry the materials the parser built, so a look that overrides them
|
|
368
375
|
// (arctic, x-ray) has to be re-applied or the solve silently reverts to shaded.
|
|
369
|
-
|
|
376
|
+
// Emissive lights wait for `applyTo` below, or a hidden lamp would count as lit.
|
|
377
|
+
setLook?.(renderStyle, { deferEmissiveLights: true });
|
|
370
378
|
// updateScene discarded the previous solve's overlays along with its content.
|
|
371
379
|
if (edgesVisible) applyEdges?.(scene!, edgeOverrides());
|
|
372
380
|
// Rescale the grid so cells and fade match the new content's extent.
|
|
@@ -377,6 +385,7 @@
|
|
|
377
385
|
// The rebuild un-hid everything; the outliner keys hidden state on Grasshopper
|
|
378
386
|
// identity, not on the instances just discarded, so it can re-hide it.
|
|
379
387
|
outliner?.applyTo();
|
|
388
|
+
syncEmissiveLights?.();
|
|
380
389
|
sceneVersion++;
|
|
381
390
|
// Repaint now rather than on the render loop's safety interval.
|
|
382
391
|
invalidate?.();
|
|
@@ -433,6 +442,27 @@
|
|
|
433
442
|
isFullscreen = !isFullscreen;
|
|
434
443
|
}
|
|
435
444
|
|
|
445
|
+
// Single letters; F (fit) is handled by the canvas itself. Held back while typing, e.g. in the
|
|
446
|
+
// scene manager's search box.
|
|
447
|
+
const SHORTCUTS: Record<string, () => void> = {
|
|
448
|
+
o: toggleProjection,
|
|
449
|
+
m: toggleMeasure,
|
|
450
|
+
g: toggleGrid,
|
|
451
|
+
n: toggleNight,
|
|
452
|
+
e: toggleEdges,
|
|
453
|
+
s: () => (sceneManagerOpen = !sceneManagerOpen)
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
function handleShortcut(event: KeyboardEvent) {
|
|
457
|
+
if (event.ctrlKey || event.metaKey || event.altKey || event.repeat) return;
|
|
458
|
+
const target = event.target as HTMLElement;
|
|
459
|
+
if (target.closest('input, textarea, select, [contenteditable]')) return;
|
|
460
|
+
const action = SHORTCUTS[event.key.toLowerCase()];
|
|
461
|
+
if (!action) return;
|
|
462
|
+
event.preventDefault();
|
|
463
|
+
action();
|
|
464
|
+
}
|
|
465
|
+
|
|
436
466
|
function hasUsefulMetadata(metadata: Record<string, any>): boolean {
|
|
437
467
|
if (!metadata) return false;
|
|
438
468
|
|
|
@@ -463,10 +493,13 @@
|
|
|
463
493
|
}
|
|
464
494
|
</script>
|
|
465
495
|
|
|
496
|
+
<!-- Key events bubble up from the focused canvas or any control inside; the div itself is not interactive. -->
|
|
497
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
466
498
|
<div
|
|
467
499
|
class="min-h-64 sm:min-h-96 lg:min-h-125 relative h-full flex-1 border {isFullscreen
|
|
468
500
|
? 'fullscreen-viewer'
|
|
469
501
|
: 'overflow-hidden rounded-lg'}"
|
|
502
|
+
onkeydown={handleShortcut}
|
|
470
503
|
>
|
|
471
504
|
<Resizable.PaneGroup direction="horizontal" class="h-full w-full">
|
|
472
505
|
<!-- `defaultSize` must sum to 100 across the live panes. Panes register a frame before the
|
|
@@ -480,7 +513,7 @@
|
|
|
480
513
|
the DOM, so this is the only observable proof a solve's geometry decoded and
|
|
481
514
|
rendered; e2e asserts on it. -->
|
|
482
515
|
<canvas
|
|
483
|
-
class="viewer-canvas block h-full w-full select-none"
|
|
516
|
+
class="viewer-canvas block h-full w-full outline-none select-none"
|
|
484
517
|
data-testid="viewer-canvas"
|
|
485
518
|
data-mesh-count={meshes.length}
|
|
486
519
|
bind:this={canvas}
|
|
@@ -496,10 +529,10 @@
|
|
|
496
529
|
solve hides the model the user is adjusting. -->
|
|
497
530
|
{#if isSolving}
|
|
498
531
|
<div
|
|
499
|
-
class="inset-x-0 top-0
|
|
532
|
+
class="inset-x-0 top-0 animate-in fade-in pointer-events-none absolute z-20 h-px overflow-hidden duration-300"
|
|
500
533
|
aria-hidden="true"
|
|
501
534
|
>
|
|
502
|
-
<div class="solve-bar h-full w-1/3 bg-
|
|
535
|
+
<div class="solve-bar h-full w-1/3 bg-faint-foreground"></div>
|
|
503
536
|
</div>
|
|
504
537
|
{/if}
|
|
505
538
|
{#if isSlow}
|
|
@@ -533,143 +566,36 @@
|
|
|
533
566
|
{/if}
|
|
534
567
|
|
|
535
568
|
{#if config.showToolsMenu}
|
|
536
|
-
<
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
<DropdownMenu.Item onSelect={() => fitToView?.()}>
|
|
567
|
-
<Frame />
|
|
568
|
-
{t.fitToView}
|
|
569
|
-
</DropdownMenu.Item>
|
|
570
|
-
|
|
571
|
-
<DropdownMenu.Sub>
|
|
572
|
-
<DropdownMenu.SubTrigger>
|
|
573
|
-
<Box />
|
|
574
|
-
{t.views}
|
|
575
|
-
</DropdownMenu.SubTrigger>
|
|
576
|
-
<DropdownMenu.SubContent class="z-10001">
|
|
577
|
-
{#each VIEW_PRESETS as { preset, label } (preset)}
|
|
578
|
-
<DropdownMenu.Item onSelect={() => setView(preset)}
|
|
579
|
-
>{label()}</DropdownMenu.Item
|
|
580
|
-
>
|
|
581
|
-
{/each}
|
|
582
|
-
</DropdownMenu.SubContent>
|
|
583
|
-
</DropdownMenu.Sub>
|
|
584
|
-
|
|
585
|
-
{#if config.showDisplayMenu}
|
|
586
|
-
<DropdownMenu.Sub>
|
|
587
|
-
<DropdownMenu.SubTrigger>
|
|
588
|
-
<Palette />
|
|
589
|
-
{t.display}
|
|
590
|
-
</DropdownMenu.SubTrigger>
|
|
591
|
-
<DropdownMenu.SubContent class="min-w-40 z-10001">
|
|
592
|
-
<DropdownMenu.RadioGroup
|
|
593
|
-
value={renderStyle}
|
|
594
|
-
onValueChange={(look) => setRenderStyle(look as typeof renderStyle)}
|
|
595
|
-
>
|
|
596
|
-
{#each styleOptions as { look, label } (look)}
|
|
597
|
-
<DropdownMenu.RadioItem value={look} closeOnSelect={false}>
|
|
598
|
-
{label}
|
|
599
|
-
</DropdownMenu.RadioItem>
|
|
600
|
-
{/each}
|
|
601
|
-
</DropdownMenu.RadioGroup>
|
|
602
|
-
<DropdownMenu.Separator />
|
|
603
|
-
<DropdownMenu.CheckboxItem
|
|
604
|
-
checked={edgesVisible}
|
|
605
|
-
onCheckedChange={toggleEdges}
|
|
606
|
-
>
|
|
607
|
-
<Spline />
|
|
608
|
-
{t.edges}
|
|
609
|
-
</DropdownMenu.CheckboxItem>
|
|
610
|
-
</DropdownMenu.SubContent>
|
|
611
|
-
</DropdownMenu.Sub>
|
|
612
|
-
{/if}
|
|
613
|
-
|
|
614
|
-
<DropdownMenu.CheckboxItem checked={measureActive} onCheckedChange={toggleMeasure}>
|
|
615
|
-
<Ruler />
|
|
616
|
-
{t.measure}
|
|
617
|
-
</DropdownMenu.CheckboxItem>
|
|
618
|
-
|
|
619
|
-
{#if config.showGridToggle}
|
|
620
|
-
<DropdownMenu.CheckboxItem checked={gridVisible} onCheckedChange={toggleGrid}>
|
|
621
|
-
<Grid3x3 />
|
|
622
|
-
{t.grid}
|
|
623
|
-
</DropdownMenu.CheckboxItem>
|
|
624
|
-
{/if}
|
|
625
|
-
|
|
626
|
-
{#if config.showSceneManager || config.showScreenshotButton || config.showFullscreenButton}
|
|
627
|
-
<DropdownMenu.Separator />
|
|
628
|
-
{/if}
|
|
629
|
-
|
|
630
|
-
{#if config.showSceneManager}
|
|
631
|
-
<DropdownMenu.CheckboxItem
|
|
632
|
-
checked={sceneManagerOpen}
|
|
633
|
-
onCheckedChange={() => (sceneManagerOpen = !sceneManagerOpen)}
|
|
634
|
-
>
|
|
635
|
-
<Layers />
|
|
636
|
-
{t.sceneManager}
|
|
637
|
-
</DropdownMenu.CheckboxItem>
|
|
638
|
-
{/if}
|
|
639
|
-
|
|
640
|
-
{#if config.showScreenshotButton}
|
|
641
|
-
<DropdownMenu.Item onSelect={downloadScreenshot}>
|
|
642
|
-
<Camera />
|
|
643
|
-
{t.screenshot}
|
|
644
|
-
</DropdownMenu.Item>
|
|
645
|
-
{/if}
|
|
646
|
-
|
|
647
|
-
{#if config.showFullscreenButton}
|
|
648
|
-
<DropdownMenu.Item onSelect={toggleFullscreen}>
|
|
649
|
-
{#if isFullscreen}
|
|
650
|
-
<Minimize />
|
|
651
|
-
{t.exitFullscreen}
|
|
652
|
-
{:else}
|
|
653
|
-
<Maximize />
|
|
654
|
-
{t.fullscreen}
|
|
655
|
-
{/if}
|
|
656
|
-
</DropdownMenu.Item>
|
|
657
|
-
{/if}
|
|
658
|
-
</DropdownMenu.Content>
|
|
659
|
-
</DropdownMenu.Root>
|
|
660
|
-
<!-- Touch has no F key, and fit-to-view is the way back from a framed part. -->
|
|
661
|
-
<div class="hidden pointer-coarse:block">
|
|
662
|
-
<Button
|
|
663
|
-
variant="overlay"
|
|
664
|
-
size="icon-lg"
|
|
665
|
-
title={t.fitToView}
|
|
666
|
-
aria-label={t.fitToView}
|
|
667
|
-
onclick={() => fitToView?.()}
|
|
668
|
-
>
|
|
669
|
-
<Frame />
|
|
670
|
-
</Button>
|
|
671
|
-
</div>
|
|
672
|
-
</div>
|
|
569
|
+
<ViewerDock
|
|
570
|
+
{t}
|
|
571
|
+
hidden={hideButton}
|
|
572
|
+
showDisplay={config.showDisplayMenu}
|
|
573
|
+
showGrid={config.showGridToggle}
|
|
574
|
+
showSceneManager={config.showSceneManager}
|
|
575
|
+
showScreenshot={config.showScreenshotButton}
|
|
576
|
+
showFullscreen={config.showFullscreenButton}
|
|
577
|
+
{styleOptions}
|
|
578
|
+
viewPresets={VIEW_PRESETS.map(({ preset, label }) => ({ preset, label: label() }))}
|
|
579
|
+
{renderStyle}
|
|
580
|
+
{nightOn}
|
|
581
|
+
{edgesVisible}
|
|
582
|
+
{measureActive}
|
|
583
|
+
{gridVisible}
|
|
584
|
+
{sceneManagerOpen}
|
|
585
|
+
{projection}
|
|
586
|
+
{isFullscreen}
|
|
587
|
+
onSetLook={setRenderStyle}
|
|
588
|
+
onToggleNight={toggleNight}
|
|
589
|
+
onToggleEdges={toggleEdges}
|
|
590
|
+
onToggleMeasure={toggleMeasure}
|
|
591
|
+
onToggleGrid={toggleGrid}
|
|
592
|
+
onToggleSceneManager={() => (sceneManagerOpen = !sceneManagerOpen)}
|
|
593
|
+
onToggleProjection={toggleProjection}
|
|
594
|
+
onSetView={setView}
|
|
595
|
+
onFit={() => fitToView?.()}
|
|
596
|
+
onScreenshot={downloadScreenshot}
|
|
597
|
+
onToggleFullscreen={toggleFullscreen}
|
|
598
|
+
/>
|
|
673
599
|
{/if}
|
|
674
600
|
</div>
|
|
675
601
|
</Resizable.Pane>
|
|
@@ -680,7 +606,7 @@
|
|
|
680
606
|
<SceneManager
|
|
681
607
|
{outliner}
|
|
682
608
|
{sceneVersion}
|
|
683
|
-
onVisibilityChange={() =>
|
|
609
|
+
onVisibilityChange={() => syncEmissiveLights?.()}
|
|
684
610
|
onHover={(entry) => setHover?.(entry?.object ?? null, entry?.memberIndex ?? null)}
|
|
685
611
|
/>
|
|
686
612
|
</Resizable.Pane>
|