@maelstrom-co/react 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +75 -2
- package/dist/_testing.d.ts +13 -0
- package/dist/_testing.d.ts.map +1 -0
- package/dist/_testing.js +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6181 -0
- package/dist/lib/build-execute-action.d.ts +9 -0
- package/dist/lib/build-execute-action.d.ts.map +1 -0
- package/dist/lib/chart/chart.d.ts +14 -0
- package/dist/lib/chart/chart.d.ts.map +1 -0
- package/dist/lib/chart/error-boundary.d.ts +17 -0
- package/dist/lib/chart/error-boundary.d.ts.map +1 -0
- package/dist/lib/chart/loading.d.ts +14 -0
- package/dist/lib/chart/loading.d.ts.map +1 -0
- package/dist/lib/chart/motion/flip.d.ts +18 -0
- package/dist/lib/chart/motion/flip.d.ts.map +1 -0
- package/dist/lib/chart/motion/measure.d.ts +8 -0
- package/dist/lib/chart/motion/measure.d.ts.map +1 -0
- package/dist/lib/chart/motion/motion-config.d.ts +27 -0
- package/dist/lib/chart/motion/motion-config.d.ts.map +1 -0
- package/dist/lib/chart/motion/use-chart-motion.d.ts +7 -0
- package/dist/lib/chart/motion/use-chart-motion.d.ts.map +1 -0
- package/dist/lib/chart/motion/use-exiting-instances.d.ts +9 -0
- package/dist/lib/chart/motion/use-exiting-instances.d.ts.map +1 -0
- package/dist/lib/config-types.d.ts +29 -0
- package/dist/lib/config-types.d.ts.map +1 -0
- package/dist/lib/context.d.ts +42 -0
- package/dist/lib/context.d.ts.map +1 -0
- package/dist/lib/create-maelstrom.d.ts +39 -0
- package/dist/lib/create-maelstrom.d.ts.map +1 -0
- package/dist/lib/dynamic-vessel-types.d.ts +57 -0
- package/dist/lib/dynamic-vessel-types.d.ts.map +1 -0
- package/dist/lib/extension-types.d.ts +58 -0
- package/dist/lib/extension-types.d.ts.map +1 -0
- package/dist/lib/maelstrom-instance-types.d.ts +228 -0
- package/dist/lib/maelstrom-instance-types.d.ts.map +1 -0
- package/dist/lib/maelstrom-state-types.d.ts +30 -0
- package/dist/lib/maelstrom-state-types.d.ts.map +1 -0
- package/dist/lib/provider.d.ts +135 -0
- package/dist/lib/provider.d.ts.map +1 -0
- package/dist/lib/register-vessel.d.ts +13 -0
- package/dist/lib/register-vessel.d.ts.map +1 -0
- package/dist/lib/require-context.d.ts +9 -0
- package/dist/lib/require-context.d.ts.map +1 -0
- package/dist/lib/update-vessel.d.ts +21 -0
- package/dist/lib/update-vessel.d.ts.map +1 -0
- package/dist/lib/use-actions.d.ts +19 -0
- package/dist/lib/use-actions.d.ts.map +1 -0
- package/dist/lib/use-instance.d.ts +11 -0
- package/dist/lib/use-instance.d.ts.map +1 -0
- package/dist/lib/use-intent-submission.d.ts +8 -0
- package/dist/lib/use-intent-submission.d.ts.map +1 -0
- package/dist/lib/use-latest-ref.d.ts +4 -0
- package/dist/lib/use-latest-ref.d.ts.map +1 -0
- package/dist/lib/use-maelstrom.d.ts +7 -0
- package/dist/lib/use-maelstrom.d.ts.map +1 -0
- package/dist/lib/use-store-selector.d.ts +17 -0
- package/dist/lib/use-store-selector.d.ts.map +1 -0
- package/dist/lib/use-vessel-core.d.ts +18 -0
- package/dist/lib/use-vessel-core.d.ts.map +1 -0
- package/dist/lib/use-vessel.d.ts +7 -0
- package/dist/lib/use-vessel.d.ts.map +1 -0
- package/dist/lib/vessel-entry-types.d.ts +170 -0
- package/dist/lib/vessel-entry-types.d.ts.map +1 -0
- package/dist/lib/vessel.d.ts +10 -0
- package/dist/lib/vessel.d.ts.map +1 -0
- package/dist/lib/warn-once.d.ts +23 -0
- package/dist/lib/warn-once.d.ts.map +1 -0
- package/dist/warn-once-Cq9ShMdA.js +10 -0
- package/package.json +83 -4
- package/skills/maelstrom-react-sdk/SKILL.md +29 -0
- package/skills/maelstrom-react-sdk/references/common-tasks.md +146 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { ActionNames, ActionParams, ActionRunner, VariantNames } from '@maelstrom-co/client';
|
|
2
|
+
import { ActionName, InstanceId, VariantName, VesselDefinition, VesselId, VesselVariantDefinition } from '@maelstrom-co/protocol';
|
|
3
|
+
import { ComponentType } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Discriminated union of variant prop shapes for vessel `V`.
|
|
6
|
+
*
|
|
7
|
+
* For each variant `K` in `V`, contributes a member
|
|
8
|
+
* `{ variant: K } & V['variants'][K]['props']`. Components consume this
|
|
9
|
+
* to render different content per variant while preserving literal-type
|
|
10
|
+
* narrowing on the `variant` discriminant.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* function OrdersComponent({ variantProps }: { variantProps: VariantProps<typeof ordersVessel> }) {
|
|
15
|
+
* if (variantProps.variant === 'list') {
|
|
16
|
+
* // variantProps narrowed to the 'list' variant's props
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export type VariantProps<V extends VesselDefinition> = {
|
|
22
|
+
[K in VariantNames<V>]: {
|
|
23
|
+
variant: K;
|
|
24
|
+
} & V['variants'][K]['props'];
|
|
25
|
+
}[VariantNames<V>];
|
|
26
|
+
/** Typed props delivered to a vessel component */
|
|
27
|
+
export interface TypedVesselProps<V extends VesselDefinition> {
|
|
28
|
+
instanceId: InstanceId;
|
|
29
|
+
variantProps: VariantProps<V>;
|
|
30
|
+
executeAction: <N extends ActionNames<V>>(...args: ActionParams<V, N> extends undefined ? [name: N] : [name: N, params: ActionParams<V, N>]) => void;
|
|
31
|
+
}
|
|
32
|
+
/** Eager vessel entry — component is already loaded */
|
|
33
|
+
export interface VesselEntry<V extends VesselDefinition> {
|
|
34
|
+
vessel: V;
|
|
35
|
+
component: ComponentType<TypedVesselProps<V>>;
|
|
36
|
+
}
|
|
37
|
+
/** Lazy loader function for a vessel component */
|
|
38
|
+
export type LazyVesselComponentLoader<V extends VesselDefinition> = () => Promise<{
|
|
39
|
+
default: ComponentType<TypedVesselProps<V>>;
|
|
40
|
+
}>;
|
|
41
|
+
/** Lazy vessel entry — component is loaded on demand */
|
|
42
|
+
export interface LazyVesselEntry<V extends VesselDefinition> {
|
|
43
|
+
vessel: V;
|
|
44
|
+
component: LazyVesselComponentLoader<V>;
|
|
45
|
+
loadingComponent: ComponentType<{
|
|
46
|
+
vesselId: VesselId;
|
|
47
|
+
}>;
|
|
48
|
+
}
|
|
49
|
+
export type AnyVesselEntry<T extends VesselDefinition = any> = VesselEntry<T> | LazyVesselEntry<T>;
|
|
50
|
+
/** Discriminant: lazy entries carry a loadingComponent, eager ones don't. */
|
|
51
|
+
export declare function isLazyEntry(entry: AnyVesselEntry): entry is LazyVesselEntry<any>;
|
|
52
|
+
/** Extract vessel IDs from a tuple of vessel entries */
|
|
53
|
+
export type VesselIds<TVessels extends readonly AnyVesselEntry[]> = TVessels[number]['vessel']['id'];
|
|
54
|
+
/**
|
|
55
|
+
* Extract the Vessel definition type from a tuple of entries by its literal ID.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* type CalendarVessel = ExtractVesselByIdFromEntries<typeof entries, 'calendar'>;
|
|
59
|
+
*/
|
|
60
|
+
export type ExtractVesselByIdFromEntries<T extends readonly AnyVesselEntry[], Id extends VesselIds<T>> = Extract<T[number], {
|
|
61
|
+
vessel: {
|
|
62
|
+
id: Id;
|
|
63
|
+
};
|
|
64
|
+
}>['vessel'];
|
|
65
|
+
/**
|
|
66
|
+
* Pre-computed lookup mapping vessel IDs to their ActionRunner types.
|
|
67
|
+
* Avoids deep generic resolution at call sites (helps tsc --build inference).
|
|
68
|
+
*/
|
|
69
|
+
export type ActionRunnerLookup<T extends readonly AnyVesselEntry[]> = {
|
|
70
|
+
[E in T[number] as E['vessel']['id']]: ActionRunner<E['vessel']>;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* A vessel definition safe to hand to `m.updateVessel()` or `handle.update()`
|
|
74
|
+
* to republish `V`'s definition without remounting its component.
|
|
75
|
+
*
|
|
76
|
+
* `props` is the crash surface: the rendered component and the hook that
|
|
77
|
+
* feeds it read `props` straight off the store and hand it to the mounted
|
|
78
|
+
* component, so a shape drift throws at render time instead of failing to
|
|
79
|
+
* compile. `actions`, `enum` values, `description`, and `minSize` stay
|
|
80
|
+
* free-form — pinning them too would break the documented republish use
|
|
81
|
+
* case of rebuilding an action's `enum` from live data.
|
|
82
|
+
*
|
|
83
|
+
* `variants` is a `Record<string, ...>`, not a per-key mapped type over
|
|
84
|
+
* `VariantNames<V>`, because `Object.fromEntries` — the documented rebuild
|
|
85
|
+
* idiom — returns a plain index-signature type with no named keys at all.
|
|
86
|
+
* No object type with required named properties can ever accept that
|
|
87
|
+
* return value, regardless of how loosely those properties are typed, so
|
|
88
|
+
* the target has to be an index signature too. The cost: props are checked
|
|
89
|
+
* against the union of every registered variant's props, not the specific
|
|
90
|
+
* variant named at that key, so a value shaped like variant B's props
|
|
91
|
+
* passes at variant A's key. What this still catches is the actual crash —
|
|
92
|
+
* a shape that matches none of the vessel's registered variants.
|
|
93
|
+
*/
|
|
94
|
+
export type RepublishableVessel<V extends VesselDefinition> = VesselDefinition & {
|
|
95
|
+
id: V['id'];
|
|
96
|
+
variants: Record<string, VesselVariantDefinition & {
|
|
97
|
+
props: V['variants'][VariantNames<V>]['props'];
|
|
98
|
+
}>;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Payload type for `m.updateVessel({ id, ... })` — `Id` must be one of the
|
|
102
|
+
* vessel IDs declared in `createMaelstrom({ vessels })`, so a typo'd or
|
|
103
|
+
* runtime-only id fails to compile instead of silently skipping the
|
|
104
|
+
* `RepublishableVessel` shape check.
|
|
105
|
+
*
|
|
106
|
+
* `T` only knows the vessels declared in `createMaelstrom({ vessels })` —
|
|
107
|
+
* `registerVessel()` adds ids at runtime that never appear in `T`, so
|
|
108
|
+
* `m.updateVessel()` cannot name them. Republish a runtime-registered
|
|
109
|
+
* vessel through `handle.update()` on the handle `registerVessel()`
|
|
110
|
+
* returns instead — it is typed exactly to that call's inferred vessel
|
|
111
|
+
* definition, with no id lookup needed.
|
|
112
|
+
*/
|
|
113
|
+
export type UpdateVesselPayload<T extends readonly AnyVesselEntry[], Id extends VesselIds<T>> = RepublishableVessel<ExtractVesselByIdFromEntries<T, Id>> & {
|
|
114
|
+
id: Id;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Discriminates the recoverable ways `m.updateVessel()` / `handle.update()`
|
|
118
|
+
* can refuse a republish. See {@link UpdateVesselConflict} for the payload
|
|
119
|
+
* each code carries.
|
|
120
|
+
*/
|
|
121
|
+
export type UpdateVesselConflictCode = 'variant_dropped' | 'action_dropped' | 'batch_in_flight';
|
|
122
|
+
/**
|
|
123
|
+
* The recoverable reason a republish did not commit — returned as data by
|
|
124
|
+
* `m.updateVessel()` / `handle.update()`, never thrown.
|
|
125
|
+
*
|
|
126
|
+
* `'variant_dropped'` and `'action_dropped'` are ordinary, user-triggerable
|
|
127
|
+
* states, not programmer mistakes — for example a `detail` variant that
|
|
128
|
+
* only exists while its record does, and the user just deleted that
|
|
129
|
+
* record. `'batch_in_flight'` means a command batch was already queued or
|
|
130
|
+
* executing when the republish was attempted: CommandProcessor applies
|
|
131
|
+
* `set_layout` / `execute_actions` through an async queue, so the instance
|
|
132
|
+
* snapshot a conflict scan would read from is not yet trustworthy — that
|
|
133
|
+
* in-flight batch could still land an instance on a variant the republish
|
|
134
|
+
* is about to drop.
|
|
135
|
+
*
|
|
136
|
+
* Branch on `code`, not on `message` text, which this package is free to
|
|
137
|
+
* reword.
|
|
138
|
+
*/
|
|
139
|
+
export type UpdateVesselConflict = {
|
|
140
|
+
code: 'variant_dropped';
|
|
141
|
+
vesselId: VesselId;
|
|
142
|
+
instanceId: InstanceId;
|
|
143
|
+
variant: VariantName;
|
|
144
|
+
message: string;
|
|
145
|
+
} | {
|
|
146
|
+
code: 'action_dropped';
|
|
147
|
+
vesselId: VesselId;
|
|
148
|
+
instanceId: InstanceId;
|
|
149
|
+
variant: VariantName;
|
|
150
|
+
missingActionNames: readonly ActionName[];
|
|
151
|
+
message: string;
|
|
152
|
+
} | {
|
|
153
|
+
code: 'batch_in_flight';
|
|
154
|
+
vesselId: VesselId;
|
|
155
|
+
message: string;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Return type of `m.updateVessel()` and `handle.update()`.
|
|
159
|
+
*
|
|
160
|
+
* `ok: false` is an ordinary, user-triggerable outcome, not a bug report —
|
|
161
|
+
* check `result.conflict.code` and decide whether to retry, skip the
|
|
162
|
+
* republish, or surface a message.
|
|
163
|
+
*/
|
|
164
|
+
export type UpdateVesselResult = {
|
|
165
|
+
ok: true;
|
|
166
|
+
} | {
|
|
167
|
+
ok: false;
|
|
168
|
+
conflict: UpdateVesselConflict;
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=vessel-entry-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vessel-entry-types.d.ts","sourceRoot":"","sources":["../../src/lib/vessel-entry-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { VesselDefinition, VesselId } from '@maelstrom-co/protocol';
|
|
2
|
+
import { ComponentType } from 'react';
|
|
3
|
+
import { LazyVesselComponentLoader, LazyVesselEntry, TypedVesselProps, VesselEntry } from './vessel-entry-types.js';
|
|
4
|
+
/** Register a vessel with an eagerly-loaded component */
|
|
5
|
+
export declare function vessel<const V extends VesselDefinition>(definition: V, component: ComponentType<TypedVesselProps<V>>): VesselEntry<V>;
|
|
6
|
+
/** Register a vessel with a lazily-loaded component */
|
|
7
|
+
export declare function vessel<const V extends VesselDefinition>(definition: V, loader: LazyVesselComponentLoader<V>, loadingComponent: ComponentType<{
|
|
8
|
+
vesselId: VesselId;
|
|
9
|
+
}>): LazyVesselEntry<V>;
|
|
10
|
+
//# sourceMappingURL=vessel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vessel.d.ts","sourceRoot":"","sources":["../../src/lib/vessel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,OAAO,KAAK,EACV,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACZ,MAAM,yBAAyB,CAAC;AAEjC,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,gBAAgB,EACrD,UAAU,EAAE,CAAC,EACb,SAAS,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAC5C,WAAW,CAAC,CAAC,CAAC,CAAC;AAElB,uDAAuD;AACvD,wBAAgB,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,gBAAgB,EACrD,UAAU,EAAE,CAAC,EACb,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,EACpC,gBAAgB,EAAE,aAAa,CAAC;IAAE,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC,GACtD,eAAe,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface WarnOnceOptions {
|
|
2
|
+
enabled?: boolean;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Emits a console warning for the first enabled call for a key in this loaded
|
|
6
|
+
* module instance. Later enabled calls with the same key are no-ops, regardless
|
|
7
|
+
* of their message. Disabled calls neither emit a warning nor record the key.
|
|
8
|
+
* State is not shared across processes, realms, or separately loaded copies.
|
|
9
|
+
*/
|
|
10
|
+
export declare function warnOnce(key: string, message: string, options?: WarnOnceOptions): void;
|
|
11
|
+
/**
|
|
12
|
+
* Clears warning keys recorded by this loaded module instance.
|
|
13
|
+
*
|
|
14
|
+
* An empty-state reset is a no-op. After a reset, the next enabled
|
|
15
|
+
* {@link warnOnce} call for a previously recorded key emits again. The reset is
|
|
16
|
+
* local to this package copy in the current process and does not affect other
|
|
17
|
+
* processes, realms, or separately loaded copies. Application code receives
|
|
18
|
+
* neither warning-state function from the package root; tests can access only
|
|
19
|
+
* this reset through `@maelstrom-co/react/_testing`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resetWarnings(): void;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=warn-once.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warn-once.d.ts","sourceRoot":"","sources":["../../src/lib/warn-once.ts"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,eAAe,QAM1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,SAE5B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,85 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maelstrom-co/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "React bindings for Maelstrom: Provider, Chart, connectors, vessel definitions, and hooks for AI-orchestrated dynamic UI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"maelstrom",
|
|
7
|
+
"ai",
|
|
8
|
+
"llm",
|
|
9
|
+
"dynamic-ui",
|
|
10
|
+
"generative-ui",
|
|
11
|
+
"react",
|
|
12
|
+
"react-hooks",
|
|
13
|
+
"ui"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"module": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
"./package.json": "./package.json",
|
|
23
|
+
".": {
|
|
24
|
+
"@maelstrom-co/source": "./src/index.ts",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./_testing": {
|
|
30
|
+
"@maelstrom-co/source": "./src/_testing.ts",
|
|
31
|
+
"types": "./dist/_testing.d.ts",
|
|
32
|
+
"import": "./dist/_testing.js",
|
|
33
|
+
"default": "./dist/_testing.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"skills",
|
|
39
|
+
"!**/*.tsbuildinfo"
|
|
40
|
+
],
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "https://github.com/maelstrom-co/maelstrom.git",
|
|
44
|
+
"directory": "packages/react"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://maelstrom-ai.co",
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/maelstrom-co/maelstrom/issues"
|
|
49
|
+
},
|
|
50
|
+
"author": "Maelstrom (https://maelstrom-ai.co)",
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"registry": "https://registry.npmjs.org",
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@maelstrom-co/client": "0.1.1",
|
|
57
|
+
"@maelstrom-co/protocol": "0.1.1",
|
|
58
|
+
"@tanstack/react-store": "^0.9.2"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@sinonjs/fake-timers": "^15.1.1",
|
|
62
|
+
"@testing-library/react": "^16.3.1",
|
|
63
|
+
"happy-dom": "21.0.4"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"react": ">=18.0.0",
|
|
67
|
+
"react-dom": ">=18.0.0"
|
|
68
|
+
},
|
|
69
|
+
"nx": {
|
|
70
|
+
"targets": {
|
|
71
|
+
"typecheck": {
|
|
72
|
+
"command": "tsc -p tsconfig.lib.json --noEmit && tsc -p tsconfig.spec.json --noEmit",
|
|
73
|
+
"options": {
|
|
74
|
+
"cwd": "{projectRoot}"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"test": {
|
|
78
|
+
"command": "bun test",
|
|
79
|
+
"options": {
|
|
80
|
+
"cwd": "{projectRoot}"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: maelstrom-react-sdk
|
|
3
|
+
description: >-
|
|
4
|
+
Version-matched API guide for @maelstrom-co/react. Load when implementing or
|
|
5
|
+
reviewing Maelstrom React bindings and this package is installed; check the owning installed package manifest before relying on API names.
|
|
6
|
+
license: MIT
|
|
7
|
+
metadata:
|
|
8
|
+
author: Maelstrom
|
|
9
|
+
sdkPackage: '@maelstrom-co/react'
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Maelstrom React SDK
|
|
13
|
+
|
|
14
|
+
This guide is published inside its owning package. Before use, read the
|
|
15
|
+
installed package's `package.json` version as the version authority. If the guide
|
|
16
|
+
is not shipped by that exact installed package, do not rely on it: inspect the
|
|
17
|
+
installation's `exports`, declarations, source, and tests instead.
|
|
18
|
+
|
|
19
|
+
The installed public entrypoint exports `createMaelstrom`, `vessel`, and
|
|
20
|
+
`defineVessel`, and exposes the `ChartProps` and `MaelstromProviderProps` types.
|
|
21
|
+
Confirm names and call signatures against the installed entrypoint/declarations
|
|
22
|
+
before use; do not assume `MaelstromProvider` itself is a named export just
|
|
23
|
+
because that type exists. Keep framework-independent lifecycle and connection
|
|
24
|
+
logic in its owning SDK package; application data, authorization, and side
|
|
25
|
+
effects remain application-owned.
|
|
26
|
+
|
|
27
|
+
When registering a Vessel, wiring Provider/Chart, seeding a tiling first screen,
|
|
28
|
+
testing Chart in a DOM, or diagnosing bootstrap errors, read
|
|
29
|
+
[common tasks](references/common-tasks.md) before choosing the integration.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Register a read-only capability
|
|
2
|
+
|
|
3
|
+
Inspect the existing renderer and its data owner first. Keep incidental controls
|
|
4
|
+
inside the capability. This example registers one Variant without Actions; its
|
|
5
|
+
one-cell minimum is illustrative, not a measurement of your application's UI.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import type { EngineConnector } from '@maelstrom-co/client';
|
|
9
|
+
import { createMaelstrom, defineVessel, vessel } from '@maelstrom-co/react';
|
|
10
|
+
|
|
11
|
+
const status = defineVessel({
|
|
12
|
+
id: 'status',
|
|
13
|
+
name: 'Status',
|
|
14
|
+
description: 'Show the application status',
|
|
15
|
+
defaultVariant: 'summary',
|
|
16
|
+
variants: {
|
|
17
|
+
summary: { props: {}, minSize: { width: 1, height: 1 }, actions: [] },
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
function Status() {
|
|
22
|
+
return <section aria-label="Application status">Ready</section>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const m = createMaelstrom({ vessels: [vessel(status, Status)] });
|
|
26
|
+
|
|
27
|
+
export function StatusChart({ connector }: { connector: EngineConnector }) {
|
|
28
|
+
return <m.Provider connector={connector}><m.Chart /></m.Provider>;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Create the instance outside component rendering. Supply your application's
|
|
33
|
+
configured Connector. The instance owns `Provider` and `Chart`; these are not
|
|
34
|
+
standalone named package exports. Preserve a legacy path when migrating.
|
|
35
|
+
|
|
36
|
+
For Actions, keep authorization, confirmation, and effects in application-owned
|
|
37
|
+
handlers. For definition changes, preserve every existing Variant and Action;
|
|
38
|
+
inspect the returned update conflicts before deciding how to proceed.
|
|
39
|
+
|
|
40
|
+
## Seed a tiling first screen
|
|
41
|
+
|
|
42
|
+
Use this branch when a registered capability must appear before the first Engine
|
|
43
|
+
response. Keep the configured Connector and scope the Provider to the migrated
|
|
44
|
+
surface. Register the existing renderer statically; the Engine arranges Instances
|
|
45
|
+
of that renderer rather than generating runtime JSX.
|
|
46
|
+
Mount this surface in the application's sized Chart container.
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import type { EngineConnector } from '@maelstrom-co/client';
|
|
50
|
+
import {
|
|
51
|
+
InstanceId,
|
|
52
|
+
type TilingLayout,
|
|
53
|
+
VariantName,
|
|
54
|
+
VesselId,
|
|
55
|
+
tilingLeafToken,
|
|
56
|
+
} from '@maelstrom-co/protocol';
|
|
57
|
+
import { createMaelstrom, defineVessel, vessel } from '@maelstrom-co/react';
|
|
58
|
+
|
|
59
|
+
const status = defineVessel({
|
|
60
|
+
id: 'status',
|
|
61
|
+
name: 'Status',
|
|
62
|
+
description: 'Show the application status',
|
|
63
|
+
defaultVariant: 'summary',
|
|
64
|
+
variants: {
|
|
65
|
+
summary: { props: {}, minSize: { width: 1, height: 1 }, actions: [] },
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
function Status() {
|
|
70
|
+
return <section aria-label="Application status">Ready</section>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const m = createMaelstrom({ vessels: [vessel(status, Status)] });
|
|
74
|
+
const instanceId = InstanceId('status-main');
|
|
75
|
+
const initialLayout: TilingLayout = {
|
|
76
|
+
type: 'tiling',
|
|
77
|
+
tree: [tilingLeafToken(instanceId)],
|
|
78
|
+
instances: [{
|
|
79
|
+
instanceId,
|
|
80
|
+
vesselId: VesselId('status'),
|
|
81
|
+
variant: VariantName('summary'),
|
|
82
|
+
}],
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export function SeededStatusChart({ connector }: { connector: EngineConnector }) {
|
|
86
|
+
return (
|
|
87
|
+
<m.Provider connector={connector} layoutMode="tiling" initialLayout={initialLayout}>
|
|
88
|
+
<m.Chart />
|
|
89
|
+
</m.Provider>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Match each leaf to one seeded Instance, and each Instance to a registered Vessel
|
|
95
|
+
and declared Variant. `initialLayout` is captured on mount; use a new Provider
|
|
96
|
+
session when you need a different seed. Keep application data and effects with
|
|
97
|
+
their existing owners.
|
|
98
|
+
|
|
99
|
+
## Verify
|
|
100
|
+
|
|
101
|
+
Typecheck against this installation. Test the renderer and the scoped Provider
|
|
102
|
+
separately. Observe `connectionError`, `lastError`, and `lastResponse` through
|
|
103
|
+
`m.useMaelstrom()` when submitting intent. A resolved promise is not sufficient
|
|
104
|
+
evidence of success. Test real Engine selection separately from local rendering.
|
|
105
|
+
|
|
106
|
+
### Test Chart in a DOM
|
|
107
|
+
|
|
108
|
+
Before mounting `m.Chart`, configure the runner's DOM environment and provide
|
|
109
|
+
`ResizeObserver` in the test setup. jsdom does not supply layout or
|
|
110
|
+
`ResizeObserver`. For sizing or resize assertions, use a real browser with a
|
|
111
|
+
sized Chart container, or a controlled observer that emits meaningful container
|
|
112
|
+
`contentRect` dimensions. Verify the measured geometry as part of that test.
|
|
113
|
+
An inert test-only observer can support control or error tests; label their
|
|
114
|
+
layout behavior unverified. Keep that substitute in test setup and restore any
|
|
115
|
+
replaced globals during teardown.
|
|
116
|
+
|
|
117
|
+
For an intent-failure regression, inject a local test Connector that connects
|
|
118
|
+
successfully and rejects `process` with a known error. Render a probe inside the
|
|
119
|
+
same instance's Provider. Give it a button disabled until
|
|
120
|
+
`connectionStatus === 'connected'` and while `isProcessing`, and display
|
|
121
|
+
`connectionError` and `lastError` from that same `m.useMaelstrom()` call.
|
|
122
|
+
|
|
123
|
+
1. Register `afterEach` cleanup to unmount the rendered tree and restore test
|
|
124
|
+
observers, mocks, and timers, including when an assertion fails.
|
|
125
|
+
2. Use a bounded asynchronous assertion to wait for the connected state and the
|
|
126
|
+
enabled button before clicking. Treat a disabled button as a pending
|
|
127
|
+
precondition, rather than skipping the click.
|
|
128
|
+
3. Click once, then use a bounded asynchronous assertion to check the known
|
|
129
|
+
`lastError` and that processing ends. A resolved `processIntent` promise
|
|
130
|
+
alone does not distinguish success from failure.
|
|
131
|
+
4. For success tests, observe `lastResponse`, a clear `lastError`, and the
|
|
132
|
+
expected rendered capability. Include meaningful geometry when claiming
|
|
133
|
+
layout correctness.
|
|
134
|
+
|
|
135
|
+
With Testing Library, use `waitFor` with an explicit timeout, such as 1000 ms,
|
|
136
|
+
and an assertion that throws until the expected state appears. Let waits yield
|
|
137
|
+
to DOM updates and timers so a missing error fails within the bound.
|
|
138
|
+
|
|
139
|
+
## Troubleshoot
|
|
140
|
+
|
|
141
|
+
- Missing `MaelstromProvider`: use the configured instance's `Provider`.
|
|
142
|
+
- Invalid first-screen seed: only tiling mode supports `initialLayout`; seeded
|
|
143
|
+
Instances must name statically registered Vessels and legal Variants.
|
|
144
|
+
- Definition update conflict: retain the complete definition and the app's policy.
|
|
145
|
+
- Runtime source lookup: inspect `dist/index.js`. Declarations under `dist/lib/`
|
|
146
|
+
do not imply separate runtime JavaScript files at those paths.
|