@selvajs/ui 6.6.0-beta.15 → 6.6.0-beta.17

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.
Files changed (213) hide show
  1. package/README.md +0 -3
  2. package/dist/components/compute/AppLayout.svelte +5 -3
  3. package/dist/components/compute/CollapsedPanelStrip.svelte +1 -1
  4. package/dist/components/compute/ParameterPresetManager.svelte +1 -1
  5. package/dist/components/compute/SolveMessages.svelte +2 -2
  6. package/dist/components/layout/FooterItemRenderer.svelte +1 -1
  7. package/dist/components/layout/PageFooter.svelte +2 -2
  8. package/dist/components/layout/PageHeader.svelte +1 -1
  9. package/dist/components/layout/SideNav.svelte +3 -3
  10. package/dist/components/layout/SubNav.svelte +2 -2
  11. package/dist/components/preview/ChartOutput.svelte +3 -3
  12. package/dist/components/preview/Group.svelte +7 -7
  13. package/dist/components/preview/ImageOutput.svelte +6 -6
  14. package/dist/components/preview/InputControl.svelte +1 -0
  15. package/dist/components/preview/OutputDisplay.svelte +8 -6
  16. package/dist/components/preview/TabBar.svelte +6 -4
  17. package/dist/components/preview/TabBar.svelte.d.ts +2 -0
  18. package/dist/components/preview/TabContent.svelte +1 -1
  19. package/dist/components/preview/TabLayout.svelte +3 -4
  20. package/dist/components/preview/inputs/ChecklistInput.svelte +3 -3
  21. package/dist/components/preview/inputs/ColorInput.svelte +356 -14
  22. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  23. package/dist/components/preview/inputs/FileInput.svelte +3 -3
  24. package/dist/components/preview/inputs/SegmentedInput.svelte +2 -1
  25. package/dist/components/preview/inputs/TileInput.svelte +1 -1
  26. package/dist/components/primitives/CalculateButton.svelte +2 -2
  27. package/dist/components/primitives/Callout.svelte +8 -6
  28. package/dist/components/primitives/Callout.svelte.d.ts +4 -4
  29. package/dist/components/primitives/DataTable.svelte +1 -1
  30. package/dist/components/primitives/ImageUploadField.svelte +1 -1
  31. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  32. package/dist/components/primitives/badge/badge.svelte +2 -2
  33. package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
  34. package/dist/components/primitives/button/button.svelte +6 -7
  35. package/dist/components/primitives/button/button.svelte.d.ts +18 -18
  36. package/dist/components/primitives/card/card.svelte +1 -1
  37. package/dist/components/primitives/card/card.svelte.d.ts +1 -1
  38. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  39. package/dist/components/primitives/command/command-input.svelte +1 -1
  40. package/dist/components/primitives/command/command-item.svelte +1 -1
  41. package/dist/components/primitives/command/command-link-item.svelte +1 -1
  42. package/dist/components/primitives/command/command.svelte +1 -1
  43. package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  44. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  45. package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
  46. package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  47. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  48. package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  49. package/dist/components/primitives/dialog/dialog-content.svelte +2 -2
  50. package/dist/components/primitives/drawer/Drawer.svelte +1 -1
  51. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  52. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
  53. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  54. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
  55. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  56. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
  57. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  58. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  59. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  60. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  61. package/dist/components/primitives/index.d.ts +1 -1
  62. package/dist/components/primitives/index.js +1 -1
  63. package/dist/components/primitives/input/input.svelte +2 -2
  64. package/dist/components/primitives/input-group/input-group.svelte +1 -1
  65. package/dist/components/primitives/popover/popover-content.svelte +1 -1
  66. package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
  67. package/dist/components/primitives/search/search.svelte +1 -1
  68. package/dist/components/primitives/select/select-content.svelte +1 -1
  69. package/dist/components/primitives/select/select-item.svelte +1 -1
  70. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  71. package/dist/components/primitives/slider/slider.svelte +1 -1
  72. package/dist/components/primitives/switch/switch.svelte +1 -1
  73. package/dist/components/primitives/tabs/tabs-list.svelte +1 -1
  74. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +3 -3
  75. package/dist/components/primitives/tabs/tabs-trigger.svelte +1 -1
  76. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +3 -3
  77. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  78. package/dist/components/primitives/toggle/toggle.svelte +6 -3
  79. package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -7
  80. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  81. package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
  82. package/dist/components/primitives/tooltip/index.d.ts +6 -0
  83. package/dist/components/primitives/tooltip/index.js +8 -0
  84. package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
  85. package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
  86. package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  87. package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
  88. package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  89. package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
  90. package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  91. package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  92. package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
  93. package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
  94. package/dist/components/viewer/MeshMetadataPanel.svelte +1 -1
  95. package/dist/components/viewer/SceneManager.svelte +19 -19
  96. package/dist/components/viewer/Viewer.svelte +68 -157
  97. package/dist/components/viewer/ViewerDock.svelte +404 -0
  98. package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
  99. package/dist/i18n/messages.d.ts +11 -0
  100. package/dist/i18n/messages.js +18 -0
  101. package/dist/index.d.ts +1 -0
  102. package/dist/index.js +1 -0
  103. package/dist/public.d.ts +1 -0
  104. package/dist/public.js +1 -0
  105. package/dist/schema/visibility-rules.d.ts +7 -1
  106. package/dist/schema/visibility-rules.js +17 -0
  107. package/dist/styles/base.css +81 -80
  108. package/dist/utils/color-space.d.ts +21 -0
  109. package/dist/utils/color-space.js +90 -0
  110. package/package.json +8 -9
  111. package/src/lib/components/compute/AppLayout.svelte +5 -3
  112. package/src/lib/components/compute/CollapsedPanelStrip.svelte +1 -1
  113. package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
  114. package/src/lib/components/compute/SolveMessages.svelte +2 -2
  115. package/src/lib/components/layout/FooterItemRenderer.svelte +1 -1
  116. package/src/lib/components/layout/PageFooter.svelte +2 -2
  117. package/src/lib/components/layout/PageHeader.svelte +1 -1
  118. package/src/lib/components/layout/SideNav.svelte +3 -3
  119. package/src/lib/components/layout/SubNav.svelte +2 -2
  120. package/src/lib/components/preview/ChartOutput.svelte +3 -3
  121. package/src/lib/components/preview/Group.svelte +7 -7
  122. package/src/lib/components/preview/ImageOutput.svelte +6 -6
  123. package/src/lib/components/preview/InputControl.svelte +1 -0
  124. package/src/lib/components/preview/OutputDisplay.svelte +8 -6
  125. package/src/lib/components/preview/TabBar.svelte +6 -4
  126. package/src/lib/components/preview/TabContent.svelte +1 -1
  127. package/src/lib/components/preview/TabLayout.svelte +3 -4
  128. package/src/lib/components/preview/inputs/ChecklistInput.svelte +3 -3
  129. package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
  130. package/src/lib/components/preview/inputs/FileInput.svelte +3 -3
  131. package/src/lib/components/preview/inputs/SegmentedInput.svelte +2 -1
  132. package/src/lib/components/preview/inputs/TileInput.svelte +1 -1
  133. package/src/lib/components/primitives/CalculateButton.svelte +2 -2
  134. package/src/lib/components/primitives/Callout.svelte +8 -6
  135. package/src/lib/components/primitives/DataTable.svelte +1 -1
  136. package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
  137. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  138. package/src/lib/components/primitives/badge/badge.svelte +2 -2
  139. package/src/lib/components/primitives/button/button.svelte +6 -7
  140. package/src/lib/components/primitives/card/card.svelte +1 -1
  141. package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
  142. package/src/lib/components/primitives/command/command-input.svelte +1 -1
  143. package/src/lib/components/primitives/command/command-item.svelte +1 -1
  144. package/src/lib/components/primitives/command/command-link-item.svelte +1 -1
  145. package/src/lib/components/primitives/command/command.svelte +1 -1
  146. package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  147. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
  148. package/src/lib/components/primitives/context-menu/context-menu-item.svelte +1 -1
  149. package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  150. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  151. package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  152. package/src/lib/components/primitives/dialog/dialog-content.svelte +2 -2
  153. package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
  154. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  155. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  156. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  157. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  158. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  159. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  160. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  161. package/src/lib/components/primitives/index.ts +1 -1
  162. package/src/lib/components/primitives/input/input.svelte +2 -2
  163. package/src/lib/components/primitives/input-group/input-group.svelte +1 -1
  164. package/src/lib/components/primitives/popover/popover-content.svelte +1 -1
  165. package/src/lib/components/primitives/resizable/resizable-handle.svelte +2 -2
  166. package/src/lib/components/primitives/search/search.svelte +1 -1
  167. package/src/lib/components/primitives/select/select-content.svelte +1 -1
  168. package/src/lib/components/primitives/select/select-item.svelte +1 -1
  169. package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
  170. package/src/lib/components/primitives/slider/slider.svelte +1 -1
  171. package/src/lib/components/primitives/switch/switch.svelte +1 -1
  172. package/src/lib/components/primitives/tabs/tabs-list.svelte +1 -1
  173. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +1 -1
  174. package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
  175. package/src/lib/components/primitives/toggle/toggle.svelte +6 -3
  176. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  177. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +1 -1
  178. package/src/lib/components/primitives/tooltip/index.ts +19 -0
  179. package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
  180. package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  181. package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  182. package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  183. package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
  184. package/src/lib/components/viewer/MeshMetadataPanel.svelte +1 -1
  185. package/src/lib/components/viewer/SceneManager.svelte +19 -19
  186. package/src/lib/components/viewer/Viewer.svelte +68 -157
  187. package/src/lib/components/viewer/ViewerDock.svelte +404 -0
  188. package/src/lib/i18n/messages.ts +29 -0
  189. package/src/lib/index.ts +1 -0
  190. package/src/lib/public.ts +1 -0
  191. package/src/lib/schema/visibility-rules.ts +27 -1
  192. package/src/lib/styles/base.css +81 -80
  193. package/src/lib/utils/color-space.ts +107 -0
  194. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  195. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
  196. package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
  197. package/dist/components/primitives/theme-switcher/index.js +0 -1
  198. package/dist/styles/themes/cyberpunk.css +0 -98
  199. package/dist/styles/themes/neutral.css +0 -72
  200. package/dist/styles/themes/ocean.css +0 -75
  201. package/dist/styles/themes/selva.css +0 -105
  202. package/dist/theme/themeStore.svelte.d.ts +0 -12
  203. package/dist/theme/themeStore.svelte.js +0 -40
  204. package/dist/theme/themes.d.ts +0 -5
  205. package/dist/theme/themes.js +0 -13
  206. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  207. package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
  208. package/src/lib/styles/themes/cyberpunk.css +0 -98
  209. package/src/lib/styles/themes/neutral.css +0 -72
  210. package/src/lib/styles/themes/ocean.css +0 -75
  211. package/src/lib/styles/themes/selva.css +0 -105
  212. package/src/lib/theme/themeStore.svelte.ts +0 -50
  213. package/src/lib/theme/themes.ts +0 -18
@@ -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 '../primitives/resizable/index.js';
40
- import * as DropdownMenu from '../primitives/dropdown-menu/index.js';
41
- import { Button } from '../primitives/button/index.js';
42
27
  import type { Locale } from '../../i18n/messages';
43
28
  import { layerLocaleContext } from '../../i18n/localeContext.svelte';
44
29
  import { saveBlob } from '../../utils/host-files';
@@ -174,12 +159,16 @@
174
159
  wireframe: t.lookWireframe,
175
160
  night: t.lookNight
176
161
  });
162
+ // Night has its own toggle, so it stays out of the radio list.
177
163
  const styleOptions = $derived<{ look: Look; label: string }[]>(
178
- LOOKS.map((look) => ({
164
+ LOOKS.filter((look) => look !== 'night').map((look) => ({
179
165
  look,
180
166
  label: lookLabels[look] ?? look.charAt(0).toUpperCase() + look.slice(1)
181
167
  }))
182
168
  );
169
+ const nightOn = $derived(renderStyle === 'night');
170
+ // What the night toggle returns to.
171
+ let dayLook: Look = $state(openingLook === 'night' ? defaultViewerConfig.look : openingLook);
183
172
 
184
173
  const VIEW_PRESETS: { preset: ViewPreset; label: () => string }[] = [
185
174
  { preset: 'top', label: () => t.viewTop },
@@ -298,6 +287,7 @@
298
287
  if (!setLook || look === renderStyle) return;
299
288
  const wasLineDrawing = LOOK_PRESETS[renderStyle].requiresEdges === true;
300
289
  renderStyle = look;
290
+ if (look !== 'night') dayLook = look;
301
291
  setLook(look);
302
292
 
303
293
  // A look never drives the overlay itself; honouring `requiresEdges` is the host's call. Without
@@ -363,6 +353,10 @@
363
353
  else clearEdges?.(scene);
364
354
  }
365
355
 
356
+ function toggleNight() {
357
+ setRenderStyle(nightOn ? dayLook : 'night');
358
+ }
359
+
366
360
  function toggleEdges() {
367
361
  edgesVisible = !edgesVisible;
368
362
  // Toggling by hand inside lineart overrides what that look forced, so the pre-look value is
@@ -448,6 +442,27 @@
448
442
  isFullscreen = !isFullscreen;
449
443
  }
450
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
+
451
466
  function hasUsefulMetadata(metadata: Record<string, any>): boolean {
452
467
  if (!metadata) return false;
453
468
 
@@ -478,10 +493,13 @@
478
493
  }
479
494
  </script>
480
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 -->
481
498
  <div
482
499
  class="min-h-64 sm:min-h-96 lg:min-h-125 relative h-full flex-1 border {isFullscreen
483
500
  ? 'fullscreen-viewer'
484
501
  : 'overflow-hidden rounded-lg'}"
502
+ onkeydown={handleShortcut}
485
503
  >
486
504
  <Resizable.PaneGroup direction="horizontal" class="h-full w-full">
487
505
  <!-- `defaultSize` must sum to 100 across the live panes. Panes register a frame before the
@@ -495,7 +513,7 @@
495
513
  the DOM, so this is the only observable proof a solve's geometry decoded and
496
514
  rendered; e2e asserts on it. -->
497
515
  <canvas
498
- class="viewer-canvas block h-full w-full select-none"
516
+ class="viewer-canvas block h-full w-full outline-none select-none"
499
517
  data-testid="viewer-canvas"
500
518
  data-mesh-count={meshes.length}
501
519
  bind:this={canvas}
@@ -511,10 +529,10 @@
511
529
  solve hides the model the user is adjusting. -->
512
530
  {#if isSolving}
513
531
  <div
514
- class="inset-x-0 top-0 h-0.5 animate-in fade-in pointer-events-none absolute z-20 overflow-hidden bg-primary/20 duration-200"
532
+ class="inset-x-0 top-0 animate-in fade-in pointer-events-none absolute z-20 h-px overflow-hidden duration-300"
515
533
  aria-hidden="true"
516
534
  >
517
- <div class="solve-bar h-full w-1/3 bg-primary"></div>
535
+ <div class="solve-bar h-full w-1/3 bg-faint-foreground"></div>
518
536
  </div>
519
537
  {/if}
520
538
  {#if isSlow}
@@ -548,143 +566,36 @@
548
566
  {/if}
549
567
 
550
568
  {#if config.showToolsMenu}
551
- <div
552
- class="left-4 bottom-4 gap-2 *:shadow-lg absolute z-50 flex items-center *:rounded-md {hideButton
553
- ? 'pointer-events-none opacity-0'
554
- : ''}"
555
- >
556
- <DropdownMenu.Root>
557
- <DropdownMenu.Trigger>
558
- {#snippet child({ props })}
559
- <Button
560
- {...props}
561
- variant="overlay"
562
- size="icon-lg"
563
- title={t.toolsMenu}
564
- aria-label={t.toolsMenu}
565
- >
566
- <Settings2 />
567
- </Button>
568
- {/snippet}
569
- </DropdownMenu.Trigger>
570
- <!-- Above the fullscreen viewer, which sits at z-index 10000. -->
571
- <DropdownMenu.Content sideOffset={6} class="min-w-44 z-10001 w-auto">
572
- <DropdownMenu.Item onSelect={toggleProjection}>
573
- {#if projection === 'perspective'}
574
- <Square />
575
- {t.switchToOrthographic}
576
- {:else}
577
- <Box />
578
- {t.switchToPerspective}
579
- {/if}
580
- </DropdownMenu.Item>
581
- <DropdownMenu.Item onSelect={() => fitToView?.()}>
582
- <Frame />
583
- {t.fitToView}
584
- </DropdownMenu.Item>
585
-
586
- <DropdownMenu.Sub>
587
- <DropdownMenu.SubTrigger>
588
- <Box />
589
- {t.views}
590
- </DropdownMenu.SubTrigger>
591
- <DropdownMenu.SubContent class="z-10001">
592
- {#each VIEW_PRESETS as { preset, label } (preset)}
593
- <DropdownMenu.Item onSelect={() => setView(preset)}
594
- >{label()}</DropdownMenu.Item
595
- >
596
- {/each}
597
- </DropdownMenu.SubContent>
598
- </DropdownMenu.Sub>
599
-
600
- {#if config.showDisplayMenu}
601
- <DropdownMenu.Sub>
602
- <DropdownMenu.SubTrigger>
603
- <Palette />
604
- {t.display}
605
- </DropdownMenu.SubTrigger>
606
- <DropdownMenu.SubContent class="min-w-40 z-10001">
607
- <DropdownMenu.RadioGroup
608
- value={renderStyle}
609
- onValueChange={(look) => setRenderStyle(look as typeof renderStyle)}
610
- >
611
- {#each styleOptions as { look, label } (look)}
612
- <DropdownMenu.RadioItem value={look} closeOnSelect={false}>
613
- {label}
614
- </DropdownMenu.RadioItem>
615
- {/each}
616
- </DropdownMenu.RadioGroup>
617
- <DropdownMenu.Separator />
618
- <DropdownMenu.CheckboxItem
619
- checked={edgesVisible}
620
- onCheckedChange={toggleEdges}
621
- >
622
- <Spline />
623
- {t.edges}
624
- </DropdownMenu.CheckboxItem>
625
- </DropdownMenu.SubContent>
626
- </DropdownMenu.Sub>
627
- {/if}
628
-
629
- <DropdownMenu.CheckboxItem checked={measureActive} onCheckedChange={toggleMeasure}>
630
- <Ruler />
631
- {t.measure}
632
- </DropdownMenu.CheckboxItem>
633
-
634
- {#if config.showGridToggle}
635
- <DropdownMenu.CheckboxItem checked={gridVisible} onCheckedChange={toggleGrid}>
636
- <Grid3x3 />
637
- {t.grid}
638
- </DropdownMenu.CheckboxItem>
639
- {/if}
640
-
641
- {#if config.showSceneManager || config.showScreenshotButton || config.showFullscreenButton}
642
- <DropdownMenu.Separator />
643
- {/if}
644
-
645
- {#if config.showSceneManager}
646
- <DropdownMenu.CheckboxItem
647
- checked={sceneManagerOpen}
648
- onCheckedChange={() => (sceneManagerOpen = !sceneManagerOpen)}
649
- >
650
- <Layers />
651
- {t.sceneManager}
652
- </DropdownMenu.CheckboxItem>
653
- {/if}
654
-
655
- {#if config.showScreenshotButton}
656
- <DropdownMenu.Item onSelect={downloadScreenshot}>
657
- <Camera />
658
- {t.screenshot}
659
- </DropdownMenu.Item>
660
- {/if}
661
-
662
- {#if config.showFullscreenButton}
663
- <DropdownMenu.Item onSelect={toggleFullscreen}>
664
- {#if isFullscreen}
665
- <Minimize />
666
- {t.exitFullscreen}
667
- {:else}
668
- <Maximize />
669
- {t.fullscreen}
670
- {/if}
671
- </DropdownMenu.Item>
672
- {/if}
673
- </DropdownMenu.Content>
674
- </DropdownMenu.Root>
675
- <!-- Touch has no F key, and fit-to-view is the way back from a framed part. -->
676
- <div class="hidden pointer-coarse:block">
677
- <Button
678
- variant="overlay"
679
- size="icon-lg"
680
- title={t.fitToView}
681
- aria-label={t.fitToView}
682
- onclick={() => fitToView?.()}
683
- >
684
- <Frame />
685
- </Button>
686
- </div>
687
- </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
+ />
688
599
  {/if}
689
600
  </div>
690
601
  </Resizable.Pane>