@mgz-dev/inspect 0.1.0

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -0
  3. package/dist/Inspect.cjs +1 -0
  4. package/dist/Inspect.d.ts +68 -0
  5. package/dist/Inspect.mjs +1 -0
  6. package/dist/InspectRegistry.cjs +1 -0
  7. package/dist/InspectRegistry.d.ts +52 -0
  8. package/dist/InspectRegistry.mjs +1 -0
  9. package/dist/assets/default-atlas.cjs +1 -0
  10. package/dist/assets/default-atlas.d.ts +6 -0
  11. package/dist/assets/default-atlas.mjs +1 -0
  12. package/dist/core/atlas.cjs +1 -0
  13. package/dist/core/atlas.d.ts +29 -0
  14. package/dist/core/atlas.mjs +1 -0
  15. package/dist/core/canvas2d-renderer.cjs +1 -0
  16. package/dist/core/canvas2d-renderer.d.ts +94 -0
  17. package/dist/core/canvas2d-renderer.mjs +1 -0
  18. package/dist/core/font-generator.cjs +1 -0
  19. package/dist/core/font-generator.d.ts +20 -0
  20. package/dist/core/font-generator.mjs +1 -0
  21. package/dist/core/glyph-rasterizer.cjs +1 -0
  22. package/dist/core/glyph-rasterizer.d.ts +10 -0
  23. package/dist/core/glyph-rasterizer.mjs +1 -0
  24. package/dist/core/input.cjs +1 -0
  25. package/dist/core/input.d.ts +89 -0
  26. package/dist/core/input.mjs +1 -0
  27. package/dist/core/layout.d.ts +10 -0
  28. package/dist/core/layouts/stack-layout.cjs +1 -0
  29. package/dist/core/layouts/stack-layout.d.ts +69 -0
  30. package/dist/core/layouts/stack-layout.mjs +1 -0
  31. package/dist/core/renderer.d.ts +65 -0
  32. package/dist/core/surface.cjs +1 -0
  33. package/dist/core/surface.d.ts +81 -0
  34. package/dist/core/surface.mjs +1 -0
  35. package/dist/core/theme.d.ts +33 -0
  36. package/dist/core/ttf-parser.cjs +1 -0
  37. package/dist/core/ttf-parser.d.ts +29 -0
  38. package/dist/core/ttf-parser.mjs +1 -0
  39. package/dist/core/widget.cjs +1 -0
  40. package/dist/core/widget.d.ts +213 -0
  41. package/dist/core/widget.mjs +1 -0
  42. package/dist/defaults.cjs +1 -0
  43. package/dist/defaults.d.ts +113 -0
  44. package/dist/defaults.mjs +1 -0
  45. package/dist/gui/gui-button-row.cjs +1 -0
  46. package/dist/gui/gui-button-row.d.ts +21 -0
  47. package/dist/gui/gui-button-row.mjs +1 -0
  48. package/dist/gui/gui-button.cjs +1 -0
  49. package/dist/gui/gui-button.d.ts +9 -0
  50. package/dist/gui/gui-button.mjs +1 -0
  51. package/dist/gui/gui-color.cjs +1 -0
  52. package/dist/gui/gui-color.d.ts +105 -0
  53. package/dist/gui/gui-color.mjs +1 -0
  54. package/dist/gui/gui-folder.cjs +1 -0
  55. package/dist/gui/gui-folder.d.ts +49 -0
  56. package/dist/gui/gui-folder.mjs +1 -0
  57. package/dist/gui/gui-monitor.cjs +1 -0
  58. package/dist/gui/gui-monitor.d.ts +53 -0
  59. package/dist/gui/gui-monitor.mjs +1 -0
  60. package/dist/gui/gui-point2d.d.ts +43 -0
  61. package/dist/gui/gui-point3d.d.ts +48 -0
  62. package/dist/gui/gui-reorder-list.cjs +1 -0
  63. package/dist/gui/gui-reorder-list.d.ts +42 -0
  64. package/dist/gui/gui-reorder-list.mjs +1 -0
  65. package/dist/gui/gui-select.cjs +1 -0
  66. package/dist/gui/gui-select.d.ts +40 -0
  67. package/dist/gui/gui-select.mjs +1 -0
  68. package/dist/gui/gui-separator.cjs +1 -0
  69. package/dist/gui/gui-separator.d.ts +10 -0
  70. package/dist/gui/gui-separator.mjs +1 -0
  71. package/dist/gui/gui-slider.cjs +1 -0
  72. package/dist/gui/gui-slider.d.ts +34 -0
  73. package/dist/gui/gui-slider.mjs +1 -0
  74. package/dist/gui/gui-tab-container.d.ts +26 -0
  75. package/dist/gui/gui-text-log.cjs +1 -0
  76. package/dist/gui/gui-text-log.d.ts +24 -0
  77. package/dist/gui/gui-text-log.mjs +1 -0
  78. package/dist/gui/gui-text.cjs +1 -0
  79. package/dist/gui/gui-text.d.ts +22 -0
  80. package/dist/gui/gui-text.mjs +1 -0
  81. package/dist/gui/gui-toggle.cjs +1 -0
  82. package/dist/gui/gui-toggle.d.ts +19 -0
  83. package/dist/gui/gui-toggle.mjs +1 -0
  84. package/dist/gui/labeled-control.cjs +1 -0
  85. package/dist/gui/labeled-control.d.ts +21 -0
  86. package/dist/gui/labeled-control.mjs +1 -0
  87. package/dist/index.cjs +1 -0
  88. package/dist/index.d.ts +19 -0
  89. package/dist/index.mjs +1 -0
  90. package/dist/panel/inspect-debugger.cjs +1 -0
  91. package/dist/panel/inspect-debugger.d.ts +30 -0
  92. package/dist/panel/inspect-debugger.mjs +1 -0
  93. package/dist/panel/inspect-panel.cjs +1 -0
  94. package/dist/panel/inspect-panel.d.ts +66 -0
  95. package/dist/panel/inspect-panel.mjs +1 -0
  96. package/dist/panel/state-manager.cjs +1 -0
  97. package/dist/panel/state-manager.d.ts +8 -0
  98. package/dist/panel/state-manager.mjs +1 -0
  99. package/dist/panel/widget-builder.cjs +1 -0
  100. package/dist/panel/widget-builder.d.ts +80 -0
  101. package/dist/panel/widget-builder.mjs +1 -0
  102. package/dist/themes/dark.cjs +1 -0
  103. package/dist/themes/dark.d.ts +4 -0
  104. package/dist/themes/dark.mjs +1 -0
  105. package/dist/themes/inspect-theme.d.ts +20 -0
  106. package/dist/types.cjs +1 -0
  107. package/dist/types.d.ts +354 -0
  108. package/dist/types.mjs +1 -0
  109. package/dist/utils/activity.cjs +1 -0
  110. package/dist/utils/activity.d.ts +4 -0
  111. package/dist/utils/activity.mjs +1 -0
  112. package/dist/utils/color-convert.cjs +1 -0
  113. package/dist/utils/color-convert.d.ts +31 -0
  114. package/dist/utils/color-convert.mjs +1 -0
  115. package/dist/utils/index.d.ts +3 -0
  116. package/dist/utils/persistence.cjs +1 -0
  117. package/dist/utils/persistence.d.ts +16 -0
  118. package/dist/utils/persistence.mjs +1 -0
  119. package/dist/widgets/box.cjs +1 -0
  120. package/dist/widgets/box.d.ts +24 -0
  121. package/dist/widgets/box.mjs +1 -0
  122. package/dist/widgets/button.cjs +1 -0
  123. package/dist/widgets/button.d.ts +50 -0
  124. package/dist/widgets/button.mjs +1 -0
  125. package/dist/widgets/canvas-widget.cjs +1 -0
  126. package/dist/widgets/canvas-widget.d.ts +12 -0
  127. package/dist/widgets/canvas-widget.mjs +1 -0
  128. package/dist/widgets/label.cjs +1 -0
  129. package/dist/widgets/label.d.ts +41 -0
  130. package/dist/widgets/label.mjs +1 -0
  131. package/dist/widgets/number-input.cjs +1 -0
  132. package/dist/widgets/number-input.d.ts +65 -0
  133. package/dist/widgets/number-input.mjs +1 -0
  134. package/dist/widgets/overlay.d.ts +16 -0
  135. package/dist/widgets/scroll-area.cjs +1 -0
  136. package/dist/widgets/scroll-area.d.ts +80 -0
  137. package/dist/widgets/scroll-area.mjs +1 -0
  138. package/dist/widgets/separator.cjs +1 -0
  139. package/dist/widgets/separator.d.ts +16 -0
  140. package/dist/widgets/separator.mjs +1 -0
  141. package/dist/widgets/slider.cjs +1 -0
  142. package/dist/widgets/slider.d.ts +36 -0
  143. package/dist/widgets/slider.mjs +1 -0
  144. package/dist/widgets/tab-bar.cjs +1 -0
  145. package/dist/widgets/tab-bar.d.ts +72 -0
  146. package/dist/widgets/tab-bar.mjs +1 -0
  147. package/dist/widgets/text-input.cjs +1 -0
  148. package/dist/widgets/text-input.d.ts +54 -0
  149. package/dist/widgets/text-input.mjs +1 -0
  150. package/dist/widgets/toggle-button.d.ts +18 -0
  151. package/dist/widgets/toggle-icon.cjs +1 -0
  152. package/dist/widgets/toggle-icon.d.ts +38 -0
  153. package/dist/widgets/toggle-icon.mjs +1 -0
  154. package/package.json +95 -0
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../assets/default-atlas.cjs"),t=require("../core/canvas2d-renderer.cjs"),i=require("../core/font-generator.cjs"),s=require("../core/input.cjs"),a=require("../core/layouts/stack-layout.cjs"),r=require("../core/surface.cjs"),n=require("../defaults.cjs"),o=require("./inspect-debugger.cjs"),l=require("../themes/dark.cjs"),h=require("../utils/persistence.cjs"),d=require("../widgets/box.cjs"),c=new Set(["bgApp","bgPanel","bgPanelInset","bgPanelRaised","bgButton","bgButtonHover","bgButtonActive","bgInput","bgSelected","bgScrollTrack","bgScrollThumb","borderPanel","borderInset","borderRaised","textPrimary","textSecondary","textMuted","textValue","textTitle","textHighlight","spacingXS","spacingSM","spacingMD","spacingLG","borderRadius","buttonHeight","labelHeight","separatorThickness","bgFolder","bgFolderHover","textFolder","bgAccent","bgAccentDim","textLabel","bgOverlay","controlHeight","controlGap","labelRatio","folderHeaderHeight","panelPadding","scrollbarWidth","textOffsetY"]);exports.InspectPanel=class{canvas;surface;renderer;input;theme;root;visible;ready;keyHandler=null;options;hovered=!1;enterHandler=null;leaveHandler=null;debugger_=null;panelPosition;panelMargin;panelWidth;constructor(e,i){this.options=i;const c=i.width??n.DEFAULTS.panelDefaultWidth,p=i.position??"right",u=i.margin??0,g=i.storageKey??n.DEFAULTS.panelDefaultStorageKey;if(this.panelPosition=p,this.panelMargin=u,this.panelWidth=c,!1!==i.persistVisibility){const e=h.getVisibilityFromStorage(g);this.visible=null!==e?e:i.initiallyVisible??!1}else this.visible=i.initiallyVisible??!1;this.canvas=document.createElement("canvas"),this.canvas.style.position="fixed",this.canvas.style.top=`${u}px`,this.canvas.style.width=`${c}px`,this.canvas.style.height=`calc(100vh - ${2*u}px)`,this.canvas.style.zIndex=n.DEFAULTS.panelZIndex,i.borderRadius&&(this.canvas.style.borderRadius=`${i.borderRadius}px`),this.canvas.style.transition=`${p} ${n.DEFAULTS.panelTransitionEasing} ${n.DEFAULTS.panelTransitionDuration}`;const v=-(c+n.DEFAULTS.panelHiddenOffsetExtra+u)+"px",b=`${u}px`,y=n.DEFAULTS.panelBoxShadowX,f=n.DEFAULTS.panelBoxShadowBlur,x=n.DEFAULTS.panelBoxShadowColor;"right"===p?(this.canvas.style.right=this.visible?b:v,this.canvas.style.boxShadow=`-${y}px 0px ${f}px ${x}`):(this.canvas.style.left=this.visible?b:v,this.canvas.style.boxShadow=`${y}px 0px ${f}px ${x}`),e.appendChild(this.canvas),this.renderer=new t.Canvas2DRenderer(this.canvas),this.theme=l.createDarkTheme(null),this.surface=new r.Surface(this.canvas,this.renderer,this.theme),this.input=new s.InputDispatcher(this.surface),i.debugMode&&(this.debugger_=new o.InspectDebugger(this.surface,this.canvas)),this.root=new d.Box,this.root.sizingX="grow",this.root.sizingY="grow",this.root.bgColor=this.theme.bgApp,this.root.borderRadius=i.borderRadius??0,this.root.layout=new a.StackLayout("vertical",0,"start","stretch"),this.surface.setRoot(this.root),this.enterHandler=()=>{this.hovered=!0},this.leaveHandler=()=>{this.hovered=!1},this.canvas.addEventListener("pointerenter",this.enterHandler),this.canvas.addEventListener("pointerleave",this.leaveHandler),this.keyHandler=null,this.ready=this.initFontAtlas(i)}async initFontAtlas(t){const s=void 0!==t.fontUrl||void 0!==t.fontData||void 0!==t.fontFamily?await i.createFontAtlas({family:t.fontFamily??n.DEFAULTS.panelDefaultFontFamily,size:t.fontSize??n.DEFAULTS.panelDefaultFontSize,fontUrl:t.fontUrl,fontData:t.fontData,pixelPerfect:void 0!==t.fontUrl||void 0!==t.fontData,extraChars:"v>‹›"}):await e.loadDefaultAtlas(),a=t.theme;this.theme=a&&"string"!=typeof a?{...a,fontAtlas:s}:l.createDarkTheme(s);const r=function(e){let t=null;const i=e;for(const e of c)"borderRadius"!==e&&e in i&&void 0!==i[e]&&(t||(t={}),t[e]=i[e]);return void 0!==e.widgetBorderRadius&&(t||(t={}),t.borderRadius=e.widgetBorderRadius),t}(t);r&&(this.theme={...this.theme,...r,fontAtlas:s}),this.root.bgColor=this.theme.bgApp,this.surface.setTheme(this.theme)}toggle(){this.visible?this.hide():this.show()}applyPosition(){const e=`${this.panelMargin}px`,t=-(this.panelWidth+50+this.panelMargin)+"px";"right"===this.panelPosition?this.canvas.style.right=this.visible?e:t:this.canvas.style.left=this.visible?e:t}show(){this.visible||(this.visible=!0,this.applyPosition(),this.surface.markDirty(),!1!==this.options.persistVisibility&&h.setVisibilityToStorage(!0,this.options.storageKey??n.DEFAULTS.panelDefaultStorageKey))}hide(){this.visible&&(this.visible=!1,this.applyPosition(),!1!==this.options.persistVisibility&&h.setVisibilityToStorage(!1,this.options.storageKey??n.DEFAULTS.panelDefaultStorageKey))}isVisible(){return this.visible}isHovered(){return this.hovered}setContent(e){this.root.removeAllChildren(),this.root.addChild(e),this.surface.markDirty()}dispose(){this.keyHandler&&(window.removeEventListener("keydown",this.keyHandler),this.keyHandler=null),this.enterHandler&&(this.canvas.removeEventListener("pointerenter",this.enterHandler),this.enterHandler=null),this.leaveHandler&&(this.canvas.removeEventListener("pointerleave",this.leaveHandler),this.leaveHandler=null),this.debugger_&&(this.debugger_.dispose(),this.debugger_=null),this.input.dispose(),this.surface.dispose(),this.canvas.remove()}};
@@ -0,0 +1,66 @@
1
+ import { Canvas2DRenderer } from '../core/canvas2d-renderer';
2
+ import { InputDispatcher } from '../core/input';
3
+ import { Surface } from '../core/surface';
4
+ import { Box } from '../widgets/box';
5
+ import { Widget } from '../core/widget';
6
+ import { InspectTheme } from '../themes/inspect-theme';
7
+ import { MountOptions } from '../types';
8
+ /**
9
+ * The main panel component: creates the fixed-position canvas, renderer, surface,
10
+ * input dispatcher, and manages show/hide transitions and font atlas initialization.
11
+ */
12
+ export declare class InspectPanel {
13
+ /** the fixed-position canvas element the panel renders into. */
14
+ readonly canvas: HTMLCanvasElement;
15
+ /** surface driving layout and repaint of the widget tree. */
16
+ readonly surface: Surface;
17
+ /** the canvas 2D drawing backend. */
18
+ readonly renderer: Canvas2DRenderer;
19
+ /** dispatcher routing pointer, wheel, and keyboard events to widgets. */
20
+ readonly input: InputDispatcher;
21
+ /** active theme, replaced once the font atlas finishes loading. */
22
+ theme: InspectTheme;
23
+ /** root container that holds the panel content. */
24
+ root: Box;
25
+ /** whether the panel is currently slid into view. */
26
+ visible: boolean;
27
+ /** resolves once the font atlas has loaded and the real theme is applied. */
28
+ readonly ready: Promise<void>;
29
+ private keyHandler;
30
+ private options;
31
+ private hovered;
32
+ private enterHandler;
33
+ private leaveHandler;
34
+ private debugger_;
35
+ private panelPosition;
36
+ private panelMargin;
37
+ private panelWidth;
38
+ /**
39
+ * Creates and styles the fixed-position canvas, wires up the renderer,
40
+ * surface, input, and root box, restores stored visibility, positions the
41
+ * panel on or off screen, and starts loading the font atlas.
42
+ */
43
+ constructor(container: HTMLElement, options: MountOptions);
44
+ /**
45
+ * Loads the font atlas, using a runtime-generated one when a custom font is
46
+ * requested and the embedded default otherwise, then resolves the theme
47
+ * (explicit object, dark default, or option overrides) and applies it.
48
+ */
49
+ private initFontAtlas;
50
+ /** toggles panel visibility between shown and hidden. */
51
+ toggle(): void;
52
+ /** slides the panel to its shown or hidden offset by setting the anchored side (left/right) by visibility. */
53
+ private applyPosition;
54
+ /** slides the panel into view and persists visibility when enabled. */
55
+ show(): void;
56
+ /** slides the panel out of view and persists visibility when enabled. */
57
+ hide(): void;
58
+ /** returns whether the panel is currently shown. */
59
+ isVisible(): boolean;
60
+ /** returns whether the pointer is currently over the panel. */
61
+ isHovered(): boolean;
62
+ /** replaces the root content with the given widget. */
63
+ setContent(widget: Widget): void;
64
+ /** removes listeners, tears down the surface, and removes the canvas. */
65
+ dispose(): void;
66
+ }
@@ -0,0 +1 @@
1
+ import{loadDefaultAtlas as t}from"../assets/default-atlas.mjs";import{Canvas2DRenderer as e}from"../core/canvas2d-renderer.mjs";import{createFontAtlas as i}from"../core/font-generator.mjs";import{InputDispatcher as s}from"../core/input.mjs";import{StackLayout as a}from"../core/layouts/stack-layout.mjs";import{Surface as n}from"../core/surface.mjs";import{DEFAULTS as r}from"../defaults.mjs";import{InspectDebugger as o}from"./inspect-debugger.mjs";import{createDarkTheme as l}from"../themes/dark.mjs";import{getVisibilityFromStorage as h,setVisibilityToStorage as d}from"../utils/persistence.mjs";import{Box as p}from"../widgets/box.mjs";const c=/* @__PURE__ */new Set(["bgApp","bgPanel","bgPanelInset","bgPanelRaised","bgButton","bgButtonHover","bgButtonActive","bgInput","bgSelected","bgScrollTrack","bgScrollThumb","borderPanel","borderInset","borderRaised","textPrimary","textSecondary","textMuted","textValue","textTitle","textHighlight","spacingXS","spacingSM","spacingMD","spacingLG","borderRadius","buttonHeight","labelHeight","separatorThickness","bgFolder","bgFolderHover","textFolder","bgAccent","bgAccentDim","textLabel","bgOverlay","controlHeight","controlGap","labelRatio","folderHeaderHeight","panelPadding","scrollbarWidth","textOffsetY"]);class v{canvas;surface;renderer;input;theme;root;visible;ready;keyHandler=null;options;hovered=!1;enterHandler=null;leaveHandler=null;debugger_=null;panelPosition;panelMargin;panelWidth;constructor(t,i){this.options=i;const d=i.width??r.panelDefaultWidth,c=i.position??"right",v=i.margin??0,g=i.storageKey??r.panelDefaultStorageKey;if(this.panelPosition=c,this.panelMargin=v,this.panelWidth=d,!1!==i.persistVisibility){const t=h(g);this.visible=null!==t?t:i.initiallyVisible??!1}else this.visible=i.initiallyVisible??!1;this.canvas=document.createElement("canvas"),this.canvas.style.position="fixed",this.canvas.style.top=`${v}px`,this.canvas.style.width=`${d}px`,this.canvas.style.height=`calc(100vh - ${2*v}px)`,this.canvas.style.zIndex=r.panelZIndex,i.borderRadius&&(this.canvas.style.borderRadius=`${i.borderRadius}px`),this.canvas.style.transition=`${c} ${r.panelTransitionEasing} ${r.panelTransitionDuration}`;const u=-(d+r.panelHiddenOffsetExtra+v)+"px",b=`${v}px`,m=r.panelBoxShadowX,f=r.panelBoxShadowBlur,y=r.panelBoxShadowColor;"right"===c?(this.canvas.style.right=this.visible?b:u,this.canvas.style.boxShadow=`-${m}px 0px ${f}px ${y}`):(this.canvas.style.left=this.visible?b:u,this.canvas.style.boxShadow=`${m}px 0px ${f}px ${y}`),t.appendChild(this.canvas),this.renderer=new e(this.canvas),this.theme=l(null),this.surface=new n(this.canvas,this.renderer,this.theme),this.input=new s(this.surface),i.debugMode&&(this.debugger_=new o(this.surface,this.canvas)),this.root=new p,this.root.sizingX="grow",this.root.sizingY="grow",this.root.bgColor=this.theme.bgApp,this.root.borderRadius=i.borderRadius??0,this.root.layout=new a("vertical",0,"start","stretch"),this.surface.setRoot(this.root),this.enterHandler=()=>{this.hovered=!0},this.leaveHandler=()=>{this.hovered=!1},this.canvas.addEventListener("pointerenter",this.enterHandler),this.canvas.addEventListener("pointerleave",this.leaveHandler),this.keyHandler=null,this.ready=this.initFontAtlas(i)}async initFontAtlas(e){const s=void 0!==e.fontUrl||void 0!==e.fontData||void 0!==e.fontFamily?await i({family:e.fontFamily??r.panelDefaultFontFamily,size:e.fontSize??r.panelDefaultFontSize,fontUrl:e.fontUrl,fontData:e.fontData,pixelPerfect:void 0!==e.fontUrl||void 0!==e.fontData,extraChars:"v>‹›"}):await t(),a=e.theme;this.theme=a&&"string"!=typeof a?{...a,fontAtlas:s}:l(s);const n=function(t){let e=null;const i=t;for(const t of c)"borderRadius"!==t&&t in i&&void 0!==i[t]&&(e||(e={}),e[t]=i[t]);return void 0!==t.widgetBorderRadius&&(e||(e={}),e.borderRadius=t.widgetBorderRadius),e}(e);n&&(this.theme={...this.theme,...n,fontAtlas:s}),this.root.bgColor=this.theme.bgApp,this.surface.setTheme(this.theme)}toggle(){this.visible?this.hide():this.show()}applyPosition(){const t=`${this.panelMargin}px`,e=-(this.panelWidth+50+this.panelMargin)+"px";"right"===this.panelPosition?this.canvas.style.right=this.visible?t:e:this.canvas.style.left=this.visible?t:e}show(){this.visible||(this.visible=!0,this.applyPosition(),this.surface.markDirty(),!1!==this.options.persistVisibility&&d(!0,this.options.storageKey??r.panelDefaultStorageKey))}hide(){this.visible&&(this.visible=!1,this.applyPosition(),!1!==this.options.persistVisibility&&d(!1,this.options.storageKey??r.panelDefaultStorageKey))}isVisible(){return this.visible}isHovered(){return this.hovered}setContent(t){this.root.removeAllChildren(),this.root.addChild(t),this.surface.markDirty()}dispose(){this.keyHandler&&(window.removeEventListener("keydown",this.keyHandler),this.keyHandler=null),this.enterHandler&&(this.canvas.removeEventListener("pointerenter",this.enterHandler),this.enterHandler=null),this.leaveHandler&&(this.canvas.removeEventListener("pointerleave",this.leaveHandler),this.leaveHandler=null),this.debugger_&&(this.debugger_.dispose(),this.debugger_=null),this.input.dispose(),this.surface.dispose(),this.canvas.remove()}}export{v as InspectPanel};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),exports.StateManager=class{exportState(o){const e={};for(const[n,t]of o.monitors)e[n]=t.config.value();for(const n of o.folders.values())for(const o of n.children)if("config"in o){const n=o.config;n.key&&n.value&&(e[n.key]=n.value())}return e}importState(o,e){for(const n of o.folders.values())for(const o of n.children){if(!("config"in o))continue;const n=o,t=n.config.key;if(!t||!(t in e))continue;const r=e[t];n.config.onChange&&n.config.onChange(r),n.refresh&&n.refresh()}for(const[n,t]of o.monitors)n in e&&t.widget.refresh()}};
@@ -0,0 +1,8 @@
1
+ import { WidgetBuilder } from './widget-builder';
2
+ /** Serializes and deserializes control state to/from plain objects for persistence. */
3
+ export declare class StateManager {
4
+ /** collects current control and monitor values into a keyed state object. */
5
+ exportState(builder: WidgetBuilder): Record<string, unknown>;
6
+ /** applies a keyed state object back onto controls and refreshes monitors. */
7
+ importState(builder: WidgetBuilder, state: Record<string, unknown>): void;
8
+ }
@@ -0,0 +1 @@
1
+ class o{exportState(o){const n={};for(const[e,f]of o.monitors)n[e]=f.config.value();for(const e of o.folders.values())for(const o of e.children)if("config"in o){const e=o.config;e.key&&e.value&&(n[e.key]=e.value())}return n}importState(o,n){for(const e of o.folders.values())for(const o of e.children){if(!("config"in o))continue;const e=o,f=e.config.key;if(!f||!(f in n))continue;const r=n[f];e.config.onChange&&e.config.onChange(r),e.refresh&&e.refresh()}for(const[e,f]of o.monitors)e in n&&f.widget.refresh()}}export{o as StateManager};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../core/widget.cjs"),t=require("../gui/gui-button.cjs"),i=require("../gui/gui-button-row.cjs"),o=require("../gui/gui-color.cjs"),n=require("../gui/gui-folder.cjs"),r=require("../gui/gui-monitor.cjs"),l=require("../gui/gui-reorder-list.cjs"),s=require("../gui/gui-select.cjs"),u=require("../gui/gui-separator.cjs"),a=require("../gui/gui-slider.cjs"),h=require("../gui/gui-text.cjs"),c=require("../gui/gui-text-log.cjs"),g=require("../gui/gui-toggle.cjs");exports.WidgetBuilder=class{theme;monitors=new Map;textLogs=new Map;customControls=new Map;folders=new Map;reorderLists=new Map;_monitorList=[];_textLogList=[];constructor(e){this.theme=e}buildFolder(e){const t=new n.GuiFolder;return t.id=e.id,t.title=e.title,t.expanded=e.expanded??!1,t.applyTheme(this.theme),this.folders.set(e.id,t),t}buildControls(e,t,i){for(let o=0;o<t.length;o++){const n=this.buildControl(e,t[o],i);n&&e.addControl(n)}}buildControl(t,i,o){switch(i.type){case"slider":return this.buildSlider(i.config);case"toggle":return this.buildToggle(i.config);case"select":return this.buildSelect(i.config);case"button":return this.buildButton(i.config);case"monitor":return this.buildMonitor(i.config);case"color":return this.buildColor(i.config);case"text":return this.buildText(i.config);case"point2d":return this.buildPoint2D(i.config);case"point3d":return this.buildPoint3D(i.config);case"separator":return this.buildSeparator();case"buttonRow":return this.buildButtonRow(i.config);case"subfolder":return this.buildSubfolder(i.config.title,i.config.expanded,i.config.controls,o);case"reorderList":return this.buildReorderList(i.config);case"textLog":return this.buildTextLog(i.config);default:{const n=i;if(o){const i=o[n.type];if(i){const o=i(t,n.config),r=n.config.key;if(o&&r&&this.customControls.set(r,o),o instanceof e.Widget)return o}}return null}}}buildSlider(e){const t=new a.GuiSlider({key:e.key,label:e.label??e.key,min:e.min,max:e.max,step:e.step??0,value:e.value,onChange:e.onChange,applyOnRelease:e.applyOnRelease});return t.applyTheme(this.theme),t}buildToggle(e){const t=new g.GuiToggle({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildSelect(e){const t=new s.GuiSelect({key:e.key,label:e.label??e.key,options:e.options,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildButton(e){const i=new t.GuiButton(e.title,e.onClick);return i.applyTheme(this.theme),i}buildMonitor(e){const t=new r.GuiMonitor({key:e.key,label:e.label??e.key,value:e.value,format:e.format,graph:"graph"===e.view,interval:e.interval,min:e.min,max:e.max});t.applyTheme(this.theme),t.refresh();const i={widget:t,config:e};return this.monitors.set(e.key,i),this._monitorList.push(i),t}buildColor(e){const t=new o.GuiColor({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange,mode:e.colorType??"float",alpha:e.alpha,displayFormat:e.displayFormat});return t.applyTheme(this.theme),t}buildText(e){const t=new h.GuiText({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildPoint2D(e){const t=new n.GuiFolder;t.id=e.key,t.title=e.label??e.key,t.expanded=!0,t.applyTheme(this.theme);const i=new a.GuiSlider({key:e.key+".x",label:"x",min:e.x?.min??-100,max:e.x?.max??100,step:e.x?.step??.01,value:()=>e.value().x,onChange:t=>{const i=e.value();e.onChange({x:t,y:i.y})}});i.applyTheme(this.theme),t.addControl(i);const o=new a.GuiSlider({key:e.key+".y",label:"y",min:e.y?.min??-100,max:e.y?.max??100,step:e.y?.step??.01,value:()=>e.value().y,onChange:t=>{const i=e.value();e.onChange({x:i.x,y:t})}});return o.applyTheme(this.theme),t.addControl(o),t}buildPoint3D(e){const t=new n.GuiFolder;t.id=e.key,t.title=e.label??e.key,t.expanded=!0,t.applyTheme(this.theme);const i=[{name:"x",getter:()=>e.value().x,setter:t=>{const i=e.value();e.onChange({x:t,y:i.y,z:i.z})}},{name:"y",getter:()=>e.value().y,setter:t=>{const i=e.value();e.onChange({x:i.x,y:t,z:i.z})}},{name:"z",getter:()=>e.value().z,setter:t=>{const i=e.value();e.onChange({x:i.x,y:i.y,z:t})}}];for(const o of i){const i=new a.GuiSlider({key:e.key+"."+o.name,label:o.name,min:-100,max:100,step:.01,value:o.getter,onChange:o.setter});i.applyTheme(this.theme),t.addControl(i)}return t}buildSeparator(){const e=new u.GuiSeparator;return e.applyTheme(this.theme),e}buildButtonRow(e){const t=new i.GuiButtonRow(e);return t.applyTheme(this.theme),t}buildSubfolder(e,t,i,o){const r=new n.GuiFolder;return r.id=e,r.title=e,r.expanded=t??!1,r.applyTheme(this.theme),this.buildControls(r,i,o),r}buildReorderList(e){const t=new l.GuiReorderList(e);return t.applyTheme(this.theme),this.reorderLists.set(e.key,t),t}buildTextLog(e){const t=new c.GuiTextLog(e);t.applyTheme(this.theme);const i={widget:t,config:e};return this.textLogs.set(e.key,i),this._textLogList.push(i),t}refreshMonitors(){const e=this._monitorList;for(let t=0;t<e.length;t++){const i=e[t];i.widget.isEffectivelyVisible()&&i.widget.refresh()}}refreshTextLogs(){const e=this._textLogList;for(let t=0;t<e.length;t++){const i=e[t];i.widget.isEffectivelyVisible()&&i.widget.refresh()}}clear(){this.monitors.clear(),this.textLogs.clear(),this.customControls.clear(),this.folders.clear(),this.reorderLists.clear(),this._monitorList.length=0,this._textLogList.length=0}};
@@ -0,0 +1,80 @@
1
+ import { Widget } from '../core/widget';
2
+ import { GuiFolder } from '../gui/gui-folder';
3
+ import { GuiMonitor } from '../gui/gui-monitor';
4
+ import { GuiReorderList } from '../gui/gui-reorder-list';
5
+ import { GuiTextLog } from '../gui/gui-text-log';
6
+ import { InspectTheme } from '../themes/inspect-theme';
7
+ import { ControlConfig, CustomControlBuilder, FolderConfig, MonitorConfig, TextLogConfig } from '../types';
8
+ /** a monitor widget paired with the config it was built from, for refresh and state access. */
9
+ interface MonitorEntry {
10
+ widget: GuiMonitor;
11
+ config: MonitorConfig;
12
+ }
13
+ /** a text log widget paired with the config it was built from, for refresh. */
14
+ interface TextLogEntry {
15
+ widget: GuiTextLog;
16
+ config: TextLogConfig;
17
+ }
18
+ /**
19
+ * Factory that constructs themed GUI widgets from declarative control configs.
20
+ * Tracks monitors, text logs, custom controls, and folders for refresh and state export.
21
+ */
22
+ export declare class WidgetBuilder {
23
+ /** theme applied to every widget this builder creates. */
24
+ readonly theme: InspectTheme;
25
+ /** monitor entries keyed by control key. */
26
+ readonly monitors: Map<string, MonitorEntry>;
27
+ /** text log entries keyed by control key. */
28
+ readonly textLogs: Map<string, TextLogEntry>;
29
+ /** APIs returned by custom control builders, keyed by control key. */
30
+ readonly customControls: Map<string, unknown>;
31
+ /** folders keyed by id, used for state export and refresh traversal. */
32
+ readonly folders: Map<string, GuiFolder>;
33
+ /** reorder lists keyed by control key. */
34
+ readonly reorderLists: Map<string, GuiReorderList>;
35
+ private _monitorList;
36
+ private _textLogList;
37
+ /** stores the theme applied to widgets built by this instance. */
38
+ constructor(theme: InspectTheme);
39
+ /** builds a themed folder widget and registers it by id. */
40
+ buildFolder(config: FolderConfig): GuiFolder;
41
+ /** builds each control config and adds the resulting widgets to the folder. */
42
+ buildControls(folder: GuiFolder, controls: ControlConfig[], customBuilders?: Record<string, CustomControlBuilder>): void;
43
+ /** builds a single control by type, falling back to custom builders for unknown types. */
44
+ buildControl(folder: GuiFolder, control: ControlConfig, customBuilders?: Record<string, CustomControlBuilder>): Widget | null;
45
+ /** builds a themed slider control from a slider config. */
46
+ private buildSlider;
47
+ /** builds a themed toggle control from a toggle config. */
48
+ private buildToggle;
49
+ /** builds a themed dropdown select control from a select config. */
50
+ private buildSelect;
51
+ /** builds a themed action button from a button config. */
52
+ private buildButton;
53
+ /** builds a monitor control, primes it with a first sample, and registers it for later refresh. */
54
+ private buildMonitor;
55
+ /** builds a themed color picker control from a color config. */
56
+ private buildColor;
57
+ /** builds a themed text input control from a text config. */
58
+ private buildText;
59
+ /** builds a 2D point editor as a folder of x and y sliders that read and write the shared point value. */
60
+ private buildPoint2D;
61
+ /** builds a 3D point editor as a folder of x, y, and z sliders that read and write the shared point value. */
62
+ private buildPoint3D;
63
+ /** builds a themed divider control. */
64
+ private buildSeparator;
65
+ /** builds a themed row of action buttons from a button-row config. */
66
+ private buildButtonRow;
67
+ /** builds a nested folder and recursively builds its child controls into it. */
68
+ private buildSubfolder;
69
+ /** builds a reorder list control and registers it by key. */
70
+ private buildReorderList;
71
+ /** builds a text log control and registers it for later refresh. */
72
+ private buildTextLog;
73
+ /** refreshes every visible monitor widget. */
74
+ refreshMonitors(): void;
75
+ /** refreshes every visible text log widget. */
76
+ refreshTextLogs(): void;
77
+ /** clears all tracked monitors, text logs, custom controls, folders, and lists. */
78
+ clear(): void;
79
+ }
80
+ export {};
@@ -0,0 +1 @@
1
+ import{Widget as e}from"../core/widget.mjs";import{GuiButton as t}from"../gui/gui-button.mjs";import{GuiButtonRow as o}from"../gui/gui-button-row.mjs";import{GuiColor as i}from"../gui/gui-color.mjs";import{GuiFolder as n}from"../gui/gui-folder.mjs";import{GuiMonitor as r}from"../gui/gui-monitor.mjs";import{GuiReorderList as s}from"../gui/gui-reorder-list.mjs";import{GuiSelect as l}from"../gui/gui-select.mjs";import{GuiSeparator as a}from"../gui/gui-separator.mjs";import{GuiSlider as u}from"../gui/gui-slider.mjs";import{GuiText as h}from"../gui/gui-text.mjs";import{GuiTextLog as m}from"../gui/gui-text-log.mjs";import{GuiToggle as g}from"../gui/gui-toggle.mjs";class c{theme;monitors=/* @__PURE__ */new Map;textLogs=/* @__PURE__ */new Map;customControls=/* @__PURE__ */new Map;folders=/* @__PURE__ */new Map;reorderLists=/* @__PURE__ */new Map;_monitorList=[];_textLogList=[];constructor(e){this.theme=e}buildFolder(e){const t=new n;return t.id=e.id,t.title=e.title,t.expanded=e.expanded??!1,t.applyTheme(this.theme),this.folders.set(e.id,t),t}buildControls(e,t,o){for(let i=0;i<t.length;i++){const n=this.buildControl(e,t[i],o);n&&e.addControl(n)}}buildControl(t,o,i){switch(o.type){case"slider":return this.buildSlider(o.config);case"toggle":return this.buildToggle(o.config);case"select":return this.buildSelect(o.config);case"button":return this.buildButton(o.config);case"monitor":return this.buildMonitor(o.config);case"color":return this.buildColor(o.config);case"text":return this.buildText(o.config);case"point2d":return this.buildPoint2D(o.config);case"point3d":return this.buildPoint3D(o.config);case"separator":return this.buildSeparator();case"buttonRow":return this.buildButtonRow(o.config);case"subfolder":return this.buildSubfolder(o.config.title,o.config.expanded,o.config.controls,i);case"reorderList":return this.buildReorderList(o.config);case"textLog":return this.buildTextLog(o.config);default:{const n=o;if(i){const o=i[n.type];if(o){const i=o(t,n.config),r=n.config.key;if(i&&r&&this.customControls.set(r,i),i instanceof e)return i}}return null}}}buildSlider(e){const t=new u({key:e.key,label:e.label??e.key,min:e.min,max:e.max,step:e.step??0,value:e.value,onChange:e.onChange,applyOnRelease:e.applyOnRelease});return t.applyTheme(this.theme),t}buildToggle(e){const t=new g({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildSelect(e){const t=new l({key:e.key,label:e.label??e.key,options:e.options,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildButton(e){const o=new t(e.title,e.onClick);return o.applyTheme(this.theme),o}buildMonitor(e){const t=new r({key:e.key,label:e.label??e.key,value:e.value,format:e.format,graph:"graph"===e.view,interval:e.interval,min:e.min,max:e.max});t.applyTheme(this.theme),t.refresh();const o={widget:t,config:e};return this.monitors.set(e.key,o),this._monitorList.push(o),t}buildColor(e){const t=new i({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange,mode:e.colorType??"float",alpha:e.alpha,displayFormat:e.displayFormat});return t.applyTheme(this.theme),t}buildText(e){const t=new h({key:e.key,label:e.label??e.key,value:e.value,onChange:e.onChange});return t.applyTheme(this.theme),t}buildPoint2D(e){const t=new n;t.id=e.key,t.title=e.label??e.key,t.expanded=!0,t.applyTheme(this.theme);const o=new u({key:e.key+".x",label:"x",min:e.x?.min??-100,max:e.x?.max??100,step:e.x?.step??.01,value:()=>e.value().x,onChange:t=>{const o=e.value();e.onChange({x:t,y:o.y})}});o.applyTheme(this.theme),t.addControl(o);const i=new u({key:e.key+".y",label:"y",min:e.y?.min??-100,max:e.y?.max??100,step:e.y?.step??.01,value:()=>e.value().y,onChange:t=>{const o=e.value();e.onChange({x:o.x,y:t})}});return i.applyTheme(this.theme),t.addControl(i),t}buildPoint3D(e){const t=new n;t.id=e.key,t.title=e.label??e.key,t.expanded=!0,t.applyTheme(this.theme);const o=[{name:"x",getter:()=>e.value().x,setter:t=>{const o=e.value();e.onChange({x:t,y:o.y,z:o.z})}},{name:"y",getter:()=>e.value().y,setter:t=>{const o=e.value();e.onChange({x:o.x,y:t,z:o.z})}},{name:"z",getter:()=>e.value().z,setter:t=>{const o=e.value();e.onChange({x:o.x,y:o.y,z:t})}}];for(const i of o){const o=new u({key:e.key+"."+i.name,label:i.name,min:-100,max:100,step:.01,value:i.getter,onChange:i.setter});o.applyTheme(this.theme),t.addControl(o)}return t}buildSeparator(){const e=new a;return e.applyTheme(this.theme),e}buildButtonRow(e){const t=new o(e);return t.applyTheme(this.theme),t}buildSubfolder(e,t,o,i){const r=new n;return r.id=e,r.title=e,r.expanded=t??!1,r.applyTheme(this.theme),this.buildControls(r,o,i),r}buildReorderList(e){const t=new s(e);return t.applyTheme(this.theme),this.reorderLists.set(e.key,t),t}buildTextLog(e){const t=new m(e);t.applyTheme(this.theme);const o={widget:t,config:e};return this.textLogs.set(e.key,o),this._textLogList.push(o),t}refreshMonitors(){const e=this._monitorList;for(let t=0;t<e.length;t++){const o=e[t];o.widget.isEffectivelyVisible()&&o.widget.refresh()}}refreshTextLogs(){const e=this._textLogList;for(let t=0;t<e.length;t++){const o=e[t];o.widget.isEffectivelyVisible()&&o.widget.refresh()}}clear(){this.monitors.clear(),this.textLogs.clear(),this.customControls.clear(),this.folders.clear(),this.reorderLists.clear(),this._monitorList.length=0,this._textLogList.length=0}}export{c as WidgetBuilder};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),exports.createDarkTheme=function(e){return{bgApp:232,bgPanel:168431321,bgPanelInset:64,bgPanelRaised:4294967066,bgButton:4294967071,bgButtonHover:4294967078,bgButtonActive:4294967104,bgInput:4294967060,bgSelected:2192900019,bgScrollTrack:0,bgScrollThumb:4294967078,borderPanel:4294967060,borderInset:4294967055,borderRaised:4294967060,textPrimary:4294967282,textSecondary:4294967129,textMuted:4294967168,textValue:3034382297,textTitle:4294967270,textHighlight:4294967295,fontAtlas:e,spacingXS:1,spacingSM:2,spacingMD:4,spacingLG:8,borderRadius:3,buttonHeight:24,labelHeight:24,separatorThickness:2,bgFolder:4294967055,bgFolderHover:4294967063,textFolder:4294967270,bgAccent:2192900019,bgAccentDim:2192899917,textLabel:4294967168,bgOverlay:170,controlHeight:24,controlGap:4,labelRatio:.36,folderHeaderHeight:28,panelPadding:8,scrollbarWidth:5,textOffsetY:0}};
@@ -0,0 +1,4 @@
1
+ import { InspectTheme } from './inspect-theme';
2
+ import { FontAtlas } from '../core/atlas';
3
+ /** Creates the default dark theme with semi-transparent backgrounds. */
4
+ export declare function createDarkTheme(fontAtlas: FontAtlas): InspectTheme;
@@ -0,0 +1 @@
1
+ function e(e){return{bgApp:232,bgPanel:168431321,bgPanelInset:64,bgPanelRaised:4294967066,bgButton:4294967071,bgButtonHover:4294967078,bgButtonActive:4294967104,bgInput:4294967060,bgSelected:2192900019,bgScrollTrack:0,bgScrollThumb:4294967078,borderPanel:4294967060,borderInset:4294967055,borderRaised:4294967060,textPrimary:4294967282,textSecondary:4294967129,textMuted:4294967168,textValue:3034382297,textTitle:4294967270,textHighlight:4294967295,fontAtlas:e,spacingXS:1,spacingSM:2,spacingMD:4,spacingLG:8,borderRadius:3,buttonHeight:24,labelHeight:24,separatorThickness:2,bgFolder:4294967055,bgFolderHover:4294967063,textFolder:4294967270,bgAccent:2192900019,bgAccentDim:2192899917,textLabel:4294967168,bgOverlay:170,controlHeight:24,controlGap:4,labelRatio:.36,folderHeaderHeight:28,panelPadding:8,scrollbarWidth:5,textOffsetY:0}}export{e as createDarkTheme};
@@ -0,0 +1,20 @@
1
+ import { Theme } from '../core/theme';
2
+ /** Extended theme tokens specific to the inspect panel (folders, accents, layout sizes). */
3
+ export interface InspectTheme extends Theme {
4
+ bgFolder: number;
5
+ bgFolderHover: number;
6
+ textFolder: number;
7
+ bgAccent: number;
8
+ bgAccentDim: number;
9
+ textLabel: number;
10
+ bgOverlay: number;
11
+ controlHeight: number;
12
+ controlGap: number;
13
+ /** fraction of control width given to the label column. */
14
+ labelRatio: number;
15
+ folderHeaderHeight: number;
16
+ panelPadding: number;
17
+ scrollbarWidth: number;
18
+ /** vertical nudge applied to baseline-align text within a control. */
19
+ textOffsetY: number;
20
+ }
package/dist/types.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";function t(t){return{type:"slider",config:t}}function o(t){return{type:"toggle",config:t}}function e(t){return{type:"select",config:t}}function n(t){return{type:"color",config:t}}function r(t){return{type:"text",config:t}}function i(t){return{type:"point2d",config:t}}function c(t){return{type:"point3d",config:t}}function u(t){return t.replace(/([a-z0-9])([A-Z])/g,"$1 $2").toLowerCase()}Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),(t||(t={})).of=function(t,o,e,n){const r=t;return{type:"slider",config:{key:o,label:e.label??u(o),min:e.min,max:e.max,step:e.step,applyOnRelease:e.applyOnRelease,value:()=>r[o],onChange:t=>{r[o]=t,n?.()}}}},(o||(o={})).of=function(t,o,e,n){const r="function"==typeof e,i=r?void 0:e,c=r?e:n,p=t;return{type:"toggle",config:{key:o,label:i?.label??u(o),value:()=>p[o],onChange:t=>{p[o]=t,c?.()}}}},(e||(e={})).of=function(t,o,e,n){const r=t;return{type:"select",config:{key:o,label:e.label??u(o),options:e.options,value:()=>r[o],onChange:t=>{r[o]=t,n?.()}}}},(n||(n={})).of=function(t,o,e,n){const r="function"==typeof e,i=r?void 0:e,c=r?e:n,p=t;return{type:"color",config:{key:o,label:i?.label??u(o),colorType:i?.colorType,alpha:i?.alpha,displayFormat:i?.displayFormat,value:()=>p[o],onChange:t=>{const e=p[o];null!==t&&"object"==typeof t&&null!==e&&"object"==typeof e?Object.assign(e,t):p[o]=t,c?.()}}}},(r||(r={})).of=function(t,o,e,n){const r="function"==typeof e,i=r?void 0:e,c=r?e:n,p=t;return{type:"text",config:{key:o,label:i?.label??u(o),value:()=>p[o],onChange:t=>{p[o]=t,c?.()}}}},(i||(i={})).of=function(t,o,e,n){const r="function"==typeof e,i=r?void 0:e,c=r?e:n,p=t;return{type:"point2d",config:{key:o,label:i?.label??u(o),x:i?.x,y:i?.y,value:()=>p[o],onChange:t=>{p[o]=t,c?.()}}}},(c||(c={})).of=function(t,o,e,n){const r="function"==typeof e,i=r?void 0:e,c=r?e:n,p=t;return{type:"point3d",config:{key:o,label:i?.label??u(o),value:()=>p[o],onChange:t=>{p[o]=t,c?.()}}}},exports.button=function(t){return{type:"button",config:t}},exports.buttonRow=function(t){return{type:"buttonRow",config:t}},exports.color=n,exports.customControl=function(t,o){return{type:t,config:o}},exports.matrixGrid=function(t){return{type:"matrixGrid",config:t}},exports.monitor=function(t){return{type:"monitor",config:t}},exports.point2d=i,exports.point3d=c,exports.reorderList=function(t){return{type:"reorderList",config:t}},exports.select=e,exports.separator=function(t){return{type:"separator",config:{key:t}}},exports.slider=t,exports.subfolder=function(t){return{type:"subfolder",config:t}},exports.text=r,exports.textLog=function(t){return{type:"textLog",config:t}},exports.toggle=o;
@@ -0,0 +1,354 @@
1
+ import { InspectTheme } from './themes/inspect-theme';
2
+ /** Configuration for a numeric slider control. */
3
+ export interface SliderConfig {
4
+ key: string;
5
+ label?: string;
6
+ min: number;
7
+ max: number;
8
+ step?: number;
9
+ value: () => number;
10
+ onChange: (value: number) => void;
11
+ applyOnRelease?: boolean;
12
+ }
13
+ /** Configuration for a boolean toggle control. */
14
+ export interface ToggleConfig {
15
+ key: string;
16
+ label?: string;
17
+ value: () => boolean;
18
+ onChange: (value: boolean) => void;
19
+ }
20
+ /** Configuration for a dropdown select control. */
21
+ export interface SelectConfig<T = string | number> {
22
+ key: string;
23
+ label?: string;
24
+ options: Record<string, T>;
25
+ value: () => T;
26
+ onChange: (value: T) => void;
27
+ }
28
+ /** Configuration for a clickable button control. */
29
+ export interface ButtonConfig {
30
+ key: string;
31
+ title: string;
32
+ onClick: () => void;
33
+ }
34
+ /** Configuration for a read-only monitor display (text or graph). */
35
+ export interface MonitorConfig {
36
+ key: string;
37
+ label?: string;
38
+ value: () => string | number;
39
+ interval?: number;
40
+ format?: (v: number) => string;
41
+ view?: "graph";
42
+ min?: number;
43
+ max?: number;
44
+ rows?: number;
45
+ }
46
+ /** Supported display representations for color values. */
47
+ export type ColorDisplayFormat = "hex" | "hexAlpha" | "floatRgb" | "floatRgba" | "intRgb" | "intRgba";
48
+ /** Configuration for a color picker control. */
49
+ export interface ColorConfig {
50
+ key: string;
51
+ label?: string;
52
+ value: () => string | {
53
+ r: number;
54
+ g: number;
55
+ b: number;
56
+ };
57
+ onChange: (value: string | {
58
+ r: number;
59
+ g: number;
60
+ b: number;
61
+ }) => void;
62
+ alpha?: boolean;
63
+ colorType?: "float" | "int";
64
+ displayFormat?: ColorDisplayFormat;
65
+ }
66
+ /** Configuration for a text input control. */
67
+ export interface TextConfig {
68
+ key: string;
69
+ label?: string;
70
+ value: () => string;
71
+ onChange: (value: string) => void;
72
+ }
73
+ /** Configuration for a 2D point editor (x, y). */
74
+ export interface Point2DConfig {
75
+ key: string;
76
+ label?: string;
77
+ value: () => {
78
+ x: number;
79
+ y: number;
80
+ };
81
+ onChange: (value: {
82
+ x: number;
83
+ y: number;
84
+ }) => void;
85
+ x?: {
86
+ min?: number;
87
+ max?: number;
88
+ step?: number;
89
+ };
90
+ y?: {
91
+ min?: number;
92
+ max?: number;
93
+ step?: number;
94
+ };
95
+ }
96
+ /** Configuration for a 3D point editor (x, y, z). */
97
+ export interface Point3DConfig {
98
+ key: string;
99
+ label?: string;
100
+ value: () => {
101
+ x: number;
102
+ y: number;
103
+ z: number;
104
+ };
105
+ onChange: (value: {
106
+ x: number;
107
+ y: number;
108
+ z: number;
109
+ }) => void;
110
+ }
111
+ /** Configuration for a visual separator line. */
112
+ export interface SeparatorConfig {
113
+ key: string;
114
+ }
115
+ /** Configuration for an editable interaction matrix grid. */
116
+ export interface MatrixGridConfig {
117
+ key: string;
118
+ label?: string;
119
+ nTypes: number;
120
+ matrix: Float32Array;
121
+ maxTypes: number;
122
+ palette: Float32Array;
123
+ onChange: (row: number, col: number, value: number) => void;
124
+ minValue?: number;
125
+ maxValue?: number;
126
+ tooltip?: (row: number, col: number, value: number) => string;
127
+ }
128
+ /** Configuration for a row of buttons sharing one line. */
129
+ export interface ButtonRowConfig {
130
+ key: string;
131
+ buttons: {
132
+ title: string;
133
+ onClick: () => void;
134
+ }[];
135
+ }
136
+ /** Configuration for a collapsible subfolder of controls. */
137
+ export interface SubfolderConfig {
138
+ key: string;
139
+ title: string;
140
+ expanded?: boolean;
141
+ controls: ControlConfig[];
142
+ }
143
+ /** Configuration for a drag-to-reorder list widget. */
144
+ export interface ReorderListConfig {
145
+ key: string;
146
+ items: {
147
+ id: string;
148
+ label: string;
149
+ }[];
150
+ onChange: (newOrder: string[]) => void;
151
+ }
152
+ /** Configuration for a scrollable text log display. */
153
+ export interface TextLogConfig {
154
+ key: string;
155
+ rows?: number;
156
+ getValue: () => string;
157
+ }
158
+ /** Discriminated union of all control configurations. */
159
+ export type ControlConfig = {
160
+ type: "slider";
161
+ config: SliderConfig;
162
+ } | {
163
+ type: "toggle";
164
+ config: ToggleConfig;
165
+ } | {
166
+ type: "select";
167
+ config: SelectConfig;
168
+ } | {
169
+ type: "button";
170
+ config: ButtonConfig;
171
+ } | {
172
+ type: "monitor";
173
+ config: MonitorConfig;
174
+ } | {
175
+ type: "color";
176
+ config: ColorConfig;
177
+ } | {
178
+ type: "text";
179
+ config: TextConfig;
180
+ } | {
181
+ type: "point2d";
182
+ config: Point2DConfig;
183
+ } | {
184
+ type: "point3d";
185
+ config: Point3DConfig;
186
+ } | {
187
+ type: "separator";
188
+ config: SeparatorConfig;
189
+ } | {
190
+ type: "matrixGrid";
191
+ config: MatrixGridConfig;
192
+ } | {
193
+ type: "buttonRow";
194
+ config: ButtonRowConfig;
195
+ } | {
196
+ type: "subfolder";
197
+ config: SubfolderConfig;
198
+ } | {
199
+ type: "reorderList";
200
+ config: ReorderListConfig;
201
+ } | {
202
+ type: "textLog";
203
+ config: TextLogConfig;
204
+ };
205
+ /** Top-level folder containing a set of controls. */
206
+ export interface FolderConfig {
207
+ id: string;
208
+ title: string;
209
+ expanded?: boolean;
210
+ parent?: string;
211
+ controls: ControlConfig[];
212
+ }
213
+ /** Configuration for a single tab page containing folders. */
214
+ export interface TabPageConfig {
215
+ title: string;
216
+ folders: FolderConfig[];
217
+ showImportExport?: boolean;
218
+ }
219
+ /** Callback signature for registering a custom control builder. */
220
+ export type CustomControlBuilder = (folder: any, config: Record<string, any>) => any;
221
+ /** Mount options common to the panel, independent of theme and font settings. */
222
+ export interface BaseMountOptions {
223
+ position?: "left" | "right";
224
+ width?: number;
225
+ toggleKey?: string;
226
+ persistVisibility?: boolean;
227
+ storageKey?: string;
228
+ initiallyVisible?: boolean;
229
+ showImportExport?: boolean;
230
+ showToggleButton?: boolean;
231
+ toggleButtonSize?: number;
232
+ tabBarReservedEdge?: number;
233
+ borderRadius?: number;
234
+ margin?: number;
235
+ debugMode?: boolean;
236
+ customPlugins?: unknown[];
237
+ customControlBuilders?: Record<string, CustomControlBuilder>;
238
+ }
239
+ /** Create a slider control config. */
240
+ export declare function slider(config: SliderConfig): ControlConfig;
241
+ /** Create a toggle control config. */
242
+ export declare function toggle(config: ToggleConfig): ControlConfig;
243
+ /** Create a select control config. */
244
+ export declare function select<T = string | number>(config: SelectConfig<T>): ControlConfig;
245
+ /** Create a button control config. */
246
+ export declare function button(config: ButtonConfig): ControlConfig;
247
+ /** Create a monitor control config. */
248
+ export declare function monitor(config: MonitorConfig): ControlConfig;
249
+ /** Create a color picker control config. */
250
+ export declare function color(config: ColorConfig): ControlConfig;
251
+ /** Create a text input control config. */
252
+ export declare function text(config: TextConfig): ControlConfig;
253
+ /** Create a 2D point editor control config. */
254
+ export declare function point2d(config: Point2DConfig): ControlConfig;
255
+ /** Create a 3D point editor control config. */
256
+ export declare function point3d(config: Point3DConfig): ControlConfig;
257
+ /** Create a separator control config. */
258
+ export declare function separator(key: string): ControlConfig;
259
+ /** Create a matrix grid control config. */
260
+ export declare function matrixGrid(config: MatrixGridConfig): ControlConfig;
261
+ /** Create a button row control config. */
262
+ export declare function buttonRow(config: ButtonRowConfig): ControlConfig;
263
+ /** Create a subfolder control config. */
264
+ export declare function subfolder(config: SubfolderConfig): ControlConfig;
265
+ /** Create a reorder list control config. */
266
+ export declare function reorderList(config: ReorderListConfig): ControlConfig;
267
+ /** Create a text log control config. */
268
+ export declare function textLog(config: TextLogConfig): ControlConfig;
269
+ /** Create a custom control config with an arbitrary type string. */
270
+ export declare function customControl(type: string, config: Record<string, any>): ControlConfig;
271
+ /** Extract keys of T whose values extend V. */
272
+ export type KeysOfType<T, V> = {
273
+ [K in keyof T]: T[K] extends V ? K : never;
274
+ }[keyof T] & string;
275
+ export declare namespace slider {
276
+ /** Bind a slider to a numeric property of the target object. */
277
+ function of<T>(target: T, key: KeysOfType<T, number>, opts: {
278
+ min: number;
279
+ max: number;
280
+ step?: number;
281
+ label?: string;
282
+ applyOnRelease?: boolean;
283
+ }, onChange?: () => void): ControlConfig;
284
+ }
285
+ export declare namespace toggle {
286
+ /** Bind a toggle to a boolean property of the target object. */
287
+ function of<T>(target: T, key: KeysOfType<T, boolean>, optsOrOnChange?: {
288
+ label?: string;
289
+ } | (() => void), onChange?: () => void): ControlConfig;
290
+ }
291
+ export declare namespace select {
292
+ /** Bind a select dropdown to a string or number property of the target object. */
293
+ function of<T>(target: T, key: KeysOfType<T, string | number>, opts: {
294
+ options: Record<string, string | number>;
295
+ label?: string;
296
+ }, onChange?: () => void): ControlConfig;
297
+ }
298
+ export declare namespace color {
299
+ /** Bind a color picker to a color property of the target object. */
300
+ function of<T>(target: T, key: KeysOfType<T, string | {
301
+ r: number;
302
+ g: number;
303
+ b: number;
304
+ }>, optsOrOnChange?: {
305
+ colorType?: "float" | "int";
306
+ alpha?: boolean;
307
+ label?: string;
308
+ displayFormat?: ColorDisplayFormat;
309
+ } | (() => void), onChange?: () => void): ControlConfig;
310
+ }
311
+ export declare namespace text {
312
+ /** Bind a text input to a string property of the target object. */
313
+ function of<T>(target: T, key: KeysOfType<T, string>, optsOrOnChange?: {
314
+ label?: string;
315
+ } | (() => void), onChange?: () => void): ControlConfig;
316
+ }
317
+ export declare namespace point2d {
318
+ /** Bind a 2D point editor to an {x, y} property of the target object. */
319
+ function of<T>(target: T, key: KeysOfType<T, {
320
+ x: number;
321
+ y: number;
322
+ }>, optsOrOnChange?: {
323
+ label?: string;
324
+ x?: {
325
+ min?: number;
326
+ max?: number;
327
+ step?: number;
328
+ };
329
+ y?: {
330
+ min?: number;
331
+ max?: number;
332
+ step?: number;
333
+ };
334
+ } | (() => void), onChange?: () => void): ControlConfig;
335
+ }
336
+ export declare namespace point3d {
337
+ /** Bind a 3D point editor to an {x, y, z} property of the target object. */
338
+ function of<T>(target: T, key: KeysOfType<T, {
339
+ x: number;
340
+ y: number;
341
+ z: number;
342
+ }>, optsOrOnChange?: {
343
+ label?: string;
344
+ } | (() => void), onChange?: () => void): ControlConfig;
345
+ }
346
+ /** Options for mounting the inspect panel into the DOM. */
347
+ export interface MountOptions extends BaseMountOptions, Partial<Omit<InspectTheme, "fontAtlas" | "borderRadius">> {
348
+ theme?: "dark" | InspectTheme;
349
+ widgetBorderRadius?: number;
350
+ fontUrl?: string;
351
+ fontData?: ArrayBuffer;
352
+ fontFamily?: string;
353
+ fontSize?: number;
354
+ }
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+ function n(n){return{type:"slider",config:n}}function t(n){return{type:"toggle",config:n}}function e(n){return{type:"select",config:n}}function o(n){return{type:"button",config:n}}function i(n){return{type:"monitor",config:n}}function c(n){return{type:"color",config:n}}function r(n){return{type:"text",config:n}}function f(n){return{type:"point2d",config:n}}function u(n){return{type:"point3d",config:n}}function l(n){return{type:"separator",config:{key:n}}}function p(n){return{type:"matrixGrid",config:n}}function a(n){return{type:"buttonRow",config:n}}function y(n){return{type:"subfolder",config:n}}function g(n){return{type:"reorderList",config:n}}function s(n){return{type:"textLog",config:n}}function b(n,t){return{type:n,config:t}}function d(n){return n.replace(/([a-z0-9])([A-Z])/g,"$1 $2").toLowerCase()}(n||(n={})).of=function(n,t,e,o){const i=n;return{type:"slider",config:{key:t,label:e.label??d(t),min:e.min,max:e.max,step:e.step,applyOnRelease:e.applyOnRelease,value:()=>i[t],onChange:n=>{i[t]=n,o?.()}}}},(t||(t={})).of=function(n,t,e,o){const i="function"==typeof e,c=i?void 0:e,r=i?e:o,f=n;return{type:"toggle",config:{key:t,label:c?.label??d(t),value:()=>f[t],onChange:n=>{f[t]=n,r?.()}}}},(e||(e={})).of=function(n,t,e,o){const i=n;return{type:"select",config:{key:t,label:e.label??d(t),options:e.options,value:()=>i[t],onChange:n=>{i[t]=n,o?.()}}}},(c||(c={})).of=function(n,t,e,o){const i="function"==typeof e,c=i?void 0:e,r=i?e:o,f=n;return{type:"color",config:{key:t,label:c?.label??d(t),colorType:c?.colorType,alpha:c?.alpha,displayFormat:c?.displayFormat,value:()=>f[t],onChange:n=>{const e=f[t];null!==n&&"object"==typeof n&&null!==e&&"object"==typeof e?Object.assign(e,n):f[t]=n,r?.()}}}},(r||(r={})).of=function(n,t,e,o){const i="function"==typeof e,c=i?void 0:e,r=i?e:o,f=n;return{type:"text",config:{key:t,label:c?.label??d(t),value:()=>f[t],onChange:n=>{f[t]=n,r?.()}}}},(f||(f={})).of=function(n,t,e,o){const i="function"==typeof e,c=i?void 0:e,r=i?e:o,f=n;return{type:"point2d",config:{key:t,label:c?.label??d(t),x:c?.x,y:c?.y,value:()=>f[t],onChange:n=>{f[t]=n,r?.()}}}},(u||(u={})).of=function(n,t,e,o){const i="function"==typeof e,c=i?void 0:e,r=i?e:o,f=n;return{type:"point3d",config:{key:t,label:c?.label??d(t),value:()=>f[t],onChange:n=>{f[t]=n,r?.()}}}};export{o as button,a as buttonRow,c as color,b as customControl,p as matrixGrid,i as monitor,f as point2d,u as point3d,g as reorderList,e as select,l as separator,n as slider,y as subfolder,r as text,s as textLog,t as toggle};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let t=!1;exports.getGuiActive=function(){return t},exports.setGuiActive=function(e){t=e};
@@ -0,0 +1,4 @@
1
+ /** set whether a GUI control is currently being interacted with. */
2
+ export declare function setGuiActive(active: boolean): void;
3
+ /** whether a GUI control is currently being interacted with. */
4
+ export declare function getGuiActive(): boolean;
@@ -0,0 +1 @@
1
+ let n=!1;function t(t){n=t}function e(){return n}export{e as getGuiActive,t as setGuiActive};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=[0,0,0],r=[0,0,0],o=Array.from({length:256},(t,r)=>r.toString(16).padStart(2,"0"));exports.HEX_LUT=o,exports.hsvToRgb=function(t,o,e){const n=e*o,s=n*(1-Math.abs(t/60%2-1)),a=e-n;let c=0,u=0,i=0;return t<60?(c=n,u=s,i=0):t<120?(c=s,u=n,i=0):t<180?(c=0,u=n,i=s):t<240?(c=0,u=s,i=n):t<300?(c=s,u=0,i=n):(c=n,u=0,i=s),r[0]=c+a,r[1]=u+a,r[2]=i+a,r},exports.packRGBA=function(t,r,o,e=1){return(255*t+.5<<24|255*r+.5<<16|255*o+.5<<8|255*e+.5)>>>0},exports.rgbToHsv=function(r,o,e){const n=Math.max(r,o,e),s=n-Math.min(r,o,e);let a=0;return s>0&&(a=n===r?(o-e)/s%6:n===o?(e-r)/s+2:(r-o)/s+4,a*=60,a<0&&(a+=360)),t[0]=a,t[1]=0===n?0:s/n,t[2]=n,t};