@jarenjs/studio 0.67.0 → 0.72.2
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 +2 -0
- package/dist/types/component/index.d.ts +43 -19
- package/dist/types/component/view.d.ts +43 -19
- package/docs/PROJECT-FORMAT.md +13 -3
- package/package.json +8 -8
- package/schemas/jaren-project.draft-07.schema.json +1 -1
- package/src/component/view.js +7 -2
- package/src/component/viewmodel.js +1 -0
- package/styles/studio.css +11 -5
package/README.md
CHANGED
|
@@ -32,7 +32,11 @@ export declare function createStudioComponent(options?: {
|
|
|
32
32
|
name: string;
|
|
33
33
|
class: string;
|
|
34
34
|
role: string;
|
|
35
|
-
'aria-orientation':
|
|
35
|
+
'aria-orientation': {
|
|
36
|
+
$if: (string | {
|
|
37
|
+
$eq: string[];
|
|
38
|
+
})[];
|
|
39
|
+
};
|
|
36
40
|
'aria-label': string;
|
|
37
41
|
'aria-valuemin': string;
|
|
38
42
|
'aria-valuemax': string;
|
|
@@ -41,6 +45,11 @@ export declare function createStudioComponent(options?: {
|
|
|
41
45
|
props: {
|
|
42
46
|
ratio: string;
|
|
43
47
|
mode: string;
|
|
48
|
+
axis: {
|
|
49
|
+
$if: (string | {
|
|
50
|
+
$eq: string[];
|
|
51
|
+
})[];
|
|
52
|
+
};
|
|
44
53
|
};
|
|
45
54
|
})[] | (string | any[] | {
|
|
46
55
|
class: string;
|
|
@@ -65,6 +74,12 @@ export declare function createStudioComponent(options?: {
|
|
|
65
74
|
})[] | {
|
|
66
75
|
class: string;
|
|
67
76
|
$if?: undefined;
|
|
77
|
+
} | {
|
|
78
|
+
class?: undefined;
|
|
79
|
+
$if: (string | (string | {
|
|
80
|
+
class: string;
|
|
81
|
+
role: string;
|
|
82
|
+
})[])[];
|
|
68
83
|
} | {
|
|
69
84
|
class?: undefined;
|
|
70
85
|
$if: ((string | (string | {
|
|
@@ -96,24 +111,6 @@ export declare function createStudioComponent(options?: {
|
|
|
96
111
|
})[];
|
|
97
112
|
$eq?: undefined;
|
|
98
113
|
})[];
|
|
99
|
-
})[] | (string | (string | {
|
|
100
|
-
class: string;
|
|
101
|
-
type: string;
|
|
102
|
-
on: {
|
|
103
|
-
click: string;
|
|
104
|
-
};
|
|
105
|
-
})[] | (string | any[] | {
|
|
106
|
-
class: string;
|
|
107
|
-
role: string;
|
|
108
|
-
'aria-label': string;
|
|
109
|
-
})[] | (string | {
|
|
110
|
-
$apply: string;
|
|
111
|
-
}[] | (string | {
|
|
112
|
-
class: string;
|
|
113
|
-
})[] | {
|
|
114
|
-
class: string;
|
|
115
|
-
})[] | {
|
|
116
|
-
class: string;
|
|
117
114
|
})[] | (string | (string | {
|
|
118
115
|
class: string;
|
|
119
116
|
rows: number;
|
|
@@ -169,6 +166,33 @@ export declare function createStudioComponent(options?: {
|
|
|
169
166
|
role: string;
|
|
170
167
|
})[])[];
|
|
171
168
|
class?: undefined;
|
|
169
|
+
})[] | (string | (string | {
|
|
170
|
+
class: string;
|
|
171
|
+
type: string;
|
|
172
|
+
'aria-pressed': {
|
|
173
|
+
$if: string[];
|
|
174
|
+
};
|
|
175
|
+
on: {
|
|
176
|
+
click: string;
|
|
177
|
+
};
|
|
178
|
+
})[] | (string | {
|
|
179
|
+
class: string;
|
|
180
|
+
type: string;
|
|
181
|
+
on: {
|
|
182
|
+
click: string;
|
|
183
|
+
};
|
|
184
|
+
})[] | (string | any[] | {
|
|
185
|
+
class: string;
|
|
186
|
+
role: string;
|
|
187
|
+
'aria-label': string;
|
|
188
|
+
})[] | (string | {
|
|
189
|
+
$apply: string;
|
|
190
|
+
}[] | (string | {
|
|
191
|
+
class: string;
|
|
192
|
+
})[] | {
|
|
193
|
+
class: string;
|
|
194
|
+
})[] | {
|
|
195
|
+
class: string;
|
|
172
196
|
})[] | {
|
|
173
197
|
class: string;
|
|
174
198
|
'data-mode': string;
|
|
@@ -30,7 +30,11 @@ export declare const projectRules: ({
|
|
|
30
30
|
name: string;
|
|
31
31
|
class: string;
|
|
32
32
|
role: string;
|
|
33
|
-
'aria-orientation':
|
|
33
|
+
'aria-orientation': {
|
|
34
|
+
$if: (string | {
|
|
35
|
+
$eq: string[];
|
|
36
|
+
})[];
|
|
37
|
+
};
|
|
34
38
|
'aria-label': string;
|
|
35
39
|
'aria-valuemin': string;
|
|
36
40
|
'aria-valuemax': string;
|
|
@@ -39,6 +43,11 @@ export declare const projectRules: ({
|
|
|
39
43
|
props: {
|
|
40
44
|
ratio: string;
|
|
41
45
|
mode: string;
|
|
46
|
+
axis: {
|
|
47
|
+
$if: (string | {
|
|
48
|
+
$eq: string[];
|
|
49
|
+
})[];
|
|
50
|
+
};
|
|
42
51
|
};
|
|
43
52
|
})[] | (string | any[] | {
|
|
44
53
|
class: string;
|
|
@@ -63,6 +72,12 @@ export declare const projectRules: ({
|
|
|
63
72
|
})[] | {
|
|
64
73
|
class: string;
|
|
65
74
|
$if?: undefined;
|
|
75
|
+
} | {
|
|
76
|
+
class?: undefined;
|
|
77
|
+
$if: (string | (string | {
|
|
78
|
+
class: string;
|
|
79
|
+
role: string;
|
|
80
|
+
})[])[];
|
|
66
81
|
} | {
|
|
67
82
|
class?: undefined;
|
|
68
83
|
$if: ((string | (string | {
|
|
@@ -94,24 +109,6 @@ export declare const projectRules: ({
|
|
|
94
109
|
})[];
|
|
95
110
|
$eq?: undefined;
|
|
96
111
|
})[];
|
|
97
|
-
})[] | (string | (string | {
|
|
98
|
-
class: string;
|
|
99
|
-
type: string;
|
|
100
|
-
on: {
|
|
101
|
-
click: string;
|
|
102
|
-
};
|
|
103
|
-
})[] | (string | any[] | {
|
|
104
|
-
class: string;
|
|
105
|
-
role: string;
|
|
106
|
-
'aria-label': string;
|
|
107
|
-
})[] | (string | {
|
|
108
|
-
$apply: string;
|
|
109
|
-
}[] | (string | {
|
|
110
|
-
class: string;
|
|
111
|
-
})[] | {
|
|
112
|
-
class: string;
|
|
113
|
-
})[] | {
|
|
114
|
-
class: string;
|
|
115
112
|
})[] | (string | (string | {
|
|
116
113
|
class: string;
|
|
117
114
|
rows: number;
|
|
@@ -167,6 +164,33 @@ export declare const projectRules: ({
|
|
|
167
164
|
role: string;
|
|
168
165
|
})[])[];
|
|
169
166
|
class?: undefined;
|
|
167
|
+
})[] | (string | (string | {
|
|
168
|
+
class: string;
|
|
169
|
+
type: string;
|
|
170
|
+
'aria-pressed': {
|
|
171
|
+
$if: string[];
|
|
172
|
+
};
|
|
173
|
+
on: {
|
|
174
|
+
click: string;
|
|
175
|
+
};
|
|
176
|
+
})[] | (string | {
|
|
177
|
+
class: string;
|
|
178
|
+
type: string;
|
|
179
|
+
on: {
|
|
180
|
+
click: string;
|
|
181
|
+
};
|
|
182
|
+
})[] | (string | any[] | {
|
|
183
|
+
class: string;
|
|
184
|
+
role: string;
|
|
185
|
+
'aria-label': string;
|
|
186
|
+
})[] | (string | {
|
|
187
|
+
$apply: string;
|
|
188
|
+
}[] | (string | {
|
|
189
|
+
class: string;
|
|
190
|
+
})[] | {
|
|
191
|
+
class: string;
|
|
192
|
+
})[] | {
|
|
193
|
+
class: string;
|
|
170
194
|
})[] | {
|
|
171
195
|
class: string;
|
|
172
196
|
'data-mode': string;
|
package/docs/PROJECT-FORMAT.md
CHANGED
|
@@ -72,6 +72,16 @@ than one name).
|
|
|
72
72
|
autorun: boolean }`, defaulted to `{ classic, 0.5, true }`. It rides the
|
|
73
73
|
share link and the eject, so its shape is fixed at v0.1.
|
|
74
74
|
|
|
75
|
+
The IDE honours `autorun`: when false, edits keep the last committed stage
|
|
76
|
+
until **Run** is pressed. The toolbar toggle changes the saved layout.
|
|
77
|
+
The splitter resizes the editor horizontally in `classic`/`right` and
|
|
78
|
+
vertically in `top`; pointer cancellation restores the previous ratio.
|
|
79
|
+
|
|
80
|
+
**Download** exports the complete `jaren-project` envelope, including every
|
|
81
|
+
file and the active file/layout, and works for projects without an app.
|
|
82
|
+
**App JSON** separately exports the designated app document and reports
|
|
83
|
+
when none exists. A runnable offline folder/ZIP is a future export format.
|
|
84
|
+
|
|
75
85
|
## `classifyChange` — reboot vs. hot-update
|
|
76
86
|
|
|
77
87
|
`classifyChange(prev, next)` reports, **per artifact**, whether a change
|
|
@@ -109,8 +119,8 @@ Still open, and tracked with their constraints in
|
|
|
109
119
|
validate but have no editor or runner, so they cannot be added from the
|
|
110
120
|
IDE; fragment assembly (one artifact from several files) is unbuilt;
|
|
111
121
|
the assistant authors files as free-form tool arguments rather than under
|
|
112
|
-
constrained decoding;
|
|
113
|
-
|
|
114
|
-
|
|
122
|
+
constrained decoding; and a runnable offline `.zip` eject is unbuilt.
|
|
123
|
+
The stage displays the nested app's latest boot/runtime failure and clears
|
|
124
|
+
it on restart. Syntax highlighting stays a
|
|
115
125
|
non-goal — the editor is a plain `<textarea>` so the whole IDE remains a
|
|
116
126
|
JSLT document with no imperative chrome.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarenjs/studio",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.72.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -59,12 +59,12 @@
|
|
|
59
59
|
"prepack": "npm run build:types"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@jarenjs/core": "^0.
|
|
63
|
-
"@jarenjs/validate": "^0.
|
|
64
|
-
"@jarenjs/json": "^0.
|
|
65
|
-
"@jarenjs/app": "^0.
|
|
66
|
-
"@jarenjs/flow": "^0.
|
|
67
|
-
"@jarenjs/db": "^0.
|
|
68
|
-
"@jarenjs/contract": "^0.
|
|
62
|
+
"@jarenjs/core": "^0.72.2",
|
|
63
|
+
"@jarenjs/validate": "^0.72.2",
|
|
64
|
+
"@jarenjs/json": "^0.72.2",
|
|
65
|
+
"@jarenjs/app": "^0.72.2",
|
|
66
|
+
"@jarenjs/flow": "^0.72.2",
|
|
67
|
+
"@jarenjs/db": "^0.72.2",
|
|
68
|
+
"@jarenjs/contract": "^0.72.2"
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"properties": {
|
|
24
24
|
"name": { "type": "string", "minLength": 1 },
|
|
25
25
|
"kind": {
|
|
26
|
-
"enum": ["app", "jslt", "query", "state", "data", "schema", "fsm", "dag", "model"]
|
|
26
|
+
"enum": ["app", "jslt", "query", "state", "data", "schema", "fsm", "dag", "model", "contract"]
|
|
27
27
|
},
|
|
28
28
|
"text": { "type": "string" }
|
|
29
29
|
}
|
package/src/component/view.js
CHANGED
|
@@ -75,6 +75,10 @@ const shell = {
|
|
|
75
75
|
layoutButton('right', 'Swap', 'Stage beside the editor'),
|
|
76
76
|
layoutButton('top', 'Stack', 'Editor over the stage'),
|
|
77
77
|
],
|
|
78
|
+
['button', { class: 'btn small', type: 'button',
|
|
79
|
+
'aria-pressed': { $if: ['$.layout.autorun', 'true', 'false'] },
|
|
80
|
+
on: { click: 'project/autorun' },
|
|
81
|
+
}, 'Autorun'],
|
|
78
82
|
['button', { class: 'btn small', type: 'button', on: { click: 'project/run' } }, 'Run'],
|
|
79
83
|
],
|
|
80
84
|
// ——— file rail ———
|
|
@@ -132,15 +136,16 @@ const shell = {
|
|
|
132
136
|
// ——— splitter (a pointer-capture widget; its host IS the grab bar) ———
|
|
133
137
|
['jaren-widget', {
|
|
134
138
|
name: 'studio-splitter', class: 'js-split',
|
|
135
|
-
role: 'separator', 'aria-orientation': 'vertical',
|
|
139
|
+
role: 'separator', 'aria-orientation': { $if: [{ $eq: ['$.layout.mode', 'top'] }, 'horizontal', 'vertical'] },
|
|
136
140
|
'aria-label': 'Resize the editor and stage',
|
|
137
141
|
'aria-valuemin': '10', 'aria-valuemax': '90', 'aria-valuenow': '$.ratioPct',
|
|
138
142
|
tabindex: '0',
|
|
139
|
-
props: { ratio: '$.layout.ratio', mode: '$.layout.mode' },
|
|
143
|
+
props: { ratio: '$.layout.ratio', mode: '$.layout.mode', axis: { $if: [{ $eq: ['$.layout.mode', 'top'] }, 'y', 'x'] } },
|
|
140
144
|
}],
|
|
141
145
|
// ——— stage ———
|
|
142
146
|
['div', { class: 'js-stage' },
|
|
143
147
|
['div', { class: 'js-stage-head' }, 'Stage'],
|
|
148
|
+
{ $if: ['$.stageError', ['div', { class: 'js-stage-error js-stage-fail', role: 'status' }, '$.stageError'], ''] },
|
|
144
149
|
{ $if: [{ $eq: ['$.stage.kind', 'app'] },
|
|
145
150
|
['div', { class: 'js-stage-mount' }, ['jaren-widget', { name: 'studio-stage', props: '$.stage.mount' }]],
|
|
146
151
|
{ $if: [{ $eq: ['$.stage.kind', 'result'] },
|
|
@@ -143,6 +143,7 @@ export function projectViewModel(state, options = {}) {
|
|
|
143
143
|
problems,
|
|
144
144
|
problemCount: problems.length,
|
|
145
145
|
stage: deriveStage(project, activeMeta, results, revision, committed),
|
|
146
|
+
stageError: slice.stageError ?? null,
|
|
146
147
|
saveState: (slice.dirty === true || reconciled.dirty) ? 'Unsaved ●' : 'Saved',
|
|
147
148
|
// the phone pane (Files · Editor · Stage). This is host chrome, not a
|
|
148
149
|
// project member: `layout` travels with the saved document, which pane
|
package/styles/studio.css
CHANGED
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
.jstudio[data-mode="right"] { grid-template-areas: "penbar penbar penbar penbar" "rail stage split editor"; }
|
|
29
29
|
.jstudio[data-mode="top"] {
|
|
30
30
|
grid-template-columns: 11rem minmax(0, 1fr);
|
|
31
|
-
grid-template-areas: "penbar penbar" "rail editor" "rail stage";
|
|
32
|
-
grid-template-rows: auto minmax(0,
|
|
31
|
+
grid-template-areas: "penbar penbar" "rail editor" "rail split" "rail stage";
|
|
32
|
+
grid-template-rows: auto minmax(0, var(--js-ratio-first, 0.5fr)) auto minmax(0, var(--js-ratio-rest, 0.5fr));
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
.js-penbar {
|
|
@@ -167,8 +167,12 @@
|
|
|
167
167
|
}
|
|
168
168
|
.js-split:hover::before, .js-split:focus-visible::before { background: var(--accent, #2563eb); }
|
|
169
169
|
.js-split:focus-visible { outline: none; }
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
.jstudio[data-mode="top"] .js-split {
|
|
171
|
+
justify-self: stretch; inline-size: auto; block-size: 10px; cursor: row-resize;
|
|
172
|
+
}
|
|
173
|
+
.jstudio[data-mode="top"] .js-split::before {
|
|
174
|
+
inline-size: 100%; block-size: 4px; margin-block: auto;
|
|
175
|
+
}
|
|
172
176
|
|
|
173
177
|
/* the phone pane switcher exists only below the breakpoint */
|
|
174
178
|
.js-panebar { display: none; }
|
|
@@ -183,8 +187,10 @@
|
|
|
183
187
|
@media (max-width: 1024px) {
|
|
184
188
|
.jstudio, .jstudio[data-mode="right"], .jstudio[data-mode="top"] {
|
|
185
189
|
grid-template-columns: minmax(0, 1fr);
|
|
186
|
-
grid-template-areas: "penbar" "panes" "
|
|
190
|
+
grid-template-areas: "penbar" "panes" "content";
|
|
191
|
+
grid-template-rows: auto auto minmax(0, 1fr);
|
|
187
192
|
}
|
|
193
|
+
.js-rail, .js-editor, .js-stage { grid-area: content; }
|
|
188
194
|
.js-panebar { display: flex; grid-area: panes; align-self: start; }
|
|
189
195
|
.js-panebar .seg-btn { flex: 1; }
|
|
190
196
|
.jstudio[data-pane="files"] .js-editor,
|