@three-flatland/devtools 0.1.0-alpha.3 → 1.0.0-alpha.6

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 (172) hide show
  1. package/README.md +1 -1
  2. package/dist/buffers-modal.d.ts +16 -52
  3. package/dist/buffers-modal.d.ts.map +1 -0
  4. package/dist/buffers-modal.js +459 -464
  5. package/dist/buffers-modal.js.map +1 -1
  6. package/dist/buffers-view.d.ts +22 -34
  7. package/dist/buffers-view.d.ts.map +1 -0
  8. package/dist/buffers-view.js +252 -240
  9. package/dist/buffers-view.js.map +1 -1
  10. package/dist/create-pane.d.ts +38 -37
  11. package/dist/create-pane.d.ts.map +1 -0
  12. package/dist/create-pane.js +197 -166
  13. package/dist/create-pane.js.map +1 -1
  14. package/dist/dashboard/app.tsx +2 -0
  15. package/dist/dashboard/export.ts +1 -3
  16. package/dist/dashboard/frame-cursor.ts +81 -0
  17. package/dist/dashboard/hooks.ts +10 -2
  18. package/dist/dashboard/index.html +61 -0
  19. package/dist/dashboard/panels/batches.tsx +5 -18
  20. package/dist/dashboard/panels/buffers.tsx +52 -26
  21. package/dist/dashboard/panels/env.tsx +5 -6
  22. package/dist/dashboard/panels/protocol-log.tsx +146 -58
  23. package/dist/dashboard/panels/registry.tsx +55 -69
  24. package/dist/dashboard/panels/scrubber.tsx +100 -0
  25. package/dist/dashboard/panels/stats.tsx +60 -32
  26. package/dist/dashboard/protocol-store.ts +25 -8
  27. package/dist/dashboard/vendor/hooks.module.d.ts +146 -0
  28. package/dist/dashboard/vendor/jsx-runtime.d.ts +55 -0
  29. package/dist/dashboard/vendor/jsx.d.ts +3123 -0
  30. package/dist/dashboard/vendor/preact.module.d.ts +397 -0
  31. package/dist/devtools-client.d.ts +312 -300
  32. package/dist/devtools-client.d.ts.map +1 -0
  33. package/dist/devtools-client.js +866 -838
  34. package/dist/devtools-client.js.map +1 -1
  35. package/dist/index.d.ts +6 -8
  36. package/dist/index.js +5 -12
  37. package/dist/perf-trace.d.ts +6 -4
  38. package/dist/perf-trace.d.ts.map +1 -0
  39. package/dist/perf-trace.js +80 -66
  40. package/dist/perf-trace.js.map +1 -1
  41. package/dist/plugins.d.ts +6 -6
  42. package/dist/plugins.d.ts.map +1 -0
  43. package/dist/plugins.js +5 -5
  44. package/dist/plugins.js.map +1 -1
  45. package/dist/provider-switcher.d.ts +8 -15
  46. package/dist/provider-switcher.d.ts.map +1 -0
  47. package/dist/provider-switcher.js +68 -68
  48. package/dist/provider-switcher.js.map +1 -1
  49. package/dist/react/devtools-provider.d.ts +11 -10
  50. package/dist/react/devtools-provider.d.ts.map +1 -0
  51. package/dist/react/devtools-provider.js +60 -32
  52. package/dist/react/devtools-provider.js.map +1 -1
  53. package/dist/react/use-fps-graph.d.ts +7 -7
  54. package/dist/react/use-fps-graph.d.ts.map +1 -0
  55. package/dist/react/use-fps-graph.js +27 -21
  56. package/dist/react/use-fps-graph.js.map +1 -1
  57. package/dist/react/use-pane-button.d.ts +4 -4
  58. package/dist/react/use-pane-button.d.ts.map +1 -0
  59. package/dist/react/use-pane-button.js +35 -30
  60. package/dist/react/use-pane-button.js.map +1 -1
  61. package/dist/react/use-pane-folder.d.ts +5 -4
  62. package/dist/react/use-pane-folder.d.ts.map +1 -0
  63. package/dist/react/use-pane-folder.js +33 -20
  64. package/dist/react/use-pane-folder.js.map +1 -1
  65. package/dist/react/use-pane-input.d.ts +31 -30
  66. package/dist/react/use-pane-input.d.ts.map +1 -0
  67. package/dist/react/use-pane-input.js +46 -42
  68. package/dist/react/use-pane-input.js.map +1 -1
  69. package/dist/react/use-pane-radio-grid.d.ts +20 -20
  70. package/dist/react/use-pane-radio-grid.d.ts.map +1 -0
  71. package/dist/react/use-pane-radio-grid.js +72 -50
  72. package/dist/react/use-pane-radio-grid.js.map +1 -1
  73. package/dist/react/use-pane.d.ts +4 -4
  74. package/dist/react/use-pane.d.ts.map +1 -0
  75. package/dist/react/use-pane.js +52 -17
  76. package/dist/react/use-pane.js.map +1 -1
  77. package/dist/react.d.ts +10 -12
  78. package/dist/react.js +2 -12
  79. package/dist/registry-view.d.ts +8 -21
  80. package/dist/registry-view.d.ts.map +1 -0
  81. package/dist/registry-view.js +357 -338
  82. package/dist/registry-view.js.map +1 -1
  83. package/dist/relay.d.ts +16 -0
  84. package/dist/relay.d.ts.map +1 -0
  85. package/dist/relay.js +189 -0
  86. package/dist/relay.js.map +1 -0
  87. package/dist/remote.d.ts +10 -0
  88. package/dist/remote.d.ts.map +1 -0
  89. package/dist/remote.js +28 -0
  90. package/dist/remote.js.map +1 -0
  91. package/dist/stats-graph.d.ts +23 -31
  92. package/dist/stats-graph.d.ts.map +1 -0
  93. package/dist/stats-graph.js +323 -264
  94. package/dist/stats-graph.js.map +1 -1
  95. package/dist/stats-row.d.ts +8 -21
  96. package/dist/stats-row.d.ts.map +1 -0
  97. package/dist/stats-row.js +99 -101
  98. package/dist/stats-row.js.map +1 -1
  99. package/dist/theme.d.ts +3 -1
  100. package/dist/theme.d.ts.map +1 -0
  101. package/dist/theme.js +43 -54
  102. package/dist/theme.js.map +1 -1
  103. package/dist/vite-plugin.d.ts +7 -6
  104. package/dist/vite-plugin.d.ts.map +1 -0
  105. package/dist/vite-plugin.js +87 -78
  106. package/dist/vite-plugin.js.map +1 -1
  107. package/package.json +33 -29
  108. package/dist/buffers-modal.cjs +0 -491
  109. package/dist/buffers-modal.cjs.map +0 -1
  110. package/dist/buffers-modal.d.cts +0 -62
  111. package/dist/buffers-view.cjs +0 -269
  112. package/dist/buffers-view.cjs.map +0 -1
  113. package/dist/buffers-view.d.cts +0 -39
  114. package/dist/create-pane.cjs +0 -203
  115. package/dist/create-pane.cjs.map +0 -1
  116. package/dist/create-pane.d.cts +0 -66
  117. package/dist/devtools-client.cjs +0 -870
  118. package/dist/devtools-client.cjs.map +0 -1
  119. package/dist/devtools-client.d.cts +0 -362
  120. package/dist/index.cjs +0 -42
  121. package/dist/index.cjs.map +0 -1
  122. package/dist/index.d.cts +0 -8
  123. package/dist/index.js.map +0 -1
  124. package/dist/perf-trace.cjs +0 -103
  125. package/dist/perf-trace.cjs.map +0 -1
  126. package/dist/perf-trace.d.cts +0 -27
  127. package/dist/plugins.cjs +0 -44
  128. package/dist/plugins.cjs.map +0 -1
  129. package/dist/plugins.d.cts +0 -7
  130. package/dist/provider-switcher.cjs +0 -95
  131. package/dist/provider-switcher.cjs.map +0 -1
  132. package/dist/provider-switcher.d.cts +0 -18
  133. package/dist/react/devtools-provider.cjs +0 -59
  134. package/dist/react/devtools-provider.cjs.map +0 -1
  135. package/dist/react/devtools-provider.d.cts +0 -39
  136. package/dist/react/use-fps-graph.cjs +0 -49
  137. package/dist/react/use-fps-graph.cjs.map +0 -1
  138. package/dist/react/use-fps-graph.d.cts +0 -15
  139. package/dist/react/use-pane-button.cjs +0 -58
  140. package/dist/react/use-pane-button.cjs.map +0 -1
  141. package/dist/react/use-pane-button.d.cts +0 -10
  142. package/dist/react/use-pane-folder.cjs +0 -48
  143. package/dist/react/use-pane-folder.cjs.map +0 -1
  144. package/dist/react/use-pane-folder.d.cts +0 -15
  145. package/dist/react/use-pane-input.cjs +0 -70
  146. package/dist/react/use-pane-input.cjs.map +0 -1
  147. package/dist/react/use-pane-input.d.cts +0 -44
  148. package/dist/react/use-pane-radio-grid.cjs +0 -78
  149. package/dist/react/use-pane-radio-grid.cjs.map +0 -1
  150. package/dist/react/use-pane-radio-grid.d.cts +0 -35
  151. package/dist/react/use-pane.cjs +0 -45
  152. package/dist/react/use-pane.cjs.map +0 -1
  153. package/dist/react/use-pane.d.cts +0 -40
  154. package/dist/react.cjs +0 -50
  155. package/dist/react.cjs.map +0 -1
  156. package/dist/react.d.cts +0 -12
  157. package/dist/react.js.map +0 -1
  158. package/dist/registry-view.cjs +0 -371
  159. package/dist/registry-view.cjs.map +0 -1
  160. package/dist/registry-view.d.cts +0 -24
  161. package/dist/stats-graph.cjs +0 -297
  162. package/dist/stats-graph.cjs.map +0 -1
  163. package/dist/stats-graph.d.cts +0 -40
  164. package/dist/stats-row.cjs +0 -153
  165. package/dist/stats-row.cjs.map +0 -1
  166. package/dist/stats-row.d.cts +0 -24
  167. package/dist/theme.cjs +0 -260
  168. package/dist/theme.cjs.map +0 -1
  169. package/dist/theme.d.cts +0 -10
  170. package/dist/vite-plugin.cjs +0 -113
  171. package/dist/vite-plugin.cjs.map +0 -1
  172. package/dist/vite-plugin.d.cts +0 -9
@@ -1,15 +0,0 @@
1
- import { FolderParams, FolderApi } from 'tweakpane';
2
- import { PaneParent } from './use-pane-input.cjs';
3
-
4
- /**
5
- * Create a Tweakpane folder underneath `parent`. Disposes on unmount and
6
- * recreates when `parent` (or `title`) changes — e.g., when `usePane`
7
- * tears down and rebuilds its bundle on a StrictMode remount.
8
- *
9
- * Returns `null` on the first render before the layout effect commits,
10
- * then the FolderApi on the next render. The two renders happen
11
- * synchronously before paint, so consumers don't see a flicker.
12
- */
13
- declare function usePaneFolder(parent: PaneParent | null, title: string, options?: Partial<FolderParams>): FolderApi | null;
14
-
15
- export { usePaneFolder };
@@ -1,70 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var use_pane_input_exports = {};
20
- __export(use_pane_input_exports, {
21
- usePaneInput: () => usePaneInput
22
- });
23
- module.exports = __toCommonJS(use_pane_input_exports);
24
- var import_react = require("react");
25
- function usePaneInput(parent, key, initialValue, options = {}) {
26
- const [value, setValueState] = (0, import_react.useState)(initialValue);
27
- const paramsRef = (0, import_react.useRef)({ [key]: initialValue });
28
- const bindingRef = (0, import_react.useRef)(null);
29
- const getOptions = (0, import_react.useEffectEvent)(() => options);
30
- const getValue = (0, import_react.useEffectEvent)(() => value);
31
- (0, import_react.useLayoutEffect)(() => {
32
- if (!parent) {
33
- bindingRef.current = null;
34
- return;
35
- }
36
- paramsRef.current[key] = getValue();
37
- const { label, ...bindingOpts } = getOptions();
38
- const binding = parent.addBinding(paramsRef.current, key, {
39
- label: label ?? key,
40
- ...bindingOpts
41
- });
42
- binding.on("change", (ev) => {
43
- setValueState(ev.value);
44
- });
45
- bindingRef.current = binding;
46
- return () => {
47
- try {
48
- binding.dispose();
49
- } catch {
50
- }
51
- if (bindingRef.current === binding) {
52
- bindingRef.current = null;
53
- }
54
- };
55
- }, [parent, key]);
56
- const setValue = (0, import_react.useCallback)(
57
- (v) => {
58
- paramsRef.current[key] = v;
59
- setValueState(v);
60
- bindingRef.current?.refresh();
61
- },
62
- [key]
63
- );
64
- return [value, setValue];
65
- }
66
- // Annotate the CommonJS export names for ESM import in node:
67
- 0 && (module.exports = {
68
- usePaneInput
69
- });
70
- //# sourceMappingURL=use-pane-input.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/react/use-pane-input.ts"],"sourcesContent":["import { useCallback, useEffectEvent, useLayoutEffect, useRef, useState } from 'react'\nimport type { FolderApi, Pane } from 'tweakpane'\n\nexport type PaneParent = Pane | FolderApi\n\nexport interface PaneInputOptions {\n /** Minimum value (for number inputs, creates a slider) */\n min?: number\n /** Maximum value (for number inputs) */\n max?: number\n /** Step increment */\n step?: number\n /** Named options for list/dropdown binding */\n options?: Record<string, unknown>\n /** Label override (defaults to key) */\n label?: string\n /** Display as color picker */\n color?: { type: 'float' }\n /** Inverted range */\n inverted?: boolean\n /**\n * Render as a read-only monitor (no interactive editor). Value still\n * updates when `setValue` is called; tweakpane repaints on refresh.\n */\n readonly?: boolean\n /**\n * Custom display formatter (e.g. `(v) => v.toFixed(2)`). Forwarded to\n * tweakpane's native `format` option.\n */\n format?: (value: number) => string\n}\n\n/**\n * Bind a Tweakpane input to React state.\n * Returns [value, setValue] — setValue updates both React state and the\n * Tweakpane binding.\n *\n * The binding is created in `useLayoutEffect` and rebuilt whenever\n * `parent` or `key` changes — so when `usePane` tears down and rebuilds\n * its bundle (StrictMode, true remount), this hook automatically\n * re-binds to the new pane. Cleanup disposes the binding immediately.\n */\nexport function usePaneInput<T>(\n parent: PaneParent | null,\n key: string,\n initialValue: T,\n options: PaneInputOptions = {},\n): [T, (v: T) => void] {\n const [value, setValueState] = useState<T>(initialValue)\n const paramsRef = useRef<Record<string, unknown>>({ [key]: initialValue })\n const bindingRef = useRef<{ refresh(): void; dispose(): void } | null>(null)\n\n // Capture the latest options + value non-reactively, read only when the\n // binding is (re)created. useEffectEvent avoids touching refs during\n // render while keeping options/value out of the effect's dep list (so\n // they don't retrigger setup). tweakpane writes the bound object back on\n // its own change events; setValue keeps it synced for external updates.\n const getOptions = useEffectEvent(() => options)\n const getValue = useEffectEvent(() => value)\n\n useLayoutEffect(() => {\n if (!parent) {\n bindingRef.current = null\n return\n }\n\n // Seed the bound object with the latest value so a recreated binding\n // shows current state, not the initial.\n paramsRef.current[key] = getValue()\n const { label, ...bindingOpts } = getOptions()\n const binding = parent.addBinding(paramsRef.current, key, {\n label: label ?? key,\n ...bindingOpts,\n } as Record<string, unknown>)\n\n binding.on('change', (ev: { value: unknown }) => {\n setValueState(ev.value as T)\n })\n bindingRef.current = binding as unknown as { refresh(): void; dispose(): void }\n\n return () => {\n try {\n binding.dispose()\n } catch {\n // Parent may have been disposed first (cascade). Ignore.\n }\n if (\n bindingRef.current ===\n (binding as unknown as { refresh(): void; dispose(): void })\n ) {\n bindingRef.current = null\n }\n }\n // options/value are read via useEffectEvent, so they stay out of the\n // dep list and don't retrigger setup — only parent/key rebind.\n }, [parent, key])\n\n const setValue = useCallback(\n (v: T) => {\n paramsRef.current[key] = v\n setValueState(v)\n bindingRef.current?.refresh()\n },\n [key],\n )\n\n return [value, setValue]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+E;AA0CxE,SAAS,aACd,QACA,KACA,cACA,UAA4B,CAAC,GACR;AACrB,QAAM,CAAC,OAAO,aAAa,QAAI,uBAAY,YAAY;AACvD,QAAM,gBAAY,qBAAgC,EAAE,CAAC,GAAG,GAAG,aAAa,CAAC;AACzE,QAAM,iBAAa,qBAAoD,IAAI;AAO3E,QAAM,iBAAa,6BAAe,MAAM,OAAO;AAC/C,QAAM,eAAW,6BAAe,MAAM,KAAK;AAE3C,oCAAgB,MAAM;AACpB,QAAI,CAAC,QAAQ;AACX,iBAAW,UAAU;AACrB;AAAA,IACF;AAIA,cAAU,QAAQ,GAAG,IAAI,SAAS;AAClC,UAAM,EAAE,OAAO,GAAG,YAAY,IAAI,WAAW;AAC7C,UAAM,UAAU,OAAO,WAAW,UAAU,SAAS,KAAK;AAAA,MACxD,OAAO,SAAS;AAAA,MAChB,GAAG;AAAA,IACL,CAA4B;AAE5B,YAAQ,GAAG,UAAU,CAAC,OAA2B;AAC/C,oBAAc,GAAG,KAAU;AAAA,IAC7B,CAAC;AACD,eAAW,UAAU;AAErB,WAAO,MAAM;AACX,UAAI;AACF,gBAAQ,QAAQ;AAAA,MAClB,QAAQ;AAAA,MAER;AACA,UACE,WAAW,YACV,SACD;AACA,mBAAW,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,EAGF,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,QAAM,eAAW;AAAA,IACf,CAAC,MAAS;AACR,gBAAU,QAAQ,GAAG,IAAI;AACzB,oBAAc,CAAC;AACf,iBAAW,SAAS,QAAQ;AAAA,IAC9B;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAEA,SAAO,CAAC,OAAO,QAAQ;AACzB;","names":[]}
@@ -1,44 +0,0 @@
1
- import { Pane, FolderApi } from 'tweakpane';
2
-
3
- type PaneParent = Pane | FolderApi;
4
- interface PaneInputOptions {
5
- /** Minimum value (for number inputs, creates a slider) */
6
- min?: number;
7
- /** Maximum value (for number inputs) */
8
- max?: number;
9
- /** Step increment */
10
- step?: number;
11
- /** Named options for list/dropdown binding */
12
- options?: Record<string, unknown>;
13
- /** Label override (defaults to key) */
14
- label?: string;
15
- /** Display as color picker */
16
- color?: {
17
- type: 'float';
18
- };
19
- /** Inverted range */
20
- inverted?: boolean;
21
- /**
22
- * Render as a read-only monitor (no interactive editor). Value still
23
- * updates when `setValue` is called; tweakpane repaints on refresh.
24
- */
25
- readonly?: boolean;
26
- /**
27
- * Custom display formatter (e.g. `(v) => v.toFixed(2)`). Forwarded to
28
- * tweakpane's native `format` option.
29
- */
30
- format?: (value: number) => string;
31
- }
32
- /**
33
- * Bind a Tweakpane input to React state.
34
- * Returns [value, setValue] — setValue updates both React state and the
35
- * Tweakpane binding.
36
- *
37
- * The binding is created in `useLayoutEffect` and rebuilt whenever
38
- * `parent` or `key` changes — so when `usePane` tears down and rebuilds
39
- * its bundle (StrictMode, true remount), this hook automatically
40
- * re-binds to the new pane. Cleanup disposes the binding immediately.
41
- */
42
- declare function usePaneInput<T>(parent: PaneParent | null, key: string, initialValue: T, options?: PaneInputOptions): [T, (v: T) => void];
43
-
44
- export { type PaneInputOptions, type PaneParent, usePaneInput };
@@ -1,78 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var use_pane_radio_grid_exports = {};
20
- __export(use_pane_radio_grid_exports, {
21
- usePaneRadioGrid: () => usePaneRadioGrid
22
- });
23
- module.exports = __toCommonJS(use_pane_radio_grid_exports);
24
- var import_react = require("react");
25
- function usePaneRadioGrid(parent, options) {
26
- const { cells, initialValue, groupName, size } = options;
27
- const [value, setValueState] = (0, import_react.useState)(initialValue);
28
- const bladeRef = (0, import_react.useRef)(null);
29
- const cellsRef = (0, import_react.useRef)(cells);
30
- cellsRef.current = cells;
31
- const mountedRef = (0, import_react.useRef)(false);
32
- const ensureBlade = (0, import_react.useCallback)(() => {
33
- if (!parent || bladeRef.current) return;
34
- const [cols, rows] = size ?? [cells.length, 1];
35
- const bag = { value: initialValue };
36
- const blade = parent.addBlade({
37
- view: "radiogrid",
38
- groupName: groupName ?? `radio-${Math.random().toString(36).slice(2, 10)}`,
39
- size: [cols, rows],
40
- cells: (x, y) => {
41
- const idx = y * cols + x;
42
- const cell = cellsRef.current[idx];
43
- return cell ? { title: cell.title, value: cell.value } : { title: "", value: void 0 };
44
- },
45
- value: bag.value
46
- });
47
- blade?.on("change", (ev) => {
48
- setValueState(ev.value);
49
- });
50
- bladeRef.current = blade;
51
- }, [parent, groupName, initialValue, cells.length, size]);
52
- if (parent && bladeRef.current === null) ensureBlade();
53
- (0, import_react.useEffect)(() => {
54
- mountedRef.current = true;
55
- if (parent && bladeRef.current === null) ensureBlade();
56
- return () => {
57
- const blade = bladeRef.current;
58
- setTimeout(() => {
59
- if (!mountedRef.current && blade) {
60
- blade.dispose();
61
- if (bladeRef.current === blade) bladeRef.current = null;
62
- }
63
- }, 0);
64
- mountedRef.current = false;
65
- };
66
- }, [parent]);
67
- const setValue = (0, import_react.useCallback)((v) => {
68
- setValueState(v);
69
- const blade = bladeRef.current;
70
- if (blade && "value" in blade) blade.value = v;
71
- }, []);
72
- return [value, setValue];
73
- }
74
- // Annotate the CommonJS export names for ESM import in node:
75
- 0 && (module.exports = {
76
- usePaneRadioGrid
77
- });
78
- //# sourceMappingURL=use-pane-radio-grid.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/react/use-pane-radio-grid.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { PaneParent } from './use-pane-input.js'\n\nexport interface PaneRadioGridCell<T> {\n /** Visible label on the button. */\n title: string\n /** Value emitted by this cell when selected. */\n value: T\n}\n\nexport interface PaneRadioGridOptions<T> {\n /** Radio-group name. Required by Tweakpane — any unique string works. */\n groupName?: string\n /** Initially-selected value. Must match one of `cells[i].value`. */\n initialValue: T\n /**\n * Grid cells in row-major order. Default layout is a single row with\n * `cells.length` columns, matching a top-of-pane toggle bar.\n */\n cells: ReadonlyArray<PaneRadioGridCell<T>>\n /** Explicit `[cols, rows]`. Defaults to `[cells.length, 1]`. */\n size?: [number, number]\n}\n\n/**\n * Render an inline button-bar selector backed by the Tweakpane Essentials\n * `radiogrid` blade. Returns `[value, setValue]` — interacting with the\n * pane buttons updates React state, and `setValue` pushes back into the\n * blade. Intended for scene/mode toggles where a dropdown feels too\n * heavyweight and a row of labeled buttons reads better.\n *\n * Disposal is deferred through `setTimeout(0)` so the blade survives\n * React strict-mode's synchronous cleanup/re-mount pair.\n */\nexport function usePaneRadioGrid<T>(\n parent: PaneParent | null,\n options: PaneRadioGridOptions<T>,\n): [T, (v: T) => void] {\n const { cells, initialValue, groupName, size } = options\n const [value, setValueState] = useState<T>(initialValue)\n\n const bladeRef = useRef<{ dispose(): void; on: (ev: string, fn: (e: { value: T }) => void) => unknown; value?: T } | null>(null)\n const cellsRef = useRef(cells)\n cellsRef.current = cells\n const mountedRef = useRef(false)\n\n const ensureBlade = useCallback(() => {\n if (!parent || bladeRef.current) return\n\n const [cols, rows] = size ?? [cells.length, 1]\n const bag = { value: initialValue }\n const blade = (parent as unknown as {\n addBlade: (opts: Record<string, unknown>) => typeof bladeRef.current\n }).addBlade({\n view: 'radiogrid',\n groupName: groupName ?? `radio-${Math.random().toString(36).slice(2, 10)}`,\n size: [cols, rows],\n cells: (x: number, y: number) => {\n const idx = y * cols + x\n const cell = cellsRef.current[idx]\n return cell ? { title: cell.title, value: cell.value } : { title: '', value: undefined }\n },\n value: bag.value,\n })\n\n blade?.on('change', (ev) => {\n setValueState(ev.value)\n })\n bladeRef.current = blade\n }, [parent, groupName, initialValue, cells.length, size])\n\n // Synchronous creation so the toggle bar appears on first paint.\n if (parent && bladeRef.current === null) ensureBlade()\n\n useEffect(() => {\n mountedRef.current = true\n if (parent && bladeRef.current === null) ensureBlade()\n\n return () => {\n const blade = bladeRef.current\n setTimeout(() => {\n if (!mountedRef.current && blade) {\n blade.dispose()\n if (bladeRef.current === blade) bladeRef.current = null\n }\n }, 0)\n mountedRef.current = false\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [parent])\n\n const setValue = useCallback((v: T) => {\n setValueState(v)\n const blade = bladeRef.current as (typeof bladeRef.current & { value?: T }) | null\n if (blade && 'value' in blade) blade.value = v\n }, [])\n\n return [value, setValue]\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyD;AAkClD,SAAS,iBACd,QACA,SACqB;AACrB,QAAM,EAAE,OAAO,cAAc,WAAW,KAAK,IAAI;AACjD,QAAM,CAAC,OAAO,aAAa,QAAI,uBAAY,YAAY;AAEvD,QAAM,eAAW,qBAA0G,IAAI;AAC/H,QAAM,eAAW,qBAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,iBAAa,qBAAO,KAAK;AAE/B,QAAM,kBAAc,0BAAY,MAAM;AACpC,QAAI,CAAC,UAAU,SAAS,QAAS;AAEjC,UAAM,CAAC,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAC7C,UAAM,MAAM,EAAE,OAAO,aAAa;AAClC,UAAM,QAAS,OAEZ,SAAS;AAAA,MACV,MAAM;AAAA,MACN,WAAW,aAAa,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,MACxE,MAAM,CAAC,MAAM,IAAI;AAAA,MACjB,OAAO,CAAC,GAAW,MAAc;AAC/B,cAAM,MAAM,IAAI,OAAO;AACvB,cAAM,OAAO,SAAS,QAAQ,GAAG;AACjC,eAAO,OAAO,EAAE,OAAO,KAAK,OAAO,OAAO,KAAK,MAAM,IAAI,EAAE,OAAO,IAAI,OAAO,OAAU;AAAA,MACzF;AAAA,MACA,OAAO,IAAI;AAAA,IACb,CAAC;AAED,WAAO,GAAG,UAAU,CAAC,OAAO;AAC1B,oBAAc,GAAG,KAAK;AAAA,IACxB,CAAC;AACD,aAAS,UAAU;AAAA,EACrB,GAAG,CAAC,QAAQ,WAAW,cAAc,MAAM,QAAQ,IAAI,CAAC;AAGxD,MAAI,UAAU,SAAS,YAAY,KAAM,aAAY;AAErD,8BAAU,MAAM;AACd,eAAW,UAAU;AACrB,QAAI,UAAU,SAAS,YAAY,KAAM,aAAY;AAErD,WAAO,MAAM;AACX,YAAM,QAAQ,SAAS;AACvB,iBAAW,MAAM;AACf,YAAI,CAAC,WAAW,WAAW,OAAO;AAChC,gBAAM,QAAQ;AACd,cAAI,SAAS,YAAY,MAAO,UAAS,UAAU;AAAA,QACrD;AAAA,MACF,GAAG,CAAC;AACJ,iBAAW,UAAU;AAAA,IACvB;AAAA,EAEF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,eAAW,0BAAY,CAAC,MAAS;AACrC,kBAAc,CAAC;AACf,UAAM,QAAQ,SAAS;AACvB,QAAI,SAAS,WAAW,MAAO,OAAM,QAAQ;AAAA,EAC/C,GAAG,CAAC,CAAC;AAEL,SAAO,CAAC,OAAO,QAAQ;AACzB;","names":[]}
@@ -1,35 +0,0 @@
1
- import { PaneParent } from './use-pane-input.cjs';
2
- import 'tweakpane';
3
-
4
- interface PaneRadioGridCell<T> {
5
- /** Visible label on the button. */
6
- title: string;
7
- /** Value emitted by this cell when selected. */
8
- value: T;
9
- }
10
- interface PaneRadioGridOptions<T> {
11
- /** Radio-group name. Required by Tweakpane — any unique string works. */
12
- groupName?: string;
13
- /** Initially-selected value. Must match one of `cells[i].value`. */
14
- initialValue: T;
15
- /**
16
- * Grid cells in row-major order. Default layout is a single row with
17
- * `cells.length` columns, matching a top-of-pane toggle bar.
18
- */
19
- cells: ReadonlyArray<PaneRadioGridCell<T>>;
20
- /** Explicit `[cols, rows]`. Defaults to `[cells.length, 1]`. */
21
- size?: [number, number];
22
- }
23
- /**
24
- * Render an inline button-bar selector backed by the Tweakpane Essentials
25
- * `radiogrid` blade. Returns `[value, setValue]` — interacting with the
26
- * pane buttons updates React state, and `setValue` pushes back into the
27
- * blade. Intended for scene/mode toggles where a dropdown feels too
28
- * heavyweight and a row of labeled buttons reads better.
29
- *
30
- * Disposal is deferred through `setTimeout(0)` so the blade survives
31
- * React strict-mode's synchronous cleanup/re-mount pair.
32
- */
33
- declare function usePaneRadioGrid<T>(parent: PaneParent | null, options: PaneRadioGridOptions<T>): [T, (v: T) => void];
34
-
35
- export { type PaneRadioGridCell, type PaneRadioGridOptions, usePaneRadioGrid };
@@ -1,45 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var use_pane_exports = {};
20
- __export(use_pane_exports, {
21
- usePane: () => usePane
22
- });
23
- module.exports = __toCommonJS(use_pane_exports);
24
- var import_react = require("react");
25
- var import_create_pane = require("../create-pane.js");
26
- function usePane(options = {}) {
27
- const [bundle, setBundle] = (0, import_react.useState)(() => (0, import_create_pane.createPane)(options));
28
- const getOptions = (0, import_react.useEffectEvent)(() => options);
29
- (0, import_react.useEffect)(() => {
30
- if (bundle.disposed) {
31
- setBundle((0, import_create_pane.createPane)(getOptions()));
32
- return;
33
- }
34
- (0, import_create_pane.claimPane)(bundle);
35
- return () => {
36
- bundle.pane.dispose();
37
- };
38
- }, [bundle]);
39
- return bundle;
40
- }
41
- // Annotate the CommonJS export names for ESM import in node:
42
- 0 && (module.exports = {
43
- usePane
44
- });
45
- //# sourceMappingURL=use-pane.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/react/use-pane.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useState } from 'react'\nimport { claimPane, createPane } from '../create-pane.js'\nimport type { CreatePaneOptions, PaneBundle } from '../create-pane.js'\n\n/**\n * Create a themed Tweakpane instance. Disposes on unmount, recreates on\n * remount. Returns a `PaneBundle` whose identity changes if React tears\n * the component down and rebuilds it (StrictMode, parent remount,\n * Suspense). Child hooks that depend on the pane (`usePaneFolder`,\n * `usePaneInput`) re-bind when this happens.\n *\n * Lifecycle:\n * - Render: lazy-creates the bundle into a ref so it's available\n * synchronously on first paint. Render runs twice in StrictMode but\n * the ref guard prevents double-creation. Orphans from aborted\n * concurrent renders are reclaimed by `createPane`'s unclaimed-slot\n * mechanism.\n * - Effect: claims the bundle so unrelated `createPane` calls won't\n * dispose it; cleanup disposes the pane unconditionally.\n * - Effect re-mount (StrictMode or true remount): the bundle in the\n * ref is now `disposed`, so we create a fresh one and `force()` a\n * re-render so consumers receive the new identity.\n *\n * Uses `driver: 'raf'` so the stats graph self-ticks via its own\n * `requestAnimationFrame` loop. This makes `usePane` work regardless\n * of whether it's called inside or outside R3F's `<Canvas>` context.\n *\n * @param options - Same {@link CreatePaneOptions} as `createPane`.\n * @returns A {@link PaneBundle}; its identity changes across teardown and\n * rebuild so dependent hooks (`usePaneFolder`, `usePaneInput`) re-bind.\n *\n * @example\n * ```tsx\n * const { pane } = usePane()\n * const folder = usePaneFolder(pane, 'Settings')\n * const [speed] = usePaneInput(folder, 'speed', 1, { min: 0, max: 10 })\n * ```\n */\nexport function usePane(options: CreatePaneOptions = {}): PaneBundle {\n // Lazy initializer creates the bundle once, synchronously on first\n // render, so it's available for first paint. StrictMode's double-invoke\n // is absorbed by createPane's unclaimed-slot orphan disposal.\n const [bundle, setBundle] = useState(() => createPane(options))\n\n // Latest options read non-reactively when a disposed bundle is rebuilt.\n const getOptions = useEffectEvent(() => options)\n\n useEffect(() => {\n if (bundle.disposed) {\n setBundle(createPane(getOptions()))\n return\n }\n claimPane(bundle)\n return () => {\n bundle.pane.dispose()\n }\n }, [bundle])\n\n return bundle\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAoD;AACpD,yBAAsC;AAqC/B,SAAS,QAAQ,UAA6B,CAAC,GAAe;AAInE,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAS,UAAM,+BAAW,OAAO,CAAC;AAG9D,QAAM,iBAAa,6BAAe,MAAM,OAAO;AAE/C,8BAAU,MAAM;AACd,QAAI,OAAO,UAAU;AACnB,oBAAU,+BAAW,WAAW,CAAC,CAAC;AAClC;AAAA,IACF;AACA,sCAAU,MAAM;AAChB,WAAO,MAAM;AACX,aAAO,KAAK,QAAQ;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AACT;","names":[]}
@@ -1,40 +0,0 @@
1
- import { CreatePaneOptions, PaneBundle } from '../create-pane.cjs';
2
- import 'tweakpane';
3
-
4
- /**
5
- * Create a themed Tweakpane instance. Disposes on unmount, recreates on
6
- * remount. Returns a `PaneBundle` whose identity changes if React tears
7
- * the component down and rebuilds it (StrictMode, parent remount,
8
- * Suspense). Child hooks that depend on the pane (`usePaneFolder`,
9
- * `usePaneInput`) re-bind when this happens.
10
- *
11
- * Lifecycle:
12
- * - Render: lazy-creates the bundle into a ref so it's available
13
- * synchronously on first paint. Render runs twice in StrictMode but
14
- * the ref guard prevents double-creation. Orphans from aborted
15
- * concurrent renders are reclaimed by `createPane`'s unclaimed-slot
16
- * mechanism.
17
- * - Effect: claims the bundle so unrelated `createPane` calls won't
18
- * dispose it; cleanup disposes the pane unconditionally.
19
- * - Effect re-mount (StrictMode or true remount): the bundle in the
20
- * ref is now `disposed`, so we create a fresh one and `force()` a
21
- * re-render so consumers receive the new identity.
22
- *
23
- * Uses `driver: 'raf'` so the stats graph self-ticks via its own
24
- * `requestAnimationFrame` loop. This makes `usePane` work regardless
25
- * of whether it's called inside or outside R3F's `<Canvas>` context.
26
- *
27
- * @param options - Same {@link CreatePaneOptions} as `createPane`.
28
- * @returns A {@link PaneBundle}; its identity changes across teardown and
29
- * rebuild so dependent hooks (`usePaneFolder`, `usePaneInput`) re-bind.
30
- *
31
- * @example
32
- * ```tsx
33
- * const { pane } = usePane()
34
- * const folder = usePaneFolder(pane, 'Settings')
35
- * const [speed] = usePaneInput(folder, 'speed', 1, { min: 0, max: 10 })
36
- * ```
37
- */
38
- declare function usePane(options?: CreatePaneOptions): PaneBundle;
39
-
40
- export { usePane };
package/dist/react.cjs DELETED
@@ -1,50 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var react_exports = {};
20
- __export(react_exports, {
21
- DevtoolsClient: () => import_devtools_client.DevtoolsClient,
22
- DevtoolsProvider: () => import_devtools_provider.DevtoolsProvider,
23
- useFpsGraph: () => import_use_fps_graph.useFpsGraph,
24
- usePane: () => import_use_pane.usePane,
25
- usePaneButton: () => import_use_pane_button.usePaneButton,
26
- usePaneFolder: () => import_use_pane_folder.usePaneFolder,
27
- usePaneInput: () => import_use_pane_input.usePaneInput,
28
- usePaneRadioGrid: () => import_use_pane_radio_grid.usePaneRadioGrid
29
- });
30
- module.exports = __toCommonJS(react_exports);
31
- var import_use_pane = require("./react/use-pane.js");
32
- var import_devtools_provider = require("./react/devtools-provider.js");
33
- var import_use_pane_input = require("./react/use-pane-input.js");
34
- var import_use_pane_folder = require("./react/use-pane-folder.js");
35
- var import_use_pane_button = require("./react/use-pane-button.js");
36
- var import_use_pane_radio_grid = require("./react/use-pane-radio-grid.js");
37
- var import_use_fps_graph = require("./react/use-fps-graph.js");
38
- var import_devtools_client = require("./devtools-client.js");
39
- // Annotate the CommonJS export names for ESM import in node:
40
- 0 && (module.exports = {
41
- DevtoolsClient,
42
- DevtoolsProvider,
43
- useFpsGraph,
44
- usePane,
45
- usePaneButton,
46
- usePaneFolder,
47
- usePaneInput,
48
- usePaneRadioGrid
49
- });
50
- //# sourceMappingURL=react.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/react.ts"],"sourcesContent":["export { usePane } from './react/use-pane.js'\nexport { DevtoolsProvider } from './react/devtools-provider.js'\nexport type { DevtoolsProviderProps } from './react/devtools-provider.js'\nexport { usePaneInput } from './react/use-pane-input.js'\nexport type { PaneParent, PaneInputOptions } from './react/use-pane-input.js'\nexport { usePaneFolder } from './react/use-pane-folder.js'\nexport { usePaneButton } from './react/use-pane-button.js'\nexport { usePaneRadioGrid } from './react/use-pane-radio-grid.js'\nexport type { PaneRadioGridCell, PaneRadioGridOptions } from './react/use-pane-radio-grid.js'\nexport { useFpsGraph } from './react/use-fps-graph.js'\nexport type { FpsGraphHandle } from './react/use-fps-graph.js'\nexport type { CreatePaneOptions, PaneBundle } from './create-pane.js'\n// Advanced: re-export the bus consumer so callers can spin up extra\n// consumers next to the one that `usePane` already manages.\nexport { DevtoolsClient } from './devtools-client.js'\nexport type {\n DevtoolsClientOptions,\n DevtoolsState,\n DevtoolsStateListener,\n} from './devtools-client.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAwB;AACxB,+BAAiC;AAEjC,4BAA6B;AAE7B,6BAA8B;AAC9B,6BAA8B;AAC9B,iCAAiC;AAEjC,2BAA4B;AAK5B,6BAA+B;","names":[]}
package/dist/react.d.cts DELETED
@@ -1,12 +0,0 @@
1
- export { usePane } from './react/use-pane.cjs';
2
- export { DevtoolsProvider, DevtoolsProviderProps } from './react/devtools-provider.cjs';
3
- export { PaneInputOptions, PaneParent, usePaneInput } from './react/use-pane-input.cjs';
4
- export { usePaneFolder } from './react/use-pane-folder.cjs';
5
- export { usePaneButton } from './react/use-pane-button.cjs';
6
- export { PaneRadioGridCell, PaneRadioGridOptions, usePaneRadioGrid } from './react/use-pane-radio-grid.cjs';
7
- export { FpsGraphHandle, useFpsGraph } from './react/use-fps-graph.cjs';
8
- export { CreatePaneOptions, PaneBundle } from './create-pane.cjs';
9
- export { DevtoolsClient, DevtoolsClientOptions, DevtoolsState, DevtoolsStateListener } from './devtools-client.cjs';
10
- import 'react';
11
- import 'tweakpane';
12
- import 'three-flatland/debug-protocol';
package/dist/react.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/react.ts"],"sourcesContent":["export { usePane } from './react/use-pane.js'\nexport { DevtoolsProvider } from './react/devtools-provider.js'\nexport type { DevtoolsProviderProps } from './react/devtools-provider.js'\nexport { usePaneInput } from './react/use-pane-input.js'\nexport type { PaneParent, PaneInputOptions } from './react/use-pane-input.js'\nexport { usePaneFolder } from './react/use-pane-folder.js'\nexport { usePaneButton } from './react/use-pane-button.js'\nexport { usePaneRadioGrid } from './react/use-pane-radio-grid.js'\nexport type { PaneRadioGridCell, PaneRadioGridOptions } from './react/use-pane-radio-grid.js'\nexport { useFpsGraph } from './react/use-fps-graph.js'\nexport type { FpsGraphHandle } from './react/use-fps-graph.js'\nexport type { CreatePaneOptions, PaneBundle } from './create-pane.js'\n// Advanced: re-export the bus consumer so callers can spin up extra\n// consumers next to the one that `usePane` already manages.\nexport { DevtoolsClient } from './devtools-client.js'\nexport type {\n DevtoolsClientOptions,\n DevtoolsState,\n DevtoolsStateListener,\n} from './devtools-client.js'\n"],"mappings":"AAAA,SAAS,eAAe;AACxB,SAAS,wBAAwB;AAEjC,SAAS,oBAAoB;AAE7B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AAEjC,SAAS,mBAAmB;AAK5B,SAAS,sBAAsB;","names":[]}