@joycostudio/studio 0.1.4 → 0.1.5
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/README.md +3 -2
- package/dist/{chunk-2RGQF5X5.js → chunk-ZH3NEN4V.js} +55 -49
- package/dist/chunk-ZH3NEN4V.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +8 -3
- package/dist/client.js +1 -1
- package/dist/next.js +1 -1
- package/dist/react.d.ts +8 -3
- package/dist/react.js +13 -10
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2RGQF5X5.js.map +0 -1
package/dist/client.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
15
15
|
readonly definition: ToolDefinition<TConfig>;
|
|
16
16
|
/** The live config. Writes sync to same-origin pages and, when connected, the runtime. */
|
|
17
17
|
readonly config: TConfig;
|
|
18
|
-
/** Runtime-owned state; null
|
|
18
|
+
/** Runtime-owned state; null while no runtime is connected or until it answers. */
|
|
19
19
|
readonly state: ToolState<TConfig> | null;
|
|
20
20
|
/** Bumps on every config change. Handy as a React snapshot. */
|
|
21
21
|
readonly version: number;
|
|
@@ -25,7 +25,7 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
25
25
|
controls(): DebugSchema;
|
|
26
26
|
/** Xyz `Debuggable`: `debugManager.register(handle)` mounts this tool in the app's floating pane. */
|
|
27
27
|
debug(): DebugFolder;
|
|
28
|
-
/** The config on disk: the runtime's saved value or, until one answers, the bundled `initial`. */
|
|
28
|
+
/** The config on disk: the runtime's last reported saved value or, until one answers, the bundled `initial`. */
|
|
29
29
|
readonly saved: TConfig;
|
|
30
30
|
/** Dotted paths where the draft differs from `saved`. Tracked locally, so it works without a runtime too. */
|
|
31
31
|
readonly changes: string[];
|
|
@@ -47,10 +47,15 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
47
47
|
*/
|
|
48
48
|
undo(): boolean;
|
|
49
49
|
redo(): boolean;
|
|
50
|
+
/** Persist the draft. Needs a connected runtime. */
|
|
50
51
|
save(options?: {
|
|
51
52
|
force?: boolean;
|
|
52
53
|
}): Promise<Result<ToolState<TConfig>>>;
|
|
53
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Reset the draft to `saved`, with or without a runtime, then sync it like any other edit.
|
|
56
|
+
* Undoable as its own step. Returns false when there is nothing to discard.
|
|
57
|
+
*/
|
|
58
|
+
discard(): boolean;
|
|
54
59
|
};
|
|
55
60
|
type Studio = {
|
|
56
61
|
/** Every registered tool in order, including preview-only ones. */
|
package/dist/client.js
CHANGED
package/dist/next.js
CHANGED
package/dist/react.d.ts
CHANGED
|
@@ -93,7 +93,7 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
93
93
|
readonly definition: ToolDefinition<TConfig>;
|
|
94
94
|
/** The live config. Writes sync to same-origin pages and, when connected, the runtime. */
|
|
95
95
|
readonly config: TConfig;
|
|
96
|
-
/** Runtime-owned state; null
|
|
96
|
+
/** Runtime-owned state; null while no runtime is connected or until it answers. */
|
|
97
97
|
readonly state: ToolState<TConfig> | null;
|
|
98
98
|
/** Bumps on every config change. Handy as a React snapshot. */
|
|
99
99
|
readonly version: number;
|
|
@@ -103,7 +103,7 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
103
103
|
controls(): DebugSchema;
|
|
104
104
|
/** Xyz `Debuggable`: `debugManager.register(handle)` mounts this tool in the app's floating pane. */
|
|
105
105
|
debug(): DebugFolder;
|
|
106
|
-
/** The config on disk: the runtime's saved value or, until one answers, the bundled `initial`. */
|
|
106
|
+
/** The config on disk: the runtime's last reported saved value or, until one answers, the bundled `initial`. */
|
|
107
107
|
readonly saved: TConfig;
|
|
108
108
|
/** Dotted paths where the draft differs from `saved`. Tracked locally, so it works without a runtime too. */
|
|
109
109
|
readonly changes: string[];
|
|
@@ -125,10 +125,15 @@ type ToolHandle<TConfig extends object = any> = {
|
|
|
125
125
|
*/
|
|
126
126
|
undo(): boolean;
|
|
127
127
|
redo(): boolean;
|
|
128
|
+
/** Persist the draft. Needs a connected runtime. */
|
|
128
129
|
save(options?: {
|
|
129
130
|
force?: boolean;
|
|
130
131
|
}): Promise<Result<ToolState<TConfig>>>;
|
|
131
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Reset the draft to `saved`, with or without a runtime, then sync it like any other edit.
|
|
134
|
+
* Undoable as its own step. Returns false when there is nothing to discard.
|
|
135
|
+
*/
|
|
136
|
+
discard(): boolean;
|
|
132
137
|
};
|
|
133
138
|
type Studio$1 = {
|
|
134
139
|
/** Every registered tool in order, including preview-only ones. */
|
package/dist/react.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { useEffect as useEffect5, useRef as useRef3, useState as useState9 } from "react";
|
|
15
15
|
|
|
16
16
|
// package.json
|
|
17
|
-
var version = "0.1.
|
|
17
|
+
var version = "0.1.5";
|
|
18
18
|
|
|
19
19
|
// src/client/studio.ts
|
|
20
20
|
import {
|
|
@@ -409,7 +409,7 @@ function describe(studio, handle) {
|
|
|
409
409
|
if (studio.connection.phase !== "connected") return { tone: "text-faint", text: "Not persisting" };
|
|
410
410
|
if (!state) return { tone: "text-destructive", text: "Restart studio dev" };
|
|
411
411
|
if (state.conflict) return { tone: "text-destructive", text: "Changed on disk" };
|
|
412
|
-
if (
|
|
412
|
+
if (handle.dirty) return { tone: "text-warning", text: "Unsaved" };
|
|
413
413
|
return { tone: "text-success", text: state.saved.hash ? "Saved" : "Not on disk yet" };
|
|
414
414
|
}
|
|
415
415
|
function adoptTweakpaneStyles(container) {
|
|
@@ -429,8 +429,10 @@ function Inspector({
|
|
|
429
429
|
const container = useRef(null);
|
|
430
430
|
const pane = useRef(null);
|
|
431
431
|
const [failure, setFailure] = useState2(null);
|
|
432
|
-
const
|
|
433
|
-
const
|
|
432
|
+
const { definition, state } = handle;
|
|
433
|
+
const canDiscard = handle.dirty && !handle.comparing;
|
|
434
|
+
const canSave = canDiscard && !!state;
|
|
435
|
+
const save = (force = false) => void handle.save({ force }).then((result) => setFailure(result.ok ? null : result.message ?? result.error));
|
|
434
436
|
useEffect(() => {
|
|
435
437
|
let disposed = false;
|
|
436
438
|
let teardown = () => {
|
|
@@ -461,7 +463,7 @@ function Inspector({
|
|
|
461
463
|
const onKeyDown = (event) => {
|
|
462
464
|
if (event.key !== "s" || !(event.metaKey || event.ctrlKey)) return;
|
|
463
465
|
event.preventDefault();
|
|
464
|
-
if (
|
|
466
|
+
if (canSave) save();
|
|
465
467
|
};
|
|
466
468
|
addEventListener("keydown", onKeyDown);
|
|
467
469
|
return () => removeEventListener("keydown", onKeyDown);
|
|
@@ -469,10 +471,8 @@ function Inspector({
|
|
|
469
471
|
useEffect(() => {
|
|
470
472
|
if (pane.current) pane.current.disabled = handle.comparing;
|
|
471
473
|
});
|
|
472
|
-
const { definition, state } = handle;
|
|
473
474
|
const ConfigFile = fileHref ? "a" : "span";
|
|
474
475
|
const status = describe(studio, handle);
|
|
475
|
-
const editable2 = studio.connection.phase === "connected" && !!state?.dirty && !handle.comparing;
|
|
476
476
|
const changes = handle.changes.map(
|
|
477
477
|
(path) => path.split(".").map((key) => key.charAt(0).toUpperCase() + key.slice(1)).join(" \u203A ")
|
|
478
478
|
);
|
|
@@ -549,12 +549,15 @@ function Inspector({
|
|
|
549
549
|
variant: "secondary",
|
|
550
550
|
size: "sm",
|
|
551
551
|
className: "flex-1",
|
|
552
|
-
disabled: !
|
|
553
|
-
onClick: () =>
|
|
552
|
+
disabled: !canDiscard,
|
|
553
|
+
onClick: () => {
|
|
554
|
+
setFailure(null);
|
|
555
|
+
handle.discard();
|
|
556
|
+
},
|
|
554
557
|
children: "Discard"
|
|
555
558
|
}
|
|
556
559
|
),
|
|
557
|
-
state?.conflict ? /* @__PURE__ */ jsx8(Button, { variant: "destructive", size: "sm", className: "flex-1", onClick: () => save(true), children: "Overwrite file" }) : /* @__PURE__ */ jsxs2(Button, { size: "sm", className: "flex-1", disabled: !
|
|
560
|
+
state?.conflict ? /* @__PURE__ */ jsx8(Button, { variant: "destructive", size: "sm", className: "flex-1", onClick: () => save(true), children: "Overwrite file" }) : /* @__PURE__ */ jsxs2(Button, { size: "sm", className: "flex-1", disabled: !canSave, onClick: () => save(), children: [
|
|
558
561
|
"Save",
|
|
559
562
|
/* @__PURE__ */ jsxs2(KbdGroup, { children: [
|
|
560
563
|
/* @__PURE__ */ jsx8(Kbd, { children: "\u2318" }),
|