@tai42/studio-sdk 9.2.0 → 9.2.1
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.
|
@@ -5,10 +5,19 @@
|
|
|
5
5
|
* media-annotated schema renders the upload control instead; and when the form
|
|
6
6
|
* supplies a completion provider, the input is backed by argument autocomplete.
|
|
7
7
|
*
|
|
8
|
-
* `JqField` is
|
|
8
|
+
* `JqField` is reached through the SDK's own `./jq` re-export — the ONE
|
|
9
9
|
* `@tai42/jq-studio` instance the whole deployment shares — never from
|
|
10
10
|
* `@tai42/jq-studio` directly, which would bundle a second copy and orphan its
|
|
11
11
|
* worker (see the `jq` module doc-comment).
|
|
12
|
+
*
|
|
13
|
+
* That door is loaded LAZILY, through a dynamic `import('../jq')` behind
|
|
14
|
+
* {@link JqField}. The jq authoring door drags a heavy subgraph — the xyflow
|
|
15
|
+
* visual editor, a Web Worker entry, and a wasm engine chunk — that a form
|
|
16
|
+
* whose fields carry no `x-tai42-expression` annotation must never ship. A
|
|
17
|
+
* static import would pin that subgraph into every consumer that bundles the
|
|
18
|
+
* SDK (a host that externalises the SDK is unaffected either way); the dynamic
|
|
19
|
+
* import keeps it out of `schema-form`'s static graph and pulls it only when an
|
|
20
|
+
* annotated field actually mounts.
|
|
12
21
|
*/
|
|
13
22
|
import type { ReactNode } from 'react';
|
|
14
23
|
import type { ExpressionAnnotation, MediaUpload } from './classify';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-field.d.ts","sourceRoot":"","sources":["../../src/schema-form/string-field.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"string-field.d.ts","sourceRoot":"","sources":["../../src/schema-form/string-field.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AASvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAkBpE,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,WAAW,EACX,KAAK,EACL,MAAM,EACN,KAAK,EACL,UAAU,EACV,OAAO,EACP,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/B,UAAU,EAAE,oBAAoB,GAAG,SAAS,CAAC;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,GAAG,SAAS,CA+DZ"}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { Suspense, lazy, useCallback, useContext, useMemo, useState } from 'react';
|
|
3
3
|
import { CompletionInput } from '../components/completion-input';
|
|
4
4
|
import { Field } from '../components/field';
|
|
5
5
|
import { AlertTriangleIcon } from '../components/icons';
|
|
6
|
-
import { TextInput } from '../components/inputs';
|
|
6
|
+
import { TextInput, Textarea } from '../components/inputs';
|
|
7
7
|
import { errorMessage } from '../errors';
|
|
8
|
-
import { JqField } from '../jq';
|
|
9
8
|
import { CompletionProviderContext } from './context';
|
|
10
9
|
import { MediaField } from './media-field';
|
|
10
|
+
// The lazily-loaded jq door. Defining it at module scope (never inside a
|
|
11
|
+
// component) is what keeps the lazy component's identity stable across renders,
|
|
12
|
+
// so React resolves the chunk once and never re-suspends a mounted field. The
|
|
13
|
+
// `import('../jq')` here is a DYNAMIC import — the sole runtime edge from
|
|
14
|
+
// `schema-form` to the jq door — so the visual editor, worker, and wasm live in
|
|
15
|
+
// a split chunk that a non-annotated form never requests. The `type`-only
|
|
16
|
+
// import of `JqInputShapeDescriptor` above is erased at compile time and adds no
|
|
17
|
+
// such edge.
|
|
18
|
+
const JqField = lazy(async () => {
|
|
19
|
+
const { JqField } = await import('../jq');
|
|
20
|
+
return { default: JqField };
|
|
21
|
+
});
|
|
11
22
|
export function StringField({ heading, description, error, format, media, expression, argName, value, required, onChange, }) {
|
|
12
23
|
const completionProvider = useContext(CompletionProviderContext);
|
|
13
24
|
const current = typeof value === 'string' ? value : '';
|
|
@@ -78,12 +89,28 @@ function CompletionField({ argName, value, onChange, provider, }) {
|
|
|
78
89
|
* - `compact` — the form renders every sibling field with a visible label;
|
|
79
90
|
* the compact variant (visually-hidden label, icon-only door) is for dense
|
|
80
91
|
* host rows, which the schema form does not have.
|
|
92
|
+
*
|
|
93
|
+
* The door is code-split ({@link JqField} is a `lazy` component), so it mounts
|
|
94
|
+
* inside a `Suspense` boundary. Its fallback paints the resting shell —
|
|
95
|
+
* label/description/error chrome around the current value in a read-only
|
|
96
|
+
* multiline control — so the field holds its layout and keeps the value visible
|
|
97
|
+
* while the chunk resolves, and the swap to the live door does not flash.
|
|
81
98
|
*/
|
|
82
99
|
function JqExpressionField({ heading, description, error, expression, argName, value, onChange, }) {
|
|
83
100
|
// Memoised: the descriptor's identity feeds jq-studio's own memoisation, so a
|
|
84
101
|
// fresh object each keystroke would defeat it.
|
|
85
102
|
const shape = useMemo(() => expressionShape(expression, argName), [expression, argName]);
|
|
86
|
-
return (_jsx(JqField, { label: heading, description: description, error: error, shape: shape, multiline: true, value: value, onChange: onChange }));
|
|
103
|
+
return (_jsx(Suspense, { fallback: _jsx(JqExpressionFieldSkeleton, { heading: heading, description: description, error: error, value: value }), children: _jsx(JqField, { label: heading, description: description, error: error, shape: shape, multiline: true, value: value, onChange: onChange }) }));
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The resting shell shown while the jq door chunk loads. It mirrors the live
|
|
107
|
+
* door's footprint — the same label/description/error chrome wrapping a
|
|
108
|
+
* multiline control seeded with the current value — but the control is inert
|
|
109
|
+
* (read-only, `aria-busy`) because there is nothing to edit yet. Matching the
|
|
110
|
+
* footprint is what keeps the Suspense swap from shifting layout or flashing.
|
|
111
|
+
*/
|
|
112
|
+
function JqExpressionFieldSkeleton({ heading, description, error, value, }) {
|
|
113
|
+
return (_jsx(Field, { label: heading, description: description, error: error, children: _jsx(Textarea, { value: value, readOnly: true, "aria-busy": "true" }) }));
|
|
87
114
|
}
|
|
88
115
|
/**
|
|
89
116
|
* Map a classified expression annotation onto jq-studio's input-shape
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"string-field.js","sourceRoot":"","sources":["../../src/schema-form/string-field.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"string-field.js","sourceRoot":"","sources":["../../src/schema-form/string-field.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tai42/studio-sdk",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.1",
|
|
4
4
|
"description": "The Studio plugin contract, shared UI components, and hooks that every feature builds on.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "tai42 <oss@tai42.ai>",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"@radix-ui/react-tabs": "^1.1.16",
|
|
92
92
|
"@radix-ui/react-tooltip": "^1.2.11",
|
|
93
93
|
"@tai42/jq-studio": "^0.1.3",
|
|
94
|
-
"@tai42/api-client": "9.2.
|
|
94
|
+
"@tai42/api-client": "9.2.1"
|
|
95
95
|
},
|
|
96
96
|
"scripts": {
|
|
97
97
|
"build": "tsc -b tsconfig.build.json && node scripts/copy-assets.mjs",
|
|
@@ -5,25 +5,47 @@
|
|
|
5
5
|
* media-annotated schema renders the upload control instead; and when the form
|
|
6
6
|
* supplies a completion provider, the input is backed by argument autocomplete.
|
|
7
7
|
*
|
|
8
|
-
* `JqField` is
|
|
8
|
+
* `JqField` is reached through the SDK's own `./jq` re-export — the ONE
|
|
9
9
|
* `@tai42/jq-studio` instance the whole deployment shares — never from
|
|
10
10
|
* `@tai42/jq-studio` directly, which would bundle a second copy and orphan its
|
|
11
11
|
* worker (see the `jq` module doc-comment).
|
|
12
|
+
*
|
|
13
|
+
* That door is loaded LAZILY, through a dynamic `import('../jq')` behind
|
|
14
|
+
* {@link JqField}. The jq authoring door drags a heavy subgraph — the xyflow
|
|
15
|
+
* visual editor, a Web Worker entry, and a wasm engine chunk — that a form
|
|
16
|
+
* whose fields carry no `x-tai42-expression` annotation must never ship. A
|
|
17
|
+
* static import would pin that subgraph into every consumer that bundles the
|
|
18
|
+
* SDK (a host that externalises the SDK is unaffected either way); the dynamic
|
|
19
|
+
* import keeps it out of `schema-form`'s static graph and pulls it only when an
|
|
20
|
+
* annotated field actually mounts.
|
|
12
21
|
*/
|
|
13
22
|
import type { ReactNode } from 'react';
|
|
14
|
-
import { useCallback, useContext, useMemo, useState } from 'react';
|
|
23
|
+
import { Suspense, lazy, useCallback, useContext, useMemo, useState } from 'react';
|
|
15
24
|
|
|
16
25
|
import { CompletionInput } from '../components/completion-input';
|
|
17
26
|
import { Field } from '../components/field';
|
|
18
27
|
import { AlertTriangleIcon } from '../components/icons';
|
|
19
|
-
import { TextInput } from '../components/inputs';
|
|
28
|
+
import { TextInput, Textarea } from '../components/inputs';
|
|
20
29
|
import { errorMessage } from '../errors';
|
|
21
|
-
import {
|
|
30
|
+
import type { JqInputShapeDescriptor } from '../jq';
|
|
22
31
|
import type { ExpressionAnnotation, MediaUpload } from './classify';
|
|
23
32
|
import { CompletionProviderContext } from './context';
|
|
24
33
|
import { MediaField } from './media-field';
|
|
25
34
|
import type { CompletionProvider } from './SchemaForm';
|
|
26
35
|
|
|
36
|
+
// The lazily-loaded jq door. Defining it at module scope (never inside a
|
|
37
|
+
// component) is what keeps the lazy component's identity stable across renders,
|
|
38
|
+
// so React resolves the chunk once and never re-suspends a mounted field. The
|
|
39
|
+
// `import('../jq')` here is a DYNAMIC import — the sole runtime edge from
|
|
40
|
+
// `schema-form` to the jq door — so the visual editor, worker, and wasm live in
|
|
41
|
+
// a split chunk that a non-annotated form never requests. The `type`-only
|
|
42
|
+
// import of `JqInputShapeDescriptor` above is erased at compile time and adds no
|
|
43
|
+
// such edge.
|
|
44
|
+
const JqField = lazy(async () => {
|
|
45
|
+
const { JqField } = await import('../jq');
|
|
46
|
+
return { default: JqField };
|
|
47
|
+
});
|
|
48
|
+
|
|
27
49
|
export function StringField({
|
|
28
50
|
heading,
|
|
29
51
|
description,
|
|
@@ -191,6 +213,12 @@ function CompletionField({
|
|
|
191
213
|
* - `compact` — the form renders every sibling field with a visible label;
|
|
192
214
|
* the compact variant (visually-hidden label, icon-only door) is for dense
|
|
193
215
|
* host rows, which the schema form does not have.
|
|
216
|
+
*
|
|
217
|
+
* The door is code-split ({@link JqField} is a `lazy` component), so it mounts
|
|
218
|
+
* inside a `Suspense` boundary. Its fallback paints the resting shell —
|
|
219
|
+
* label/description/error chrome around the current value in a read-only
|
|
220
|
+
* multiline control — so the field holds its layout and keeps the value visible
|
|
221
|
+
* while the chunk resolves, and the swap to the live door does not flash.
|
|
194
222
|
*/
|
|
195
223
|
function JqExpressionField({
|
|
196
224
|
heading,
|
|
@@ -213,15 +241,51 @@ function JqExpressionField({
|
|
|
213
241
|
// fresh object each keystroke would defeat it.
|
|
214
242
|
const shape = useMemo(() => expressionShape(expression, argName), [expression, argName]);
|
|
215
243
|
return (
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
244
|
+
<Suspense
|
|
245
|
+
fallback={
|
|
246
|
+
<JqExpressionFieldSkeleton
|
|
247
|
+
heading={heading}
|
|
248
|
+
description={description}
|
|
249
|
+
error={error}
|
|
250
|
+
value={value}
|
|
251
|
+
/>
|
|
252
|
+
}
|
|
253
|
+
>
|
|
254
|
+
<JqField
|
|
255
|
+
label={heading}
|
|
256
|
+
description={description}
|
|
257
|
+
error={error}
|
|
258
|
+
shape={shape}
|
|
259
|
+
multiline
|
|
260
|
+
value={value}
|
|
261
|
+
onChange={onChange}
|
|
262
|
+
/>
|
|
263
|
+
</Suspense>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The resting shell shown while the jq door chunk loads. It mirrors the live
|
|
269
|
+
* door's footprint — the same label/description/error chrome wrapping a
|
|
270
|
+
* multiline control seeded with the current value — but the control is inert
|
|
271
|
+
* (read-only, `aria-busy`) because there is nothing to edit yet. Matching the
|
|
272
|
+
* footprint is what keeps the Suspense swap from shifting layout or flashing.
|
|
273
|
+
*/
|
|
274
|
+
function JqExpressionFieldSkeleton({
|
|
275
|
+
heading,
|
|
276
|
+
description,
|
|
277
|
+
error,
|
|
278
|
+
value,
|
|
279
|
+
}: {
|
|
280
|
+
heading: string;
|
|
281
|
+
description: string | undefined;
|
|
282
|
+
error: string | undefined;
|
|
283
|
+
value: string;
|
|
284
|
+
}): ReactNode {
|
|
285
|
+
return (
|
|
286
|
+
<Field label={heading} description={description} error={error}>
|
|
287
|
+
<Textarea value={value} readOnly aria-busy="true" />
|
|
288
|
+
</Field>
|
|
225
289
|
);
|
|
226
290
|
}
|
|
227
291
|
|