@ouispec/bindings 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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -2
  3. package/dist/binding.d.ts +46 -0
  4. package/dist/binding.d.ts.map +1 -0
  5. package/dist/binding.js +51 -0
  6. package/dist/binding.js.map +1 -0
  7. package/dist/controls.d.ts +69 -0
  8. package/dist/controls.d.ts.map +1 -0
  9. package/dist/controls.js +334 -0
  10. package/dist/controls.js.map +1 -0
  11. package/dist/effect.d.ts +54 -0
  12. package/dist/effect.d.ts.map +1 -0
  13. package/dist/effect.js +88 -0
  14. package/dist/effect.js.map +1 -0
  15. package/dist/index.d.ts +26 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +25 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/interactive.d.ts +12 -0
  20. package/dist/interactive.d.ts.map +1 -0
  21. package/dist/interactive.js +21 -0
  22. package/dist/interactive.js.map +1 -0
  23. package/dist/jobs.d.ts +54 -0
  24. package/dist/jobs.d.ts.map +1 -0
  25. package/dist/jobs.js +74 -0
  26. package/dist/jobs.js.map +1 -0
  27. package/dist/json-schema.d.ts +36 -0
  28. package/dist/json-schema.d.ts.map +1 -0
  29. package/dist/json-schema.js +196 -0
  30. package/dist/json-schema.js.map +1 -0
  31. package/dist/jsx.d.ts +19 -0
  32. package/dist/jsx.d.ts.map +1 -0
  33. package/dist/jsx.js +2 -0
  34. package/dist/jsx.js.map +1 -0
  35. package/dist/manifest.d.ts +35 -0
  36. package/dist/manifest.d.ts.map +1 -0
  37. package/dist/manifest.js +77 -0
  38. package/dist/manifest.js.map +1 -0
  39. package/dist/oui.d.ts +112 -0
  40. package/dist/oui.d.ts.map +1 -0
  41. package/dist/oui.js +514 -0
  42. package/dist/oui.js.map +1 -0
  43. package/dist/package-declaration.d.ts +24 -0
  44. package/dist/package-declaration.d.ts.map +1 -0
  45. package/dist/package-declaration.js +24 -0
  46. package/dist/package-declaration.js.map +1 -0
  47. package/dist/react.d.ts +74 -0
  48. package/dist/react.d.ts.map +1 -0
  49. package/dist/react.js +179 -0
  50. package/dist/react.js.map +1 -0
  51. package/dist/registry.d.ts +103 -0
  52. package/dist/registry.d.ts.map +1 -0
  53. package/dist/registry.js +146 -0
  54. package/dist/registry.js.map +1 -0
  55. package/dist/room.d.ts +79 -0
  56. package/dist/room.d.ts.map +1 -0
  57. package/dist/room.js +111 -0
  58. package/dist/room.js.map +1 -0
  59. package/dist/tier2-react.d.ts +35 -0
  60. package/dist/tier2-react.d.ts.map +1 -0
  61. package/dist/tier2-react.js +186 -0
  62. package/dist/tier2-react.js.map +1 -0
  63. package/dist/tier2.d.ts +68 -0
  64. package/dist/tier2.d.ts.map +1 -0
  65. package/dist/tier2.js +129 -0
  66. package/dist/tier2.js.map +1 -0
  67. package/package.json +74 -3
package/dist/room.js ADDED
@@ -0,0 +1,111 @@
1
+ /**
2
+ * The room catalog contract (ADR-0220 §2.3): what a room with its own editing
3
+ * model — the vector studio, the video editor — declares about everything a
4
+ * person can do in it, so the assistant's actions and knowledge are generated
5
+ * from the room's code rather than written by hand.
6
+ *
7
+ * The declarations are the contract's (`room-catalog-data.json`), generated
8
+ * from its schema: what `agent-catalog.json` holds and a generator reads. This
9
+ * module adds what a room runs — each action's `run`, each field's `read` and
10
+ * `write` — and the catalog's two derived pieces: its `problems` schema and
11
+ * its data.
12
+ *
13
+ * - **actions**: its operations, each carried out through the room's own
14
+ * reducer and commands, with a JSON schema for the input;
15
+ * - **fields**: its inspector's fields, from the same definitions the
16
+ * inspector renders, each with its value's schema, unit, range, its
17
+ * animation and which kinds of thing it applies to;
18
+ * - **commands**: its keymap, each command with its keys and what it does;
19
+ * - **observations**: what a host reports about the room's state, including
20
+ * the problems it has drawing it.
21
+ */
22
+ /** Whether a field animates: its `animation`, or the `keyframeable` of a catalog written before it. */
23
+ export function isKeyframeable(field) {
24
+ return field.animation?.keyframeable ?? field.keyframeable ?? false;
25
+ }
26
+ /**
27
+ * The ids of a room's two generic actions, built from the rest of its
28
+ * catalog so they cannot fall behind it: one sets any of its fields (its
29
+ * input has one property per field, under `values`), one runs any available
30
+ * command. A room with fields declares the first; a room with available
31
+ * commands declares the second.
32
+ */
33
+ export const ROOM_SET_PROPERTIES_ID = 'set-properties';
34
+ export const ROOM_RUN_COMMAND_ID = 'run-command';
35
+ /** The id every room and page reports its problems under. */
36
+ export const PROBLEMS_OBSERVATION_ID = 'problems';
37
+ const PROBLEMS_DESCRIPTION = 'What is wrong that a person would see: what the page cannot show, load or do, as its banners and messages say it. ' +
38
+ 'Empty when nothing is wrong.';
39
+ /**
40
+ * The schema of a `problems` observation: a list of `RoomProblem`. Its kinds
41
+ * are the room's own when it declares them (`RoomCatalog.problems`).
42
+ */
43
+ export function problemsSchema(kinds = []) {
44
+ const listed = kinds.map(k => `${k.kind} = ${k.description}`).join('; ');
45
+ return {
46
+ type: 'array',
47
+ description: kinds.length ? `${PROBLEMS_DESCRIPTION} Its kinds: ${listed}.` : PROBLEMS_DESCRIPTION,
48
+ items: {
49
+ type: 'object',
50
+ properties: {
51
+ kind: {
52
+ type: 'string',
53
+ description: 'What kind of problem it is, in the page’s own vocabulary',
54
+ ...(kinds.length ? { enum: kinds.map(k => k.kind) } : {}),
55
+ },
56
+ message: { type: 'string', description: 'The words the page shows for it' },
57
+ hides: {
58
+ type: 'array',
59
+ items: { type: 'string' },
60
+ description: 'Ids of what is not shown because of it',
61
+ },
62
+ resolve: {
63
+ type: 'object',
64
+ description: 'The action that resolves it, and the choices it offers',
65
+ properties: { action: { type: 'string' }, choices: { type: 'array' } },
66
+ },
67
+ detail: { type: 'object' },
68
+ },
69
+ required: ['kind', 'message'],
70
+ },
71
+ };
72
+ }
73
+ /** The schema of a `problems` observation whose kinds are not declared: every page's. */
74
+ export const PROBLEMS_SCHEMA = problemsSchema();
75
+ /** The catalog's declarations, as `agent-catalog.json` holds them. Deterministic: entries keep the catalog's order. */
76
+ export function catalogData(catalog) {
77
+ return {
78
+ room: catalog.room,
79
+ title: catalog.title,
80
+ description: catalog.description,
81
+ actions: catalog.actions.map(a => ({
82
+ kind: a.kind,
83
+ id: a.id,
84
+ title: a.title,
85
+ description: a.description,
86
+ control: a.control,
87
+ input: a.input,
88
+ effect: a.effect,
89
+ ...(a.destructive ? { destructive: true } : {}),
90
+ })),
91
+ fields: catalog.fields.map(f => ({
92
+ kind: f.kind,
93
+ id: f.id,
94
+ title: f.title,
95
+ description: f.description,
96
+ control: f.control,
97
+ section: f.section,
98
+ appliesTo: [...f.appliesTo],
99
+ value: f.value,
100
+ // Every reader finds `animation`; a catalog written before it keeps its
101
+ // `keyframeable` too, for readers of that name during the transition.
102
+ ...(f.animation || f.keyframeable !== undefined ? { animation: { keyframeable: isKeyframeable(f) } } : {}),
103
+ ...(f.keyframeable !== undefined ? { keyframeable: f.keyframeable } : {}),
104
+ })),
105
+ commands: catalog.commands.map(c => ({ ...c, keys: [...c.keys] })),
106
+ observations: catalog.observations.map(o => ({ ...o })),
107
+ ...(catalog.problems ? { problems: catalog.problems.map(p => ({ ...p })) } : {}),
108
+ ...(catalog.recipes ? { recipes: catalog.recipes.map(r => ({ ...r, steps: [...r.steps] })) } : {}),
109
+ };
110
+ }
111
+ //# sourceMappingURL=room.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room.js","sourceRoot":"","sources":["../src/room.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { Tier2Control } from '@ouispec/contract';
2
+ import type { AgentProp, AgentSlots } from './binding.js';
3
+ /**
4
+ * What the bound module lets JSX pass as `agent`: a binding, a `nonAgent`
5
+ * reason, or a composite's slots (so a tier 1 composite's own `agent` type
6
+ * still fits beside it). The generator holds every `agent` to the control it
7
+ * is on.
8
+ */
9
+ export type AgentAttribute = AgentProp | AgentSlots<string>;
10
+ /**
11
+ * A bound control: the third-party `component`, registered under the
12
+ * mapping's `kind` with the app's own callback. `name` is its export path, for
13
+ * messages and its display name.
14
+ */
15
+ export declare function boundControl<C>(component: C, name: string, control: Tier2Control): C;
16
+ /**
17
+ * A compound control (Radix `Select.Root` / `Select.Item`, Mantine `Tabs` /
18
+ * `Tabs.Tab`): the bound root registers the mapping's kind, and its options
19
+ * are the items rendered under it, each reporting its `valueProp` and title
20
+ * while it is mounted. Each compound has its own registry, so an item finds
21
+ * its own root through any other compound between them.
22
+ */
23
+ export declare function boundCompound<R, I>(root: R, item: I, name: string, control: Tier2Control): {
24
+ root: R;
25
+ item: I;
26
+ };
27
+ /**
28
+ * A namespace or component with some members replaced by bound parts
29
+ * (`Select` with its `Root` and `Item`, or a bound `Tabs` with its `Tab`),
30
+ * every other member kept. A module namespace or a third-party component is
31
+ * never changed: a new object, or a pass-through component, carries the
32
+ * members.
33
+ */
34
+ export declare function withMembers<B>(base: B, members: Readonly<Record<string, unknown>>): B;
35
+ //# sourceMappingURL=tier2-react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2-react.d.ts","sourceRoot":"","sources":["../src/tier2-react.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAA8B,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAElF,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1D;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AA8E5D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,CAAC,CAOpF;AAOD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAiD/G;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAkBrF"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * The bound wrappers `oui generate` emits for a tier 2 mapping (ADR-0226
3
+ * §2.3) are built from these. Each wrapper accepts `agent`, registers the
4
+ * mapped kind with the app's own callback through `useAgentBinding`, returns
5
+ * that callback's result (§2.2 rule 3), reports the component's `disabled`
6
+ * prop, and renders the third-party component unchanged: its props, its ref,
7
+ * its static members.
8
+ *
9
+ * A bound export keeps the third-party component's own type, generics and
10
+ * polymorphism included (a wrapper type cannot add a prop to a generic call
11
+ * signature), and the bound module adds `agent` to JSX through
12
+ * `AgentAttribute`, the way a styling library adds `css`.
13
+ */
14
+ import { createContext, createElement, forwardRef, isValidElement, useContext, useEffect, useMemo, useRef, useState, } from 'react';
15
+ import { useAgentBinding } from './react.js';
16
+ import { mappedOptions, tier2CallbackArgs } from './tier2.js';
17
+ const BOUND = Symbol.for('oui.tier2.bound');
18
+ /** React's own members of a component, never copied from the third-party one. */
19
+ const REACT_MEMBERS = new Set(['$$typeof', 'render', 'type', 'compare', 'displayName', 'propTypes', 'defaultProps', 'contextTypes', 'prototype', 'length', 'name', 'caller', 'arguments']);
20
+ /** The visible text of rendered children, nested elements included. */
21
+ function textOf(node) {
22
+ if (typeof node === 'string' || typeof node === 'number')
23
+ return String(node);
24
+ if (Array.isArray(node))
25
+ return node.map(textOf).join(' ');
26
+ if (isValidElement(node))
27
+ return textOf(node.props.children);
28
+ return '';
29
+ }
30
+ /** The first non-empty title the named props give; `children` is the element's text. */
31
+ function titleOf(titleProps, props) {
32
+ for (const prop of titleProps ?? []) {
33
+ const value = prop === 'children' ? textOf(props.children) : props[prop];
34
+ if ((typeof value === 'string' || typeof value === 'number') && String(value).trim()) {
35
+ return String(value).replace(/\s+/g, ' ').trim();
36
+ }
37
+ }
38
+ return '';
39
+ }
40
+ /** The props a value schema is derived from, as the mapping names them, over its defaults. */
41
+ function schemaPropsOf(control, props, options) {
42
+ const out = { ...(control.defaults ?? {}) };
43
+ for (const [key, prop] of Object.entries(control.schemaProps ?? {})) {
44
+ if (typeof prop === 'string' && props[prop] !== undefined)
45
+ out[key] = props[prop];
46
+ }
47
+ if (options)
48
+ out.options = options;
49
+ return out;
50
+ }
51
+ /** One mapped control's binding, from the props the page gave it. */
52
+ function useMappedBinding(name, control, props, agent, items) {
53
+ const callback = control.callbacks[0];
54
+ const options = items ?? (control.options ? mappedOptions(control.options, props[control.options.prop]) : null);
55
+ useAgentBinding({
56
+ agent,
57
+ kind: control.kind,
58
+ title: titleOf(control.titleProps, props),
59
+ schemaProps: schemaPropsOf(control, props, options),
60
+ value: control.controlled ? props[control.controlled] : undefined,
61
+ disabled: props.disabled === true,
62
+ run: ({ value }) => {
63
+ const fn = props[callback];
64
+ if (typeof fn !== 'function') {
65
+ return { ok: false, code: 'NOT_WIRED', message: `${name} was given no ${callback}, so there is nothing for it to do` };
66
+ }
67
+ return fn(...tier2CallbackArgs(control, value));
68
+ },
69
+ });
70
+ }
71
+ /** Props with `agent` taken out, and the ref put back when there is one. */
72
+ function forwarded(rest, ref) {
73
+ return ref ? { ...rest, ref } : rest;
74
+ }
75
+ /** The wrapper named, marked as bound, with the third-party component's static members. */
76
+ function finish(wrapper, original, name) {
77
+ wrapper.displayName = `Bound${name.replace(/\./g, '')}`;
78
+ Object.defineProperty(wrapper, BOUND, { value: true });
79
+ if (original && (typeof original === 'object' || typeof original === 'function')) {
80
+ for (const key of Object.getOwnPropertyNames(original)) {
81
+ if (REACT_MEMBERS.has(key) || key in wrapper)
82
+ continue;
83
+ const descriptor = Object.getOwnPropertyDescriptor(original, key);
84
+ if (descriptor)
85
+ Object.defineProperty(wrapper, key, descriptor);
86
+ }
87
+ }
88
+ return wrapper;
89
+ }
90
+ /**
91
+ * A bound control: the third-party `component`, registered under the
92
+ * mapping's `kind` with the app's own callback. `name` is its export path, for
93
+ * messages and its display name.
94
+ */
95
+ export function boundControl(component, name, control) {
96
+ const Component = component;
97
+ const Bound = forwardRef(function Bound({ agent, ...rest }, ref) {
98
+ useMappedBinding(name, control, rest, agent, null);
99
+ return createElement(Component, forwarded(rest, ref));
100
+ });
101
+ return finish(Bound, component, name);
102
+ }
103
+ /**
104
+ * A compound control (Radix `Select.Root` / `Select.Item`, Mantine `Tabs` /
105
+ * `Tabs.Tab`): the bound root registers the mapping's kind, and its options
106
+ * are the items rendered under it, each reporting its `valueProp` and title
107
+ * while it is mounted. Each compound has its own registry, so an item finds
108
+ * its own root through any other compound between them.
109
+ */
110
+ export function boundCompound(root, item, name, control) {
111
+ const part = control.parts?.item;
112
+ if (!part)
113
+ throw new Error(`${name} has no item part: bind it with boundControl`);
114
+ const valueProp = part.valueProp ?? 'value';
115
+ const itemTitleProps = part.titleProps ?? ['children'];
116
+ const Items = createContext(null);
117
+ const RootComponent = root;
118
+ const ItemComponent = item;
119
+ const BoundRoot = forwardRef(function BoundRoot({ agent, ...rest }, ref) {
120
+ const entries = useRef(new Map());
121
+ const [version, setVersion] = useState(0);
122
+ const registry = useMemo(() => ({
123
+ set: (key, option) => {
124
+ const current = entries.current.get(key);
125
+ if (current && current.value === option.value && current.title === option.title && !!current.disabled === !!option.disabled)
126
+ return;
127
+ entries.current.set(key, option);
128
+ setVersion(v => v + 1);
129
+ },
130
+ delete: key => {
131
+ if (entries.current.delete(key))
132
+ setVersion(v => v + 1);
133
+ },
134
+ }), []);
135
+ // Recomputed on each registration (`version`), in the order the items mounted.
136
+ const items = useMemo(() => [...entries.current.values()], [version]);
137
+ useMappedBinding(name, control, rest, agent, items);
138
+ return createElement(Items.Provider, { value: registry }, createElement(RootComponent, forwarded(rest, ref)));
139
+ });
140
+ const BoundItem = forwardRef(function BoundItem(props, ref) {
141
+ const registry = useContext(Items);
142
+ const key = useRef({}).current;
143
+ const value = props[valueProp];
144
+ const title = titleOf(itemTitleProps, props) || (typeof value === 'string' || typeof value === 'number' ? String(value) : '');
145
+ const disabled = props.disabled === true;
146
+ useEffect(() => {
147
+ if (registry && (typeof value === 'string' || typeof value === 'number'))
148
+ registry.set(key, { value, title, ...(disabled ? { disabled } : {}) });
149
+ }, [registry, key, value, title, disabled]);
150
+ useEffect(() => () => registry?.delete(key), [registry, key]);
151
+ return createElement(ItemComponent, forwarded(props, ref));
152
+ });
153
+ return {
154
+ root: finish(BoundRoot, root, `${name}.root`),
155
+ item: finish(BoundItem, item, `${name}.item`),
156
+ };
157
+ }
158
+ /**
159
+ * A namespace or component with some members replaced by bound parts
160
+ * (`Select` with its `Root` and `Item`, or a bound `Tabs` with its `Tab`),
161
+ * every other member kept. A module namespace or a third-party component is
162
+ * never changed: a new object, or a pass-through component, carries the
163
+ * members.
164
+ */
165
+ export function withMembers(base, members) {
166
+ let target;
167
+ if (typeof base === 'function' || (base && typeof base === 'object' && '$$typeof' in base)) {
168
+ if (base[BOUND])
169
+ target = base;
170
+ else {
171
+ const Component = base;
172
+ const PassThrough = forwardRef(function PassThrough(props, ref) {
173
+ return createElement(Component, forwarded(props, ref));
174
+ });
175
+ target = finish(PassThrough, base, 'Namespace');
176
+ }
177
+ }
178
+ else {
179
+ target = { ...base };
180
+ }
181
+ for (const [key, value] of Object.entries(members)) {
182
+ Object.defineProperty(target, key, { value, enumerable: true, configurable: true, writable: true });
183
+ }
184
+ return target;
185
+ }
186
+ //# sourceMappingURL=tier2-react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2-react.js","sourceRoot":"","sources":["../src/tier2-react.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tier 2 (ADR-0226 §2.3): what a mapping of a third-party design system
3
+ * means, as the generator reads it and the bound wrappers run it.
4
+ *
5
+ * - `tier2ControlTable`: the control table a mapping makes, which the bound
6
+ * module ships and the generator reads exactly as it reads a tier 1 table.
7
+ * - `tier2Parts`: where a control's root and items are exported.
8
+ * - `mappedOptions`: a control's options from the prop its mapping names.
9
+ * - `tier2CallbackArgs`: the arguments the app's callback gets when the
10
+ * assistant sets a value, built from `valueFrom`.
11
+ *
12
+ * Pure and dependency-free: the generator reads it in plain Node, and the
13
+ * React wrappers (`@ouispec/bindings/react`) run the same code.
14
+ */
15
+ import type { ControlDescriptor, ControlOption, ControlTableFile, OptionsSource, Tier2Control, Tier2Mapping } from '@ouispec/contract';
16
+ /** Whether a mapped control's binding runs with a value. */
17
+ export declare function tier2TakesValue(control: Tier2Control): boolean;
18
+ /**
19
+ * Where a mapped control is exported: its root (the export that takes the
20
+ * callbacks; the control's own name when it has no parts) and, for a compound
21
+ * control, its item. Each is an export of the package or one member of one.
22
+ */
23
+ export declare function tier2Parts(name: string, control: Tier2Control): {
24
+ root: string;
25
+ item?: string;
26
+ };
27
+ /**
28
+ * How the generator reads one mapped control where a page uses it: its
29
+ * mapping as a control table entry. A tabs or dialog control whose mapping
30
+ * names the prop that shows it is a container of that state, as a tier 1
31
+ * table declares one, so what it shows is reached through it.
32
+ */
33
+ export declare function tier2Descriptor(control: Tier2Control): ControlDescriptor;
34
+ /** The control table a mapping makes: one entry per mapped control, under its name. */
35
+ export declare function tier2ControlTable(mapping: Tier2Mapping): ControlTableFile;
36
+ /**
37
+ * A control's options from the value of the prop its mapping names: each
38
+ * entry an object with the named value and title keys, a string or number
39
+ * (its own title), or a group (an object with an `items` array of entries,
40
+ * and no value of its own). `null` when any entry cannot be read, so a
41
+ * schema is never narrower than the control.
42
+ */
43
+ export declare function mappedOptions(source: OptionsSource, raw: unknown): ControlOption[] | null;
44
+ /**
45
+ * What a binding hands a callback where the third-party component would hand
46
+ * it an event: shaped like one, so a handler that calls `preventDefault`
47
+ * runs, and `isTrusted: false`, as for any event a script makes.
48
+ */
49
+ export interface AgentEvent {
50
+ readonly type: 'oui-agent';
51
+ readonly isTrusted: false;
52
+ readonly defaultPrevented: boolean;
53
+ preventDefault(): void;
54
+ stopPropagation(): void;
55
+ persist(): void;
56
+ [key: string]: unknown;
57
+ }
58
+ /** A fresh event-shaped argument (`AgentEvent`). */
59
+ export declare function agentEvent(): AgentEvent;
60
+ /**
61
+ * The arguments the app's callback gets when the assistant runs a mapped
62
+ * control. A control that takes a value gets it where `valueFrom` says the
63
+ * third-party component puts it: at its argument position, or at `path`
64
+ * inside an event-shaped argument there; every argument before it is an
65
+ * event-shaped argument. A button or a dialog gets one event-shaped argument.
66
+ */
67
+ export declare function tier2CallbackArgs(control: Tier2Control, value: unknown): unknown[];
68
+ //# sourceMappingURL=tier2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2.d.ts","sourceRoot":"","sources":["../src/tier2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKvI,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE9D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAE/F;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAcxE;AAED,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,CAIzE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,IAAI,CA0BzF;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,cAAc,IAAI,IAAI,CAAC;IACvB,eAAe,IAAI,IAAI,CAAC;IACxB,OAAO,IAAI,IAAI,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,oDAAoD;AACpD,wBAAgB,UAAU,IAAI,UAAU,CAcvC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,CAsBlF"}
package/dist/tier2.js ADDED
@@ -0,0 +1,129 @@
1
+ /** The kinds that take no value, so their mapping needs no `valueFrom`. */
2
+ const VALUELESS = new Set(['button', 'dialog']);
3
+ /** Whether a mapped control's binding runs with a value. */
4
+ export function tier2TakesValue(control) {
5
+ return !VALUELESS.has(control.kind);
6
+ }
7
+ /**
8
+ * Where a mapped control is exported: its root (the export that takes the
9
+ * callbacks; the control's own name when it has no parts) and, for a compound
10
+ * control, its item. Each is an export of the package or one member of one.
11
+ */
12
+ export function tier2Parts(name, control) {
13
+ return { root: control.parts?.root.export ?? name, ...(control.parts?.item ? { item: control.parts.item.export } : {}) };
14
+ }
15
+ /**
16
+ * How the generator reads one mapped control where a page uses it: its
17
+ * mapping as a control table entry. A tabs or dialog control whose mapping
18
+ * names the prop that shows it is a container of that state, as a tier 1
19
+ * table declares one, so what it shows is reached through it.
20
+ */
21
+ export function tier2Descriptor(control) {
22
+ const container = control.controlled && (control.kind === 'tabs' || control.kind === 'dialog')
23
+ ? { container: { kind: control.kind, stateProp: control.controlled } }
24
+ : {};
25
+ return {
26
+ kind: control.kind,
27
+ callbacks: [...control.callbacks],
28
+ titleProps: [...(control.titleProps ?? [])],
29
+ ...(control.schemaProps ? { schemaProps: { ...control.schemaProps } } : {}),
30
+ ...(control.options ? { options: { ...control.options } } : {}),
31
+ ...(control.defaults ? { defaults: { ...control.defaults } } : {}),
32
+ ...container,
33
+ };
34
+ }
35
+ /** The control table a mapping makes: one entry per mapped control, under its name. */
36
+ export function tier2ControlTable(mapping) {
37
+ const table = {};
38
+ for (const [name, control] of Object.entries(mapping.controls))
39
+ table[name] = tier2Descriptor(control);
40
+ return table;
41
+ }
42
+ /**
43
+ * A control's options from the value of the prop its mapping names: each
44
+ * entry an object with the named value and title keys, a string or number
45
+ * (its own title), or a group (an object with an `items` array of entries,
46
+ * and no value of its own). `null` when any entry cannot be read, so a
47
+ * schema is never narrower than the control.
48
+ */
49
+ export function mappedOptions(source, raw) {
50
+ if (!Array.isArray(raw))
51
+ return null;
52
+ const out = [];
53
+ for (const entry of raw) {
54
+ if (typeof entry === 'string' || typeof entry === 'number') {
55
+ out.push({ value: entry, title: String(entry) });
56
+ continue;
57
+ }
58
+ if (!entry || typeof entry !== 'object')
59
+ return null;
60
+ const rec = entry;
61
+ const value = rec[source.value];
62
+ if (value === undefined && Array.isArray(rec.items)) {
63
+ const group = mappedOptions(source, rec.items);
64
+ if (!group)
65
+ return null;
66
+ out.push(...group);
67
+ continue;
68
+ }
69
+ if (typeof value !== 'string' && typeof value !== 'number')
70
+ return null;
71
+ const title = rec[source.title];
72
+ out.push({
73
+ value,
74
+ title: typeof title === 'string' && title.trim() ? title : String(value),
75
+ ...(rec.disabled === true ? { disabled: true } : {}),
76
+ });
77
+ }
78
+ return out;
79
+ }
80
+ /** A fresh event-shaped argument (`AgentEvent`). */
81
+ export function agentEvent() {
82
+ let prevented = false;
83
+ return {
84
+ type: 'oui-agent',
85
+ isTrusted: false,
86
+ get defaultPrevented() {
87
+ return prevented;
88
+ },
89
+ preventDefault() {
90
+ prevented = true;
91
+ },
92
+ stopPropagation() { },
93
+ persist() { },
94
+ };
95
+ }
96
+ /**
97
+ * The arguments the app's callback gets when the assistant runs a mapped
98
+ * control. A control that takes a value gets it where `valueFrom` says the
99
+ * third-party component puts it: at its argument position, or at `path`
100
+ * inside an event-shaped argument there; every argument before it is an
101
+ * event-shaped argument. A button or a dialog gets one event-shaped argument.
102
+ */
103
+ export function tier2CallbackArgs(control, value) {
104
+ if (!tier2TakesValue(control) || !control.valueFrom)
105
+ return [agentEvent()];
106
+ const { arg, path } = control.valueFrom;
107
+ const args = [];
108
+ for (let i = 0; i < arg; i++)
109
+ args.push(agentEvent());
110
+ if (!path) {
111
+ args.push(value);
112
+ return args;
113
+ }
114
+ const event = agentEvent();
115
+ const keys = path.split('.');
116
+ let node = event;
117
+ keys.forEach((key, i) => {
118
+ if (i === keys.length - 1)
119
+ node[key] = value;
120
+ else {
121
+ const next = {};
122
+ node[key] = next;
123
+ node = next;
124
+ }
125
+ });
126
+ args.push(event);
127
+ return args;
128
+ }
129
+ //# sourceMappingURL=tier2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tier2.js","sourceRoot":"","sources":["../src/tier2.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,77 @@
1
1
  {
2
2
  "name": "@ouispec/bindings",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "description": "Every UI capability declared once, in code (ADR-0220): the semantic binding on design-system controls, the room catalog contract, the generated manifest and knowledge, and the runtime registry that serves them as OUI surfaces",
5
+ "homepage": "https://github.com/wesreid/oui/tree/main/packages/bindings#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/wesreid/oui/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/wesreid/oui.git",
12
+ "directory": "packages/bindings"
13
+ },
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./react": {
25
+ "types": "./dist/react.d.ts",
26
+ "import": "./dist/react.js",
27
+ "default": "./dist/react.js"
28
+ },
29
+ "./oui": {
30
+ "types": "./dist/oui.d.ts",
31
+ "import": "./dist/oui.js",
32
+ "default": "./dist/oui.js"
33
+ },
34
+ "./jsx": {
35
+ "types": "./dist/jsx.d.ts",
36
+ "import": "./dist/jsx.js",
37
+ "default": "./dist/jsx.js"
38
+ }
39
+ },
40
+ "files": [
41
+ "README.md",
42
+ "dist"
43
+ ],
44
+ "sideEffects": false,
45
+ "peerDependencies": {
46
+ "react": "^18.0.0 || ^19.0.0"
47
+ },
48
+ "peerDependenciesMeta": {
49
+ "react": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "dependencies": {
54
+ "@ouispec/agent-events": "^0.1.1",
55
+ "oui-spec": "^0.7.0",
56
+ "@ouispec/contract": "^0.1.0"
57
+ },
58
+ "devDependencies": {
59
+ "@testing-library/react": "^16",
60
+ "@types/react": "^19.0.0",
61
+ "jsdom": "^26",
62
+ "react": "^19.0.0",
63
+ "react-dom": "^19.0.0",
64
+ "typescript": "^5.8.0",
65
+ "vitest": "^3.2.0"
66
+ },
67
+ "publishConfig": {
68
+ "access": "public",
69
+ "provenance": true
70
+ },
71
+ "scripts": {
72
+ "build": "tsc -p tsconfig.build.json",
73
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
74
+ "test": "vitest run",
75
+ "clean": "rm -rf dist"
76
+ }
6
77
  }