@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.
- package/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/Inspect.cjs +1 -0
- package/dist/Inspect.d.ts +68 -0
- package/dist/Inspect.mjs +1 -0
- package/dist/InspectRegistry.cjs +1 -0
- package/dist/InspectRegistry.d.ts +52 -0
- package/dist/InspectRegistry.mjs +1 -0
- package/dist/assets/default-atlas.cjs +1 -0
- package/dist/assets/default-atlas.d.ts +6 -0
- package/dist/assets/default-atlas.mjs +1 -0
- package/dist/core/atlas.cjs +1 -0
- package/dist/core/atlas.d.ts +29 -0
- package/dist/core/atlas.mjs +1 -0
- package/dist/core/canvas2d-renderer.cjs +1 -0
- package/dist/core/canvas2d-renderer.d.ts +94 -0
- package/dist/core/canvas2d-renderer.mjs +1 -0
- package/dist/core/font-generator.cjs +1 -0
- package/dist/core/font-generator.d.ts +20 -0
- package/dist/core/font-generator.mjs +1 -0
- package/dist/core/glyph-rasterizer.cjs +1 -0
- package/dist/core/glyph-rasterizer.d.ts +10 -0
- package/dist/core/glyph-rasterizer.mjs +1 -0
- package/dist/core/input.cjs +1 -0
- package/dist/core/input.d.ts +89 -0
- package/dist/core/input.mjs +1 -0
- package/dist/core/layout.d.ts +10 -0
- package/dist/core/layouts/stack-layout.cjs +1 -0
- package/dist/core/layouts/stack-layout.d.ts +69 -0
- package/dist/core/layouts/stack-layout.mjs +1 -0
- package/dist/core/renderer.d.ts +65 -0
- package/dist/core/surface.cjs +1 -0
- package/dist/core/surface.d.ts +81 -0
- package/dist/core/surface.mjs +1 -0
- package/dist/core/theme.d.ts +33 -0
- package/dist/core/ttf-parser.cjs +1 -0
- package/dist/core/ttf-parser.d.ts +29 -0
- package/dist/core/ttf-parser.mjs +1 -0
- package/dist/core/widget.cjs +1 -0
- package/dist/core/widget.d.ts +213 -0
- package/dist/core/widget.mjs +1 -0
- package/dist/defaults.cjs +1 -0
- package/dist/defaults.d.ts +113 -0
- package/dist/defaults.mjs +1 -0
- package/dist/gui/gui-button-row.cjs +1 -0
- package/dist/gui/gui-button-row.d.ts +21 -0
- package/dist/gui/gui-button-row.mjs +1 -0
- package/dist/gui/gui-button.cjs +1 -0
- package/dist/gui/gui-button.d.ts +9 -0
- package/dist/gui/gui-button.mjs +1 -0
- package/dist/gui/gui-color.cjs +1 -0
- package/dist/gui/gui-color.d.ts +105 -0
- package/dist/gui/gui-color.mjs +1 -0
- package/dist/gui/gui-folder.cjs +1 -0
- package/dist/gui/gui-folder.d.ts +49 -0
- package/dist/gui/gui-folder.mjs +1 -0
- package/dist/gui/gui-monitor.cjs +1 -0
- package/dist/gui/gui-monitor.d.ts +53 -0
- package/dist/gui/gui-monitor.mjs +1 -0
- package/dist/gui/gui-point2d.d.ts +43 -0
- package/dist/gui/gui-point3d.d.ts +48 -0
- package/dist/gui/gui-reorder-list.cjs +1 -0
- package/dist/gui/gui-reorder-list.d.ts +42 -0
- package/dist/gui/gui-reorder-list.mjs +1 -0
- package/dist/gui/gui-select.cjs +1 -0
- package/dist/gui/gui-select.d.ts +40 -0
- package/dist/gui/gui-select.mjs +1 -0
- package/dist/gui/gui-separator.cjs +1 -0
- package/dist/gui/gui-separator.d.ts +10 -0
- package/dist/gui/gui-separator.mjs +1 -0
- package/dist/gui/gui-slider.cjs +1 -0
- package/dist/gui/gui-slider.d.ts +34 -0
- package/dist/gui/gui-slider.mjs +1 -0
- package/dist/gui/gui-tab-container.d.ts +26 -0
- package/dist/gui/gui-text-log.cjs +1 -0
- package/dist/gui/gui-text-log.d.ts +24 -0
- package/dist/gui/gui-text-log.mjs +1 -0
- package/dist/gui/gui-text.cjs +1 -0
- package/dist/gui/gui-text.d.ts +22 -0
- package/dist/gui/gui-text.mjs +1 -0
- package/dist/gui/gui-toggle.cjs +1 -0
- package/dist/gui/gui-toggle.d.ts +19 -0
- package/dist/gui/gui-toggle.mjs +1 -0
- package/dist/gui/labeled-control.cjs +1 -0
- package/dist/gui/labeled-control.d.ts +21 -0
- package/dist/gui/labeled-control.mjs +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.mjs +1 -0
- package/dist/panel/inspect-debugger.cjs +1 -0
- package/dist/panel/inspect-debugger.d.ts +30 -0
- package/dist/panel/inspect-debugger.mjs +1 -0
- package/dist/panel/inspect-panel.cjs +1 -0
- package/dist/panel/inspect-panel.d.ts +66 -0
- package/dist/panel/inspect-panel.mjs +1 -0
- package/dist/panel/state-manager.cjs +1 -0
- package/dist/panel/state-manager.d.ts +8 -0
- package/dist/panel/state-manager.mjs +1 -0
- package/dist/panel/widget-builder.cjs +1 -0
- package/dist/panel/widget-builder.d.ts +80 -0
- package/dist/panel/widget-builder.mjs +1 -0
- package/dist/themes/dark.cjs +1 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.mjs +1 -0
- package/dist/themes/inspect-theme.d.ts +20 -0
- package/dist/types.cjs +1 -0
- package/dist/types.d.ts +354 -0
- package/dist/types.mjs +1 -0
- package/dist/utils/activity.cjs +1 -0
- package/dist/utils/activity.d.ts +4 -0
- package/dist/utils/activity.mjs +1 -0
- package/dist/utils/color-convert.cjs +1 -0
- package/dist/utils/color-convert.d.ts +31 -0
- package/dist/utils/color-convert.mjs +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/persistence.cjs +1 -0
- package/dist/utils/persistence.d.ts +16 -0
- package/dist/utils/persistence.mjs +1 -0
- package/dist/widgets/box.cjs +1 -0
- package/dist/widgets/box.d.ts +24 -0
- package/dist/widgets/box.mjs +1 -0
- package/dist/widgets/button.cjs +1 -0
- package/dist/widgets/button.d.ts +50 -0
- package/dist/widgets/button.mjs +1 -0
- package/dist/widgets/canvas-widget.cjs +1 -0
- package/dist/widgets/canvas-widget.d.ts +12 -0
- package/dist/widgets/canvas-widget.mjs +1 -0
- package/dist/widgets/label.cjs +1 -0
- package/dist/widgets/label.d.ts +41 -0
- package/dist/widgets/label.mjs +1 -0
- package/dist/widgets/number-input.cjs +1 -0
- package/dist/widgets/number-input.d.ts +65 -0
- package/dist/widgets/number-input.mjs +1 -0
- package/dist/widgets/overlay.d.ts +16 -0
- package/dist/widgets/scroll-area.cjs +1 -0
- package/dist/widgets/scroll-area.d.ts +80 -0
- package/dist/widgets/scroll-area.mjs +1 -0
- package/dist/widgets/separator.cjs +1 -0
- package/dist/widgets/separator.d.ts +16 -0
- package/dist/widgets/separator.mjs +1 -0
- package/dist/widgets/slider.cjs +1 -0
- package/dist/widgets/slider.d.ts +36 -0
- package/dist/widgets/slider.mjs +1 -0
- package/dist/widgets/tab-bar.cjs +1 -0
- package/dist/widgets/tab-bar.d.ts +72 -0
- package/dist/widgets/tab-bar.mjs +1 -0
- package/dist/widgets/text-input.cjs +1 -0
- package/dist/widgets/text-input.d.ts +54 -0
- package/dist/widgets/text-input.mjs +1 -0
- package/dist/widgets/toggle-button.d.ts +18 -0
- package/dist/widgets/toggle-icon.cjs +1 -0
- package/dist/widgets/toggle-icon.d.ts +38 -0
- package/dist/widgets/toggle-icon.mjs +1 -0
- package/package.json +95 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Widget } from '../core/widget';
|
|
2
|
+
import { Renderer } from '../core/renderer';
|
|
3
|
+
import { Theme } from '../core/theme';
|
|
4
|
+
/** descriptor for a single tab with its display label and value key. */
|
|
5
|
+
export interface Tab {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
/** how tab widths are computed: equal division or sized to label content. */
|
|
10
|
+
export type TabSizing = "equal" | "content";
|
|
11
|
+
/** horizontal tab bar widget with scroll arrows, hover highlighting, and separators. */
|
|
12
|
+
export declare class TabBar extends Widget {
|
|
13
|
+
/** list of tabs to display. */
|
|
14
|
+
tabs: Tab[];
|
|
15
|
+
/** value key of the currently selected tab. */
|
|
16
|
+
value: string;
|
|
17
|
+
/** background color override for the bar. */
|
|
18
|
+
bgColor: number;
|
|
19
|
+
/** background color of the active tab. */
|
|
20
|
+
activeColor: number;
|
|
21
|
+
/** text color for inactive tabs. */
|
|
22
|
+
textColor: number;
|
|
23
|
+
/** text color for the active tab. */
|
|
24
|
+
activeTextColor: number;
|
|
25
|
+
/** how tab widths are calculated. */
|
|
26
|
+
tabSizing: TabSizing;
|
|
27
|
+
/** horizontal padding within each tab in pixels. */
|
|
28
|
+
tabPadding: number;
|
|
29
|
+
/** called when the selected tab changes. */
|
|
30
|
+
onChange: ((value: string) => void) | null;
|
|
31
|
+
/** reserved space on the right edge for external elements. */
|
|
32
|
+
reservedEdge: number;
|
|
33
|
+
private tabPositions;
|
|
34
|
+
private tabWidths;
|
|
35
|
+
private scrollOffset;
|
|
36
|
+
private totalTabWidth;
|
|
37
|
+
private showLeftArrow;
|
|
38
|
+
private showRightArrow;
|
|
39
|
+
private _tabsDirty;
|
|
40
|
+
private _lastTabCount;
|
|
41
|
+
private _lastWidth;
|
|
42
|
+
private _lastCharWidth;
|
|
43
|
+
private _hoverIndex;
|
|
44
|
+
/** renders the bar background, the scrolling strip of tabs with active and hover styling, and the scroll arrows. */
|
|
45
|
+
protected drawSelf(renderer: Renderer, theme: Theme): void;
|
|
46
|
+
/** handles clicks on scroll arrows and tabs, selecting the hit tab. */
|
|
47
|
+
onPointerDown(_pointerId: number, x: number, _y: number, button: number): boolean;
|
|
48
|
+
/** scrolls the tab strip when it overflows. */
|
|
49
|
+
onWheel(deltaX: number, deltaY: number): boolean;
|
|
50
|
+
/** updates the hovered tab index under the pointer. */
|
|
51
|
+
onPointerMove(_pointerId: number, x: number, _y: number): void;
|
|
52
|
+
/** clears the hover highlight when the pointer leaves the bar. */
|
|
53
|
+
onPointerLeave(): void;
|
|
54
|
+
/** width available to the scrolling strip after reserving the edge, side padding, and an arrow. */
|
|
55
|
+
private scrollAvailableWidth;
|
|
56
|
+
/** shifts the scroll offset by delta, clamped to the scrollable range, then updates arrow visibility. */
|
|
57
|
+
private scroll;
|
|
58
|
+
/** scrolls so the selected tab is fully visible, keeping an 8px margin from the strip edge. */
|
|
59
|
+
private scrollActiveTabIntoView;
|
|
60
|
+
/** true when the tabs are wider than the space available to the strip. */
|
|
61
|
+
private overflows;
|
|
62
|
+
/** shows the left and right arrows depending on whether tabs extend past each edge. */
|
|
63
|
+
private updateArrowVisibility;
|
|
64
|
+
/** marks tab positions as stale so they are recalculated on next draw. */
|
|
65
|
+
invalidateTabs(): void;
|
|
66
|
+
/**
|
|
67
|
+
* recomputes each tab's x offset and width, either sized to its label content or split equally across
|
|
68
|
+
* the bar, then refreshes arrow visibility. skips the work when tab count, width, and glyph width are
|
|
69
|
+
* unchanged since the last call.
|
|
70
|
+
*/
|
|
71
|
+
private computeTabPositions;
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Widget as t,THEME_DEFAULT as i}from"../core/widget.mjs";import{DEFAULTS as s}from"../defaults.mjs";const h=s.tabArrowWidth,o=s.tabArrowHalf,e=s.tabStripPaddingTop,a=s.tabStripPaddingSide,l=s.tabRadius,r=s.tabSeparatorHeight,n=s.tabSeparatorColor,b=s.tabHoverColor;class d extends t{tabs=[];value="";bgColor=i;activeColor=i;textColor=i;activeTextColor=i;tabSizing="content";tabPadding=16;onChange=null;reservedEdge=0;tabPositions=new Float32Array(s.tabInitialCapacity);tabWidths=new Float32Array(s.tabInitialCapacity);scrollOffset=0;totalTabWidth=0;showLeftArrow=!1;showRightArrow=!1;_tabsDirty=!0;_lastTabCount=0;_lastWidth=0;_lastCharWidth=0;_hoverIndex=-1;drawSelf(t,s){const d=this.width,c=this.height,f=this.tabs.length;if(0===f)return;const w=this.bgColor===i?s.bgPanel:this.bgColor;t.fillRect(0,0,d,c,w);const u=s.fontAtlas,v=this.textColor===i?s.textMuted:this.textColor,g=this.activeTextColor===i?s.textPrimary:this.activeTextColor,p=this.activeColor===i?s.bgPanelRaised:this.activeColor,C=this.textColor===i?s.textMuted:this.textColor,A=u?.charWidth??8;this.computeTabPositions(d,A);const T=c-e,W=(this.showLeftArrow?h:0)+a,P=d-this.reservedEdge-(this.showRightArrow?h:0)-a-W;t.pushClip(W,0,P,c),t.pushTranslate(-this.scrollOffset+W,e);for(let i=0;i<f;i++){const s=this.tabs[i],h=this.tabPositions[i],o=this.tabWidths[i],e=s.value===this.value;if(e&&p?(t.fillRoundedRect(h,0,o,T+l,l,p),t.pushClip(h,T,o,l),t.fillRect(h,T,o,l,p),t.popClip()):i===this._hoverIndex&&(t.fillRoundedRect(h,0,o,T+l,l,b),t.pushClip(h,T,o,l),t.fillRect(h,T,o,l,b),t.popClip()),u){const a=s.label.length*A,l=Math.round(h+(o-a)/2),r=Math.round((T-u.lineHeight)/2),n=e||i===this._hoverIndex?g:v;t.drawText(u,s.label,l,r,n)}if(!e&&i<f-1&&!(i+1<f&&this.tabs[i+1].value===this.value)){const i=h+o,s=Math.round((T-r)/2);t.fillRect(i,s,1,r,n)}}if(t.popTranslate(),t.popClip(),this.showLeftArrow){t.fillRect(0,0,h+a,c,w);const i=h/2+5|0,s=2+(c/2|0);t.beginPath(),t.moveTo(i+o,s-o),t.lineTo(i-o,s),t.lineTo(i+o,s+o),t.fillPath(C)}if(this.showRightArrow){const i=d-this.reservedEdge-h-a;t.fillRect(i,0,h+a,c,w);const s=i+h/2+5|0,e=2+(c/2|0);t.beginPath(),t.moveTo(s-o,e-o),t.lineTo(s+o,e),t.lineTo(s-o,e+o),t.fillPath(C)}}onPointerDown(t,i,s,o){if(0!==o||!this.enabled)return!1;const e=this.tabs.length;if(0===e)return!1;if(this.showLeftArrow&&i<h+a)return this.scroll(.6*-this.width),!0;const l=this.width-this.reservedEdge-h-a;if(this.showRightArrow&&i>=l)return this.scroll(.6*this.width),!0;const r=i-((this.showLeftArrow?h:0)+a)+this.scrollOffset;for(let t=0;t<e;t++)if(r>=this.tabPositions[t]&&r<this.tabPositions[t]+this.tabWidths[t]){const i=this.tabs[t].value;return i!==this.value&&(this.value=i,this.scrollActiveTabIntoView(),this.onChange&&this.onChange(i),this.markDirty()),!0}return!0}onWheel(t,i){if(!this.overflows())return!1;const s=Math.abs(t)>=Math.abs(i)?t:i;return 0!==s&&(this.scroll(s),!0)}onPointerMove(t,i,s){const o=i-((this.showLeftArrow?h:0)+a)+this.scrollOffset;let e=-1;for(let t=0;t<this.tabs.length;t++)if(o>=this.tabPositions[t]&&o<this.tabPositions[t]+this.tabWidths[t]){this.tabs[t].value!==this.value&&(e=t);break}e!==this._hoverIndex&&(this._hoverIndex=e,this.markDirty())}onPointerLeave(){-1!==this._hoverIndex&&(this._hoverIndex=-1,this.markDirty())}scrollAvailableWidth(){return this.width-this.reservedEdge-2*a-h}scroll(t){const i=Math.max(0,this.totalTabWidth-this.scrollAvailableWidth());this.scrollOffset=Math.max(0,Math.min(i,this.scrollOffset+t)),this.updateArrowVisibility(),this.markDirty()}scrollActiveTabIntoView(){const t=this.tabs.length,i=this.scrollAvailableWidth();for(let s=0;s<t;s++)if(this.tabs[s].value===this.value){const t=this.tabPositions[s],h=t+this.tabWidths[s],o=this.scrollOffset,e=this.scrollOffset+i;if(t<o)this.scrollOffset=Math.max(0,t-8);else if(h>e){const t=Math.max(0,this.totalTabWidth-i);this.scrollOffset=Math.min(t,h-i+8)}this.updateArrowVisibility();break}}overflows(){const t=this.width-this.reservedEdge-2*a;return this.totalTabWidth>t}updateArrowVisibility(){const t=Math.max(0,this.totalTabWidth-this.scrollAvailableWidth()),i=t>1;this.showLeftArrow=i&&this.scrollOffset>1,this.showRightArrow=i&&this.scrollOffset<t-1}invalidateTabs(){this._tabsDirty=!0}computeTabPositions(t,i){const s=this.tabs.length;if(this._tabsDirty||s!==this._lastTabCount||t!==this._lastWidth||i!==this._lastCharWidth){if(this._tabsDirty=!1,this._lastTabCount=s,this._lastWidth=t,this._lastCharWidth=i,s>this.tabPositions.length&&(this.tabPositions=new Float32Array(s),this.tabWidths=new Float32Array(s)),"content"===this.tabSizing){let t=0;for(let h=0;h<s;h++){const s=this.tabs[h].label.length*i+2*this.tabPadding;this.tabPositions[h]=t,this.tabWidths[h]=s,t+=s}this.totalTabWidth=t}else{const i=(t-this.reservedEdge-2*a)/s|0;for(let t=0;t<s;t++)this.tabPositions[t]=t*i,this.tabWidths[t]=i;this.totalTabWidth=i*s}this.updateArrowVisibility()}}}export{d as TabBar};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../core/widget.cjs"),s=require("../defaults.cjs");class e extends t.Widget{text="";cursorPos=0;selectionStart=-1;selectionEnd=-1;placeholder="";textColor=t.THEME_DEFAULT;placeholderColor=t.THEME_DEFAULT;bgColor=t.THEME_DEFAULT;cursorColor=t.THEME_DEFAULT;selectionColor=s.DEFAULTS.textInputSelectionColor;borderRadius=2;onChange=null;cursorVisible=!0;constructor(){super(),this.focusable=!0}drawSelf(e,i){const r=this.width,o=this.height,h=i.fontAtlas;if(!h)return;const l=this.bgColor===t.THEME_DEFAULT?i.bgInput:this.bgColor;this.borderRadius>0?e.fillRoundedRect(0,0,r,o,this.borderRadius,l):e.fillRect(0,0,r,o,l);const n=(o-h.lineHeight)/2|0,c=this.innerX||s.DEFAULTS.textInputPadding;if(this.text){if(this.focused&&this.selectionStart>=0&&this.selectionEnd>this.selectionStart){const t=c+this.selectionStart*h.charWidth,s=(this.selectionEnd-this.selectionStart)*h.charWidth;e.fillRect(t,n,s,h.lineHeight,this.selectionColor)}const s=this.textColor===t.THEME_DEFAULT?i.textPrimary:this.textColor;e.drawText(h,this.text,c,n,s)}else if(this.placeholder&&!this.focused){const s=this.placeholderColor===t.THEME_DEFAULT?i.textMuted:this.placeholderColor;e.drawText(h,this.placeholder,c,n,s)}if(this.focused&&this.cursorVisible){const s=c+this.cursorPos*h.charWidth,r=this.cursorColor===t.THEME_DEFAULT?i.textPrimary:this.cursorColor;e.fillRect(s,n,1,h.lineHeight,r)}}onFocus(){this.cursorVisible=!0,this.markDirty()}onBlur(){this.selectionStart=-1,this.selectionEnd=-1,this.markDirty()}onPointerDown(t,s,e,i){return 0===i&&(this.resetBlink(),this.markDirty(),!0)}onKeyDown(t,s,e,i,r){return!(!this.enabled||(e&&"a"===t?(this.selectionStart=0,this.selectionEnd=this.text.length,this.markDirty(),0):"Backspace"===t?(this.hasSelection()?this.deleteSelection():this.cursorPos>0&&(this.text=this.text.slice(0,this.cursorPos-1)+this.text.slice(this.cursorPos),this.cursorPos--,this.onChange&&this.onChange(this.text)),this.resetBlink(),this.markDirty(),0):"Delete"===t?(this.hasSelection()?this.deleteSelection():this.cursorPos<this.text.length&&(this.text=this.text.slice(0,this.cursorPos)+this.text.slice(this.cursorPos+1),this.onChange&&this.onChange(this.text)),this.resetBlink(),this.markDirty(),0):"ArrowLeft"===t?(this.cursorPos>0&&this.cursorPos--,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"ArrowRight"===t?(this.cursorPos<this.text.length&&this.cursorPos++,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"Home"===t?(this.cursorPos=0,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"End"===t?(this.cursorPos=this.text.length,this.clearSelection(),this.resetBlink(),this.markDirty(),0):1!==t.length||e||(this.hasSelection()&&this.deleteSelection(),this.text=this.text.slice(0,this.cursorPos)+t+this.text.slice(this.cursorPos),this.cursorPos++,this.onChange&&this.onChange(this.text),this.resetBlink(),this.markDirty(),0)))}hasSelection(){return this.selectionStart>=0&&this.selectionEnd>this.selectionStart}deleteSelection(){this.hasSelection()&&(this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionEnd),this.cursorPos=this.selectionStart,this.clearSelection(),this.onChange&&this.onChange(this.text))}clearSelection(){this.selectionStart=-1,this.selectionEnd=-1}resetBlink(){this.cursorVisible=!0}}exports.TextInput=e;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Widget } from '../core/widget';
|
|
2
|
+
import { Renderer } from '../core/renderer';
|
|
3
|
+
import { Theme } from '../core/theme';
|
|
4
|
+
/** editable single-line text input widget with cursor, selection, and placeholder. */
|
|
5
|
+
export declare class TextInput extends Widget {
|
|
6
|
+
/** current text content. */
|
|
7
|
+
text: string;
|
|
8
|
+
/** character index of the editing cursor. */
|
|
9
|
+
cursorPos: number;
|
|
10
|
+
/** start index of the selection range; -1 when no selection. */
|
|
11
|
+
selectionStart: number;
|
|
12
|
+
/** end index of the selection range (exclusive); -1 when no selection. */
|
|
13
|
+
selectionEnd: number;
|
|
14
|
+
/** placeholder text shown when unfocused and empty. */
|
|
15
|
+
placeholder: string;
|
|
16
|
+
/** text color override. */
|
|
17
|
+
textColor: number;
|
|
18
|
+
/** placeholder text color override. */
|
|
19
|
+
placeholderColor: number;
|
|
20
|
+
/** background fill color override. */
|
|
21
|
+
bgColor: number;
|
|
22
|
+
/** cursor line color override. */
|
|
23
|
+
cursorColor: number;
|
|
24
|
+
/** selection highlight color. */
|
|
25
|
+
selectionColor: number;
|
|
26
|
+
/** corner radius of the background rectangle. */
|
|
27
|
+
borderRadius: number;
|
|
28
|
+
/** called on each text change from user input. */
|
|
29
|
+
onChange: ((text: string) => void) | null;
|
|
30
|
+
private cursorVisible;
|
|
31
|
+
/** marks the input focusable so it can receive keyboard focus. */
|
|
32
|
+
constructor();
|
|
33
|
+
/** draws the background, selection highlight, text or placeholder, and the cursor when focused. */
|
|
34
|
+
protected drawSelf(renderer: Renderer, theme: Theme): void;
|
|
35
|
+
/** shows the cursor and repaints when the input gains focus. */
|
|
36
|
+
onFocus(): void;
|
|
37
|
+
/** clears the selection and repaints when the input loses focus. */
|
|
38
|
+
onBlur(): void;
|
|
39
|
+
/** claims a primary-button press and shows the cursor. */
|
|
40
|
+
onPointerDown(_pointerId: number, _x: number, _y: number, button: number): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* handles editing keys (select-all, backspace, delete, cursor movement, home/end) and inserts printable
|
|
43
|
+
* characters, calling onChange on any edit. returns true when the key was consumed.
|
|
44
|
+
*/
|
|
45
|
+
onKeyDown(key: string, _code: string, ctrl: boolean, _shift: boolean, _alt: boolean): boolean;
|
|
46
|
+
/** true when a non-empty selection range is set. */
|
|
47
|
+
private hasSelection;
|
|
48
|
+
/** removes the selected text, moves the cursor to the selection start, and fires onChange. */
|
|
49
|
+
private deleteSelection;
|
|
50
|
+
/** resets the selection range to empty. */
|
|
51
|
+
private clearSelection;
|
|
52
|
+
/** forces the cursor visible so it appears immediately after input. */
|
|
53
|
+
private resetBlink;
|
|
54
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Widget as t,THEME_DEFAULT as s}from"../core/widget.mjs";import{DEFAULTS as e}from"../defaults.mjs";class i extends t{text="";cursorPos=0;selectionStart=-1;selectionEnd=-1;placeholder="";textColor=s;placeholderColor=s;bgColor=s;cursorColor=s;selectionColor=e.textInputSelectionColor;borderRadius=2;onChange=null;cursorVisible=!0;constructor(){super(),this.focusable=!0}drawSelf(t,i){const o=this.width,r=this.height,h=i.fontAtlas;if(!h)return;const l=this.bgColor===s?i.bgInput:this.bgColor;this.borderRadius>0?t.fillRoundedRect(0,0,o,r,this.borderRadius,l):t.fillRect(0,0,o,r,l);const n=(r-h.lineHeight)/2|0,c=this.innerX||e.textInputPadding;if(this.text){if(this.focused&&this.selectionStart>=0&&this.selectionEnd>this.selectionStart){const s=c+this.selectionStart*h.charWidth,e=(this.selectionEnd-this.selectionStart)*h.charWidth;t.fillRect(s,n,e,h.lineHeight,this.selectionColor)}const e=this.textColor===s?i.textPrimary:this.textColor;t.drawText(h,this.text,c,n,e)}else if(this.placeholder&&!this.focused){const e=this.placeholderColor===s?i.textMuted:this.placeholderColor;t.drawText(h,this.placeholder,c,n,e)}if(this.focused&&this.cursorVisible){const e=c+this.cursorPos*h.charWidth,o=this.cursorColor===s?i.textPrimary:this.cursorColor;t.fillRect(e,n,1,h.lineHeight,o)}}onFocus(){this.cursorVisible=!0,this.markDirty()}onBlur(){this.selectionStart=-1,this.selectionEnd=-1,this.markDirty()}onPointerDown(t,s,e,i){return 0===i&&(this.resetBlink(),this.markDirty(),!0)}onKeyDown(t,s,e,i,o){return!(!this.enabled||(e&&"a"===t?(this.selectionStart=0,this.selectionEnd=this.text.length,this.markDirty(),0):"Backspace"===t?(this.hasSelection()?this.deleteSelection():this.cursorPos>0&&(this.text=this.text.slice(0,this.cursorPos-1)+this.text.slice(this.cursorPos),this.cursorPos--,this.onChange&&this.onChange(this.text)),this.resetBlink(),this.markDirty(),0):"Delete"===t?(this.hasSelection()?this.deleteSelection():this.cursorPos<this.text.length&&(this.text=this.text.slice(0,this.cursorPos)+this.text.slice(this.cursorPos+1),this.onChange&&this.onChange(this.text)),this.resetBlink(),this.markDirty(),0):"ArrowLeft"===t?(this.cursorPos>0&&this.cursorPos--,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"ArrowRight"===t?(this.cursorPos<this.text.length&&this.cursorPos++,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"Home"===t?(this.cursorPos=0,this.clearSelection(),this.resetBlink(),this.markDirty(),0):"End"===t?(this.cursorPos=this.text.length,this.clearSelection(),this.resetBlink(),this.markDirty(),0):1!==t.length||e||(this.hasSelection()&&this.deleteSelection(),this.text=this.text.slice(0,this.cursorPos)+t+this.text.slice(this.cursorPos),this.cursorPos++,this.onChange&&this.onChange(this.text),this.resetBlink(),this.markDirty(),0)))}hasSelection(){return this.selectionStart>=0&&this.selectionEnd>this.selectionStart}deleteSelection(){this.hasSelection()&&(this.text=this.text.slice(0,this.selectionStart)+this.text.slice(this.selectionEnd),this.cursorPos=this.selectionStart,this.clearSelection(),this.onChange&&this.onChange(this.text))}clearSelection(){this.selectionStart=-1,this.selectionEnd=-1}resetBlink(){this.cursorVisible=!0}}export{i as TextInput};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Button } from './button';
|
|
2
|
+
import { Renderer } from '../core/renderer';
|
|
3
|
+
import { Theme } from '../core/theme';
|
|
4
|
+
/** button that toggles between active and inactive states on each click. */
|
|
5
|
+
export declare class ToggleButton extends Button {
|
|
6
|
+
/** whether the button is currently in the active (toggled on) state. */
|
|
7
|
+
active: boolean;
|
|
8
|
+
/** background color override for the active state. */
|
|
9
|
+
activeStateBg: number;
|
|
10
|
+
/** border color drawn around the button when active. */
|
|
11
|
+
activeBorderColor: number;
|
|
12
|
+
/** called when the toggle state changes; receives the new active state. */
|
|
13
|
+
onToggle: ((active: boolean) => void) | null;
|
|
14
|
+
/** wires the click handler to flip the active state and fire onToggle. */
|
|
15
|
+
constructor();
|
|
16
|
+
/** in the active state, draws the base button with the active background plus an outline; else draws normally. */
|
|
17
|
+
protected drawSelf(renderer: Renderer, theme: Theme): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("../defaults.cjs"),e=[{x1:28,y1:32,x2:52,y2:32,x3:76,y3:32,x4:100,y4:32,opacity:1},{x1:28,y1:64,x2:52,y2:64,x3:76,y3:64,x4:100,y4:64,opacity:1},{x1:28,y1:96,x2:52,y2:96,x3:76,y3:96,x4:100,y4:96,opacity:1}],i=[{x1:34,y1:34,x2:54,y2:54,x3:74,y3:74,x4:94,y4:94,opacity:1},{x1:64,y1:64,x2:64,y2:64,x3:64,y3:64,x4:64,y4:64,opacity:0},{x1:94,y1:34,x2:74,y2:54,x3:54,y3:74,x4:34,y4:94,opacity:1}];function r(t,e,i){return t+(e-t)*i}exports.ToggleIcon=class{element;onClick=null;ctx;size;state="hamburger";from=[{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0}];current=[{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0}];target=e;animStart=0;animating=!1;hovered=!1;animFrame=0;dpr;_boundTick;constructor(t,i,r,s){this.size=t,this.dpr=window.devicePixelRatio||1,this._boundTick=()=>{this.animFrame=0,this.tick()};for(let t=0;t<3;t++)this.copyLine(e[t],this.from[t]),this.copyLine(e[t],this.current[t]);const y=r+(s-t)/2,n=r+8,o=document.createElement("canvas");o.width=Math.round(t*this.dpr),o.height=Math.round(t*this.dpr),o.style.position="fixed",o.style.top=`${y}px`,o.style[i]=`${n}px`,o.style.width=`${t}px`,o.style.height=`${t}px`,o.style.cursor="pointer",o.style.zIndex="1000000",o.addEventListener("click",()=>{this.onClick&&this.onClick()}),o.addEventListener("mouseenter",()=>{this.hovered=!0,this.draw()}),o.addEventListener("mouseleave",()=>{this.hovered=!1,this.draw()}),this.ctx=o.getContext("2d"),this.element=o,this.draw()}copyLine(t,e){e.x1=t.x1,e.y1=t.y1,e.x2=t.x2,e.y2=t.y2,e.x3=t.x3,e.y3=t.y3,e.x4=t.x4,e.y4=t.y4,e.opacity=t.opacity}setState(t){if(t!==this.state||this.animating){for(let t=0;t<3;t++)this.copyLine(this.current[t],this.from[t]);this.state=t,this.target="x"===t?i:e,this.animStart=performance.now(),this.animating=!0,this.scheduleFrame()}}scheduleFrame(){this.animFrame||(this.animFrame=requestAnimationFrame(this._boundTick))}tick(){if(!this.animating)return;const t=performance.now()-this.animStart,e=Math.min(1,t/320),i=function(t){return t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2}(e);for(let t=0;t<3;t++){const e=this.from[t],s=this.target[t];this.current[t].x1=r(e.x1,s.x1,i),this.current[t].y1=r(e.y1,s.y1,i),this.current[t].x2=r(e.x2,s.x2,i),this.current[t].y2=r(e.y2,s.y2,i),this.current[t].x3=r(e.x3,s.x3,i),this.current[t].y3=r(e.y3,s.y3,i),this.current[t].x4=r(e.x4,s.x4,i),this.current[t].y4=r(e.y4,s.y4,i),this.current[t].opacity=r(e.opacity,s.opacity,i)}this.draw(),e>=1?this.animating=!1:this.scheduleFrame()}draw(){const e=this.ctx,i=this.size/128*this.dpr,r=Math.max(2,10/128*this.size*this.dpr);e.clearRect(0,0,this.element.width,this.element.height),e.strokeStyle=this.hovered?t.DEFAULTS.toggleIconHoveredStroke:t.DEFAULTS.toggleIconNormalStroke,e.lineWidth=r,e.lineCap="round",e.lineJoin="round";for(let t=0;t<3;t++){const r=this.current[t];r.opacity<.01||(e.globalAlpha=r.opacity,e.beginPath(),e.moveTo(r.x1*i,r.y1*i),e.lineTo(r.x2*i,r.y2*i),e.lineTo(r.x3*i,r.y3*i),e.lineTo(r.x4*i,r.y4*i),e.stroke())}e.globalAlpha=1}destroy(){this.animFrame&&(cancelAnimationFrame(this.animFrame),this.animFrame=0),this.element.remove()}};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
type ToggleState = "hamburger" | "x";
|
|
2
|
+
/** animated hamburger/close icon rendered to a canvas element. */
|
|
3
|
+
export declare class ToggleIcon {
|
|
4
|
+
/** the canvas DOM element containing the icon. */
|
|
5
|
+
readonly element: HTMLCanvasElement;
|
|
6
|
+
/** callback invoked when the icon is clicked. */
|
|
7
|
+
onClick: (() => void) | null;
|
|
8
|
+
private ctx;
|
|
9
|
+
private size;
|
|
10
|
+
private state;
|
|
11
|
+
private from;
|
|
12
|
+
private current;
|
|
13
|
+
private target;
|
|
14
|
+
private animStart;
|
|
15
|
+
private animating;
|
|
16
|
+
private hovered;
|
|
17
|
+
private animFrame;
|
|
18
|
+
private dpr;
|
|
19
|
+
private readonly _boundTick;
|
|
20
|
+
/**
|
|
21
|
+
* builds and positions the fixed canvas element, seeds the line state to the hamburger shape, and wires
|
|
22
|
+
* the click and hover listeners.
|
|
23
|
+
*/
|
|
24
|
+
constructor(size: number, position: "left" | "right", margin: number, tabBarHeight: number);
|
|
25
|
+
/** copies all four control points and the opacity from one line state into another. */
|
|
26
|
+
private copyLine;
|
|
27
|
+
/** transitions to the given state with an animated morph. */
|
|
28
|
+
setState(newState: ToggleState): void;
|
|
29
|
+
/** requests a single animation frame, coalescing repeated calls made within the same frame. */
|
|
30
|
+
private scheduleFrame;
|
|
31
|
+
/** advances the morph one frame, interpolating each line from its start toward the target, then redraws. */
|
|
32
|
+
private tick;
|
|
33
|
+
/** clears the canvas and strokes each visible line, scaling from viewbox space to device pixels. */
|
|
34
|
+
private draw;
|
|
35
|
+
/** cancels any running animation and removes the canvas element from the DOM. */
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DEFAULTS as t}from"../defaults.mjs";const i=[{x1:28,y1:32,x2:52,y2:32,x3:76,y3:32,x4:100,y4:32,opacity:1},{x1:28,y1:64,x2:52,y2:64,x3:76,y3:64,x4:100,y4:64,opacity:1},{x1:28,y1:96,x2:52,y2:96,x3:76,y3:96,x4:100,y4:96,opacity:1}],e=[{x1:34,y1:34,x2:54,y2:54,x3:74,y3:74,x4:94,y4:94,opacity:1},{x1:64,y1:64,x2:64,y2:64,x3:64,y3:64,x4:64,y4:64,opacity:0},{x1:94,y1:34,x2:74,y2:54,x3:54,y3:74,x4:34,y4:94,opacity:1}];function r(t,i,e){return t+(i-t)*e}class y{element;onClick=null;ctx;size;state="hamburger";from=[{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0}];current=[{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0},{x1:0,y1:0,x2:0,y2:0,x3:0,y3:0,x4:0,y4:0,opacity:0}];target=i;animStart=0;animating=!1;hovered=!1;animFrame=0;dpr;_boundTick;constructor(t,e,r,y){this.size=t,this.dpr=window.devicePixelRatio||1,this._boundTick=()=>{this.animFrame=0,this.tick()};for(let t=0;t<3;t++)this.copyLine(i[t],this.from[t]),this.copyLine(i[t],this.current[t]);const s=r+(y-t)/2,n=r+8,a=document.createElement("canvas");a.width=Math.round(t*this.dpr),a.height=Math.round(t*this.dpr),a.style.position="fixed",a.style.top=`${s}px`,a.style[e]=`${n}px`,a.style.width=`${t}px`,a.style.height=`${t}px`,a.style.cursor="pointer",a.style.zIndex="1000000",a.addEventListener("click",()=>{this.onClick&&this.onClick()}),a.addEventListener("mouseenter",()=>{this.hovered=!0,this.draw()}),a.addEventListener("mouseleave",()=>{this.hovered=!1,this.draw()}),this.ctx=a.getContext("2d"),this.element=a,this.draw()}copyLine(t,i){i.x1=t.x1,i.y1=t.y1,i.x2=t.x2,i.y2=t.y2,i.x3=t.x3,i.y3=t.y3,i.x4=t.x4,i.y4=t.y4,i.opacity=t.opacity}setState(t){if(t!==this.state||this.animating){for(let t=0;t<3;t++)this.copyLine(this.current[t],this.from[t]);this.state=t,this.target="x"===t?e:i,this.animStart=performance.now(),this.animating=!0,this.scheduleFrame()}}scheduleFrame(){this.animFrame||(this.animFrame=requestAnimationFrame(this._boundTick))}tick(){if(!this.animating)return;const t=performance.now()-this.animStart,i=Math.min(1,t/320),e=function(t){return t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2}(i);for(let t=0;t<3;t++){const i=this.from[t],y=this.target[t];this.current[t].x1=r(i.x1,y.x1,e),this.current[t].y1=r(i.y1,y.y1,e),this.current[t].x2=r(i.x2,y.x2,e),this.current[t].y2=r(i.y2,y.y2,e),this.current[t].x3=r(i.x3,y.x3,e),this.current[t].y3=r(i.y3,y.y3,e),this.current[t].x4=r(i.x4,y.x4,e),this.current[t].y4=r(i.y4,y.y4,e),this.current[t].opacity=r(i.opacity,y.opacity,e)}this.draw(),i>=1?this.animating=!1:this.scheduleFrame()}draw(){const i=this.ctx,e=this.size/128*this.dpr,r=Math.max(2,10/128*this.size*this.dpr);i.clearRect(0,0,this.element.width,this.element.height),i.strokeStyle=this.hovered?t.toggleIconHoveredStroke:t.toggleIconNormalStroke,i.lineWidth=r,i.lineCap="round",i.lineJoin="round";for(let t=0;t<3;t++){const r=this.current[t];r.opacity<.01||(i.globalAlpha=r.opacity,i.beginPath(),i.moveTo(r.x1*e,r.y1*e),i.lineTo(r.x2*e,r.y2*e),i.lineTo(r.x3*e,r.y3*e),i.lineTo(r.x4*e,r.y4*e),i.stroke())}i.globalAlpha=1}destroy(){this.animFrame&&(cancelAnimationFrame(this.animFrame),this.animFrame=0),this.element.remove()}}export{y as ToggleIcon};
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mgz-dev/inspect",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "A canvas based GUI panel for games and dev tools.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"gui",
|
|
8
|
+
"panel",
|
|
9
|
+
"canvas",
|
|
10
|
+
"inspector",
|
|
11
|
+
"debug",
|
|
12
|
+
"devtools",
|
|
13
|
+
"controls",
|
|
14
|
+
"sliders",
|
|
15
|
+
"tweak",
|
|
16
|
+
"parameters",
|
|
17
|
+
"hud",
|
|
18
|
+
"overlay",
|
|
19
|
+
"gamedev",
|
|
20
|
+
"webgl",
|
|
21
|
+
"webgpu",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"author": {
|
|
26
|
+
"name": "Marco Gomez",
|
|
27
|
+
"email": "marcogomez@mgz.me",
|
|
28
|
+
"url": "https://mgz.me"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/marcogomez/inspect#readme",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/marcogomez/inspect.git"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/marcogomez/inspect/issues"
|
|
37
|
+
},
|
|
38
|
+
"sideEffects": false,
|
|
39
|
+
"main": "./dist/index.cjs",
|
|
40
|
+
"module": "./dist/index.mjs",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"types": "./dist/index.d.ts",
|
|
45
|
+
"import": "./dist/index.mjs",
|
|
46
|
+
"require": "./dist/index.cjs"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"./dist"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "vite build",
|
|
54
|
+
"dev": "vite build --watch --mode development",
|
|
55
|
+
"type-check": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
56
|
+
"lint": "eslint src test --max-warnings 0",
|
|
57
|
+
"lint-fix": "eslint src test --fix",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"test-coverage": "vitest run --coverage",
|
|
60
|
+
"demo:install": "pnpm --dir demo install",
|
|
61
|
+
"demo": "pnpm install && pnpm build && pnpm --dir demo dev",
|
|
62
|
+
"demo:build": "pnpm install && pnpm build && pnpm --dir demo build",
|
|
63
|
+
"changeset": "changeset",
|
|
64
|
+
"version": "changeset version",
|
|
65
|
+
"release": "changeset publish"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@changesets/cli": "^2.29.4",
|
|
69
|
+
"@happy-dom/node-canvas-adapter": "^20.10.2",
|
|
70
|
+
"happy-dom": "^20.10.2",
|
|
71
|
+
"@mgz-dev/codestyle": "^1.0.0",
|
|
72
|
+
"@mgz-dev/viteforge": "^1.0.1",
|
|
73
|
+
"@types/node": "^25.0.3",
|
|
74
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
75
|
+
"canvas": "^3.2.3",
|
|
76
|
+
"eslint": "^9.39.4",
|
|
77
|
+
"prettier": "^3.8.3",
|
|
78
|
+
"typescript": "^5.9.3",
|
|
79
|
+
"vite": "^7.3.0",
|
|
80
|
+
"vitest": "^3.2.4"
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"access": "public"
|
|
84
|
+
},
|
|
85
|
+
"packageManager": "pnpm@10.28.2",
|
|
86
|
+
"pnpm": {
|
|
87
|
+
"onlyBuiltDependencies": [
|
|
88
|
+
"canvas"
|
|
89
|
+
],
|
|
90
|
+
"ignoredBuiltDependencies": [
|
|
91
|
+
"@parcel/watcher",
|
|
92
|
+
"esbuild"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|