@joycostudio/studio 0.1.5 → 0.2.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/dist/client.d.ts CHANGED
@@ -1,5 +1,13 @@
1
- import { DebugSchema, DebugFolder } from '@joycostudio/xyz/debug';
2
- import { f as StudioTool, T as ToolDefinition, j as ToolState, R as Result, i as ToolReference } from './protocol-DjrMADPm.js';
1
+ import { DebugFolder, DebugHost } from '@joycostudio/xyz/debug';
2
+ import { f as StudioTool, T as ToolDefinition, k as ToolState, h as ToolControls, R as Result, j as ToolReference } from './protocol-BviGBdSG.js';
3
+ import { StudioUi } from './ui.js';
4
+ import '@joycostudio/xyz/debug/dialkit';
5
+
6
+ type Change = {
7
+ path: string[];
8
+ before: unknown;
9
+ after: unknown;
10
+ };
3
11
 
4
12
  type Connection = {
5
13
  phase: 'local';
@@ -22,13 +30,15 @@ type ToolHandle<TConfig extends object = any> = {
22
30
  /** Called after every config change, local or remote. */
23
31
  subscribe(listener: (config: TConfig) => void): () => void;
24
32
  /** The tool's Xyz schema bound to the live config. */
25
- controls(): DebugSchema;
33
+ controls(): ToolControls;
26
34
  /** Xyz `Debuggable`: `debugManager.register(handle)` mounts this tool in the app's floating pane. */
27
- debug(): DebugFolder;
35
+ debug(): DebugFolder<DebugHost>;
28
36
  /** The config on disk: the runtime's last reported saved value or, until one answers, the bundled `initial`. */
29
37
  readonly saved: TConfig;
30
38
  /** Dotted paths where the draft differs from `saved`. Tracked locally, so it works without a runtime too. */
31
39
  readonly changes: string[];
40
+ /** Each leaf where the draft differs from `saved`: `before` is the saved value, `after` the draft's. */
41
+ readonly diff: Change[];
32
42
  /** The draft differs from `saved`. */
33
43
  readonly dirty: boolean;
34
44
  /** True while `compare(true)` shows the saved config in place of the draft. */
@@ -56,6 +66,16 @@ type ToolHandle<TConfig extends object = any> = {
56
66
  * Undoable as its own step. Returns false when there is nothing to discard.
57
67
  */
58
68
  discard(): boolean;
69
+ /**
70
+ * Reset one changed leaf (a dotted path from `changes`, or its keys, which also address keys containing dots) to its saved value, then sync it like any
71
+ * other edit. Undoable as its own step. Returns false when that leaf is unchanged or while comparing.
72
+ */
73
+ revert(path: string | readonly string[]): boolean;
74
+ /**
75
+ * A link to `base` (the current page by default) carrying the draft. Opening it on another machine applies
76
+ * that draft as an unsaved, undoable edit; a draft that no longer fits the tool's controls is ignored.
77
+ */
78
+ shareUrl(base?: string | URL): string;
59
79
  };
60
80
  type Studio = {
61
81
  /** Every registered tool in order, including preview-only ones. */
@@ -64,6 +84,8 @@ type Studio = {
64
84
  readonly tools: readonly ToolHandle[];
65
85
  tool<TConfig extends object>(definition: ToolReference<TConfig>): ToolHandle<TConfig>;
66
86
  readonly connection: Connection;
87
+ /** The debug UI library tools' controls are drawn with. `<Studio>` and `<StudioDebug>` need one. */
88
+ readonly ui: StudioUi | undefined;
67
89
  /** Bumps on connection or any tool state change. */
68
90
  readonly version: number;
69
91
  subscribe(listener: () => void): () => void;
@@ -76,6 +98,12 @@ type StudioOptions = {
76
98
  * Only browsers connect, so a module-scope `createStudio` is safe to evaluate during SSR.
77
99
  */
78
100
  runtime?: string | false;
101
+ /**
102
+ * The debug UI library to draw controls with, from `@joycostudio/studio/ui`:
103
+ * `tweakpane(() => import('tweakpane'))` or `dialkit(() => import('dialkit/vanilla'))`.
104
+ * Required by `<Studio>` and `<StudioDebug>`; reading configs alone doesn't need one.
105
+ */
106
+ ui?: StudioUi;
79
107
  };
80
108
  /** Make the studio running in `target` (e.g. a preview iframe) compare `tool` as well. */
81
109
  declare function postCompare(target: Window | null | undefined, tool: string, showSaved: boolean): void;
@@ -83,4 +111,4 @@ declare function postCompare(target: Window | null | undefined, tool: string, sh
83
111
  declare function everyFrame(refresh: () => void): () => void;
84
112
  declare function createStudio(config: StudioOptions, options?: Pick<StudioOptions, 'runtime'>): Studio;
85
113
 
86
- export { type Connection, type Studio, type StudioOptions, type ToolHandle, createStudio, everyFrame, postCompare };
114
+ export { type Change, type Connection, type Studio, type StudioOptions, StudioUi, type ToolHandle, createStudio, everyFrame, postCompare };
package/dist/client.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  createStudio,
3
3
  everyFrame,
4
4
  postCompare
5
- } from "./chunk-ZH3NEN4V.js";
6
- import "./chunk-DEJYGBPJ.js";
5
+ } from "./chunk-ZPKMVZ67.js";
6
+ import "./chunk-OEJWPWYJ.js";
7
7
  export {
8
8
  createStudio,
9
9
  everyFrame,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as ToolDefinition, R as Result } from './protocol-DjrMADPm.js';
2
- export { A as AnyTool, C as ConfigOf, D as DEFAULT_PORT, a as DiscoveredToolConfigs, b as DiscoveredToolDefinition, F as Failure, O as Op, c as Operations, P as PreviewToolDefinition, d as Request, S as ServerMessage, e as StudioConfig, f as StudioTool, g as Success, h as ToolIcon, i as ToolReference, j as ToolState, k as ToolSummary, l as defineConfig, m as defineTool, n as error, o as hasConfig, s as success } from './protocol-DjrMADPm.js';
1
+ import { T as ToolDefinition, R as Result } from './protocol-BviGBdSG.js';
2
+ export { A as AnyTool, C as ConfigOf, D as DEFAULT_PORT, a as DiscoveredToolConfigs, b as DiscoveredToolDefinition, F as Failure, O as Op, c as Operations, P as PreviewToolDefinition, d as Request, S as ServerMessage, e as StudioConfig, f as StudioTool, g as Success, h as ToolControls, i as ToolIcon, j as ToolReference, k as ToolState, l as ToolSummary, m as defineConfig, n as defineTool, o as error, p as hasConfig, s as success } from './protocol-BviGBdSG.js';
3
3
  import '@joycostudio/xyz/debug';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  hasConfig,
7
7
  success,
8
8
  validateConfig
9
- } from "./chunk-DEJYGBPJ.js";
9
+ } from "./chunk-OEJWPWYJ.js";
10
10
  export {
11
11
  DEFAULT_PORT,
12
12
  defineConfig,
package/dist/next.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { StudioOptions, Studio } from './client.js';
2
2
  import '@joycostudio/xyz/debug';
3
- import './protocol-DjrMADPm.js';
3
+ import './protocol-BviGBdSG.js';
4
+ import './ui.js';
5
+ import '@joycostudio/xyz/debug/dialkit';
4
6
 
5
7
  /** Next.js replaces this public environment variable in browser bundles. */
6
8
  declare function createStudio(config: StudioOptions, options?: Pick<StudioOptions, 'runtime'>): Studio;
package/dist/next.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createStudio
3
- } from "./chunk-ZH3NEN4V.js";
4
- import "./chunk-DEJYGBPJ.js";
3
+ } from "./chunk-ZPKMVZ67.js";
4
+ import "./chunk-OEJWPWYJ.js";
5
5
 
6
6
  // src/next.ts
7
7
  function createStudio2(config, options = {}) {
@@ -1,4 +1,4 @@
1
- import { DebugSchema } from '@joycostudio/xyz/debug';
1
+ import { DebugSchema, DebugHost } from '@joycostudio/xyz/debug';
2
2
 
3
3
  type Success<T> = {
4
4
  ok: true;
@@ -14,6 +14,8 @@ type Result<T> = Success<T> | Failure;
14
14
  declare const success: <T>(data: T) => Success<T>;
15
15
  declare const error: (code: string, message?: string) => Failure;
16
16
 
17
+ /** Controls as an Xyz schema. Drawn with whichever UI the app picks (`createStudio({ ui })`), so `extend` gets an unknown folder. */
18
+ type ToolControls = DebugSchema<DebugHost>;
17
19
  /**
18
20
  * An SVG icon as data: `[tag, attributes]` children of a 24×24 stroke icon.
19
21
  * Lucide's core package (`import { Palette } from 'lucide'`) exports exactly this shape.
@@ -42,10 +44,10 @@ type ToolDefinition<TConfig extends object = object> = ToolBase & {
42
44
  /** Config used before the runtime answers (and in production). */
43
45
  initial: TConfig;
44
46
  /**
45
- * What can be tweaked, as an Xyz/Tweakpane schema bound to `config`.
47
+ * What can be tweaked, as an Xyz schema bound to `config`.
46
48
  * Doubles as the runtime validator: every control's bounds are enforced on write.
47
49
  */
48
- controls: (config: TConfig) => DebugSchema;
50
+ controls: (config: TConfig) => ToolControls;
49
51
  };
50
52
  /** A tool with nothing to tune: a sidebar entry for its preview, without an inspector or config file. */
51
53
  type PreviewToolDefinition = ToolBase & {
@@ -66,7 +68,7 @@ interface DiscoveredToolConfigs {
66
68
  type DiscoveredToolDefinition<TConfig extends object = object> = ToolBase & {
67
69
  /** JSON source relative to this tool file, or a tsconfig path alias. Defaults to ./config.json. */
68
70
  config?: string;
69
- controls: (config: TConfig) => DebugSchema;
71
+ controls: (config: TConfig) => ToolControls;
70
72
  file?: never;
71
73
  initial?: never;
72
74
  };
@@ -188,4 +190,4 @@ type ServerMessage = {
188
190
  state: ToolState;
189
191
  };
190
192
 
191
- export { type AnyTool as A, type ConfigOf as C, DEFAULT_PORT as D, type Failure as F, type Op as O, type PreviewToolDefinition as P, type Result as R, type ServerMessage as S, type ToolDefinition as T, type DiscoveredToolConfigs as a, type DiscoveredToolDefinition as b, type Operations as c, type Request as d, type StudioConfig as e, type StudioTool as f, type Success as g, type ToolIcon as h, type ToolReference as i, type ToolState as j, type ToolSummary as k, defineConfig as l, defineTool as m, error as n, hasConfig as o, success as s };
193
+ export { type AnyTool as A, type ConfigOf as C, DEFAULT_PORT as D, type Failure as F, type Op as O, type PreviewToolDefinition as P, type Result as R, type ServerMessage as S, type ToolDefinition as T, type DiscoveredToolConfigs as a, type DiscoveredToolDefinition as b, type Operations as c, type Request as d, type StudioConfig as e, type StudioTool as f, type Success as g, type ToolControls as h, type ToolIcon as i, type ToolReference as j, type ToolState as k, type ToolSummary as l, defineConfig as m, defineTool as n, error as o, hasConfig as p, success as s };
package/dist/react.d.ts CHANGED
@@ -1,8 +1,14 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentType, ComponentPropsWithRef, ReactNode, ComponentPropsWithoutRef, ComponentProps } from 'react';
3
- import { DebugSchema, DebugFolder } from '@joycostudio/xyz/debug';
3
+ import { DebugSchema, DebugHost, DebugAdapter, DebugFolder } from '@joycostudio/xyz/debug';
4
4
  import { Select } from '@base-ui/react/select';
5
5
 
6
+ type Change = {
7
+ path: string[];
8
+ before: unknown;
9
+ after: unknown;
10
+ };
11
+
6
12
  type Success<T> = {
7
13
  ok: true;
8
14
  data: T;
@@ -15,6 +21,8 @@ type Failure = {
15
21
  };
16
22
  type Result<T> = Success<T> | Failure;
17
23
 
24
+ /** Controls as an Xyz schema. Drawn with whichever UI the app picks (`createStudio({ ui })`), so `extend` gets an unknown folder. */
25
+ type ToolControls = DebugSchema<DebugHost>;
18
26
  /**
19
27
  * An SVG icon as data: `[tag, attributes]` children of a 24×24 stroke icon.
20
28
  * Lucide's core package (`import { Palette } from 'lucide'`) exports exactly this shape.
@@ -43,10 +51,10 @@ type ToolDefinition<TConfig extends object = object> = ToolBase & {
43
51
  /** Config used before the runtime answers (and in production). */
44
52
  initial: TConfig;
45
53
  /**
46
- * What can be tweaked, as an Xyz/Tweakpane schema bound to `config`.
54
+ * What can be tweaked, as an Xyz schema bound to `config`.
47
55
  * Doubles as the runtime validator: every control's bounds are enforced on write.
48
56
  */
49
- controls: (config: TConfig) => DebugSchema;
57
+ controls: (config: TConfig) => ToolControls;
50
58
  };
51
59
  /** A tool with nothing to tune: a sidebar entry for its preview, without an inspector or config file. */
52
60
  type PreviewToolDefinition = ToolBase & {
@@ -79,6 +87,25 @@ type ToolState<TConfig = unknown> = {
79
87
  conflict: boolean;
80
88
  };
81
89
 
90
+ /**
91
+ * The debug UI library Studio draws tool controls with: Tweakpane or DialKit. Pick one with
92
+ * `createStudio({ ui })`; the library loads lazily through `load`, from the host app, so only
93
+ * the one you pick needs to be installed.
94
+ */
95
+ type StudioUi = {
96
+ readonly kind: string;
97
+ /** The floating pane `StudioDebug` opens on `?debug` / Option+D. */
98
+ floating: DebugAdapter;
99
+ /** Controls drawn inside `container`, as the /studio inspector does. */
100
+ inline(container: HTMLElement, options: {
101
+ title: string;
102
+ }): Promise<DebugHost & {
103
+ dispose(): void;
104
+ }>;
105
+ /** Copy the library's page styles into Studio's shadow root, which page stylesheets don't reach. */
106
+ adoptStyles(root: ShadowRoot): void | Promise<void>;
107
+ };
108
+
82
109
  type Connection = {
83
110
  phase: 'local';
84
111
  } | {
@@ -100,13 +127,15 @@ type ToolHandle<TConfig extends object = any> = {
100
127
  /** Called after every config change, local or remote. */
101
128
  subscribe(listener: (config: TConfig) => void): () => void;
102
129
  /** The tool's Xyz schema bound to the live config. */
103
- controls(): DebugSchema;
130
+ controls(): ToolControls;
104
131
  /** Xyz `Debuggable`: `debugManager.register(handle)` mounts this tool in the app's floating pane. */
105
- debug(): DebugFolder;
132
+ debug(): DebugFolder<DebugHost>;
106
133
  /** The config on disk: the runtime's last reported saved value or, until one answers, the bundled `initial`. */
107
134
  readonly saved: TConfig;
108
135
  /** Dotted paths where the draft differs from `saved`. Tracked locally, so it works without a runtime too. */
109
136
  readonly changes: string[];
137
+ /** Each leaf where the draft differs from `saved`: `before` is the saved value, `after` the draft's. */
138
+ readonly diff: Change[];
110
139
  /** The draft differs from `saved`. */
111
140
  readonly dirty: boolean;
112
141
  /** True while `compare(true)` shows the saved config in place of the draft. */
@@ -134,6 +163,16 @@ type ToolHandle<TConfig extends object = any> = {
134
163
  * Undoable as its own step. Returns false when there is nothing to discard.
135
164
  */
136
165
  discard(): boolean;
166
+ /**
167
+ * Reset one changed leaf (a dotted path from `changes`, or its keys, which also address keys containing dots) to its saved value, then sync it like any
168
+ * other edit. Undoable as its own step. Returns false when that leaf is unchanged or while comparing.
169
+ */
170
+ revert(path: string | readonly string[]): boolean;
171
+ /**
172
+ * A link to `base` (the current page by default) carrying the draft. Opening it on another machine applies
173
+ * that draft as an unsaved, undoable edit; a draft that no longer fits the tool's controls is ignored.
174
+ */
175
+ shareUrl(base?: string | URL): string;
137
176
  };
138
177
  type Studio$1 = {
139
178
  /** Every registered tool in order, including preview-only ones. */
@@ -142,6 +181,8 @@ type Studio$1 = {
142
181
  readonly tools: readonly ToolHandle[];
143
182
  tool<TConfig extends object>(definition: ToolReference<TConfig>): ToolHandle<TConfig>;
144
183
  readonly connection: Connection;
184
+ /** The debug UI library tools' controls are drawn with. `<Studio>` and `<StudioDebug>` need one. */
185
+ readonly ui: StudioUi | undefined;
145
186
  /** Bumps on connection or any tool state change. */
146
187
  readonly version: number;
147
188
  subscribe(listener: () => void): () => void;