api_binding_ui 0.0.0-stage → 1.0.0

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.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * API Binding Studio - Canonical Data Model and Simulation Engine
3
+ * Single source of truth for parameter mappings, live request resolution, and simulations.
4
+ */
5
+ import type { ActionContext, ApiBindingConfig, ApiBindingContext, ApiDefinition, BindingCall, BindingPurpose, ParamMapping, RequestPreviewItem, SampleNote, SimulationInput } from "../types";
6
+ import { isButtonId } from "./componentId";
7
+ export declare const CONFIG_VERSION = 1;
8
+ export declare const draftKey: (key: string) => string;
9
+ export declare const appliedKey: (key: string) => string;
10
+ export declare const fingerprint: (config: ApiBindingConfig) => string;
11
+ export declare const SUBMIT: string;
12
+ export declare const CANCEL: string;
13
+ export declare const CUSTOMER_PARAM = "customerIds";
14
+ export declare const newCallId: () => string;
15
+ export declare const definitionFor: (context: ApiBindingContext, api: string, method?: string) => ApiDefinition | undefined;
16
+ export declare const methodsFor: (context: ApiBindingContext, api: string) => string[];
17
+ export declare const apisOf: (context: ApiBindingContext) => string[];
18
+ export declare const fieldId: (name: string) => string;
19
+ export declare function reconcileCallParams(call: BindingCall, context: ApiBindingContext): BindingCall;
20
+ export declare function proposeConfig(context: ApiBindingContext): ApiBindingConfig;
21
+ export declare function reconcileConfig(config: ApiBindingConfig, context: ApiBindingContext): ApiBindingConfig;
22
+ export declare function migrateConfig(raw: unknown, context: ApiBindingContext): ApiBindingConfig | null;
23
+ export declare function callsFor(config: ApiBindingConfig, component?: string): BindingCall[];
24
+ export declare function changeCallTarget(call: BindingCall, api: string, method: string | undefined, context: ApiBindingContext): BindingCall;
25
+ export declare function droppedBy(call: BindingCall, api: string, method: string | undefined, context: ApiBindingContext): number;
26
+ export declare const populated: (call: BindingCall) => boolean;
27
+ export declare function changePurpose(call: BindingCall, purpose: BindingPurpose): BindingCall;
28
+ export declare function newCall(purpose: BindingPurpose, component: string): BindingCall;
29
+ export declare function moveCall(calls: BindingCall[], id: string, delta: -1 | 1): BindingCall[];
30
+ export declare function setParamSource(p: ParamMapping, source: string, gridId?: string): ParamMapping;
31
+ export declare const gridPaths: (context: ApiBindingContext) => string[];
32
+ export declare const componentLabel: (context: ApiBindingContext, id: string) => string;
33
+ export declare const endpointLabel: (call: Pick<BindingCall, "api" | "method">) => string;
34
+ export declare function callIssues(call: BindingCall, index: number, context: ApiBindingContext): string[];
35
+ export declare function issuesFor(config: ApiBindingConfig, context: ApiBindingContext): string[];
36
+ export declare function actionContext(context: ApiBindingContext, form: Record<string, string>, rows?: Record<string, unknown>[]): ActionContext;
37
+ export declare const snapshotForm: (context: ApiBindingContext) => {
38
+ [k: string]: string;
39
+ };
40
+ export declare function resolutionIssues(call: BindingCall, index: number, def: ApiDefinition | undefined, ctx: ActionContext): string[];
41
+ export declare function previewRequests(config: ApiBindingConfig, context: ApiBindingContext, ctx: ActionContext, filter?: (c: BindingCall) => boolean): RequestPreviewItem[];
42
+ export declare const isNoteContract: (def?: ApiDefinition) => boolean;
43
+ export declare function isSimulated(call: BindingCall, context: ApiBindingContext): boolean;
44
+ export declare function simulatorGaps(config: ApiBindingConfig, context: ApiBindingContext): string[];
45
+ export declare function simulationErrors(config: ApiBindingConfig, input: SimulationInput, customers: number): string[];
46
+ export declare const simulationForm: (input: SimulationInput) => Record<string, string>;
47
+ export declare function simulateSave(config: ApiBindingConfig, context: ApiBindingContext, input: SimulationInput, rows: Record<string, unknown>[], fail: boolean): {
48
+ notes: SampleNote[];
49
+ errors: string[];
50
+ requests: RequestPreviewItem[];
51
+ };
52
+ export declare function canApply(config: ApiBindingConfig, context: ApiBindingContext, verified: string | null): boolean;
53
+ export declare function fieldSummary(config: ApiBindingConfig, context: ApiBindingContext, name: string): {
54
+ from: string;
55
+ to: string;
56
+ };
57
+ export declare const isButton: typeof isButtonId;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Cross-window communication transport and state management for API Binding Studio.
3
+ */
4
+ import type { ApiBindingConfig, ApiBindingContext, BindingAppliedMessage, BindingContextMessage, BindingReadyMessage, BindingSelectionUpdateMessage } from "../types";
5
+ import { BINDING_APPLIED, BINDING_CHANNEL, BINDING_CONTEXT, BINDING_READY, BINDING_SELECTION_UPDATE } from "../types";
6
+ export declare const contextKey: (key: string) => string;
7
+ export declare function storeBindingContext(context: ApiBindingContext): void;
8
+ export declare function readBindingContext(key: string): ApiBindingContext | null;
9
+ export declare function validBindingContext(value: unknown, key: string): value is ApiBindingContext;
10
+ export interface OpenStudioOptions {
11
+ /** Base URL path for the route, defaults to `/api-binding` */
12
+ routeBase?: string;
13
+ /** Custom window features (e.g. `width=1200,height=800`) */
14
+ features?: string;
15
+ }
16
+ /**
17
+ * Opens or focuses an existing named tab for this binding key.
18
+ * Never resets active simulation or unapplied in-memory edits.
19
+ */
20
+ export declare function openBindingStudio(context: ApiBindingContext, options?: OpenStudioOptions): Window | null;
21
+ /**
22
+ * Notifies the opener and any open host tabs that the binding has been applied.
23
+ */
24
+ export declare function notifyApplied(key: string, config: ApiBindingConfig): void;
25
+ /**
26
+ * Allows the host window to update customer selection live without closing the child window.
27
+ */
28
+ export declare function notifySelectionUpdate(key: string, grid: {
29
+ id: string;
30
+ rows: Record<string, unknown>[];
31
+ }): void;
32
+ export declare const validContext: typeof validBindingContext;
33
+ export { BINDING_APPLIED, BINDING_CHANNEL, BINDING_CONTEXT, BINDING_READY, BINDING_SELECTION_UPDATE, type BindingAppliedMessage, type BindingContextMessage, type BindingReadyMessage, type BindingSelectionUpdateMessage, };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Type coercion and request construction for API Binding Studio.
3
+ */
4
+ import type { ActionContext, ApiParameter, ParamMapping, RequestParts } from "../types";
5
+ export type Scalar = string | number | boolean;
6
+ export declare function baseType(type: string): {
7
+ base: string;
8
+ array: boolean;
9
+ };
10
+ export declare function coerceScalar(text: string, base: string): Scalar | undefined;
11
+ export declare function coerce(text: string, type: string): Scalar | Scalar[] | undefined;
12
+ export declare const FREE_TEXT_SOURCE = "freeText";
13
+ export declare function resolveParam(p: ParamMapping, ctx: ActionContext): string | undefined;
14
+ export declare function buildRequest(mappings: ParamMapping[], ctx: ActionContext, spec: ApiParameter[]): RequestParts;
@@ -0,0 +1,6 @@
1
+ import type { ApiBindingConfig } from "../types";
2
+ export declare function useAppliedBinding(pageKey: string): {
3
+ appliedConfig: ApiBindingConfig | null;
4
+ isApplied: boolean;
5
+ appliedAt: string | null;
6
+ };
package/dist/index.css ADDED
@@ -0,0 +1,244 @@
1
+ /* src/styles/highradius-bridge.css */
2
+
3
+
4
+ /* src/styles/index.css */
5
+
6
+
7
+ /* src/styles/workspace.css */
8
+ .binding-workspace, .api-binding, .binding-v2 {
9
+ display: flex;
10
+ background: var(--ds-color-background, #fff);
11
+ color: var(--ds-color-foreground, #0f172a);
12
+ font-family: var(--ds-font-family-sans, sans-serif);
13
+ flex-direction: column;
14
+ height: 100vh;
15
+ }
16
+
17
+ .binding-workspace h1, .api-binding h1, .binding-v2 h1 {
18
+ font-size: var(--ds-font-size-2xl, 1.5rem);
19
+ font-weight: var(--ds-font-weight-bold, 700);
20
+ margin: 0;
21
+ }
22
+
23
+ .binding-workspace h2, .api-binding h2, .binding-v2 h2 {
24
+ font-size: var(--ds-font-size-lg, 1.125rem);
25
+ font-weight: var(--ds-font-weight-semibold, 600);
26
+ margin: 0;
27
+ }
28
+
29
+ .binding-workspace h3, .api-binding h3, .binding-v2 h3 {
30
+ font-size: var(--ds-font-size-base, .875rem);
31
+ font-weight: var(--ds-font-weight-semibold, 600);
32
+ margin: 0;
33
+ }
34
+
35
+ .binding-workspace p, .api-binding p, .binding-v2 p {
36
+ line-height: var(--ds-line-height-normal, 1.5);
37
+ margin: 0;
38
+ }
39
+
40
+ .binding-header, .binding-footer, .binding-v2-header, .binding-v2-footer {
41
+ padding: var(--ds-page-padding, 1rem 1.5rem);
42
+ display: flex;
43
+ gap: var(--ds-space-4, 1rem);
44
+ flex-wrap: wrap;
45
+ justify-content: space-between;
46
+ align-items: center;
47
+ }
48
+
49
+ .binding-header, .binding-v2-header {
50
+ border-bottom-width: var(--ds-screen-surface-border-width, 1px);
51
+ border-bottom-style: solid;
52
+ border-bottom-color: var(--ds-color-border, #e2e8f0);
53
+ }
54
+
55
+ .binding-body, .binding-v2-body {
56
+ overflow: auto;
57
+ position: relative;
58
+ padding: var(--ds-page-padding, 1rem 1.5rem);
59
+ flex: 1;
60
+ min-height: 0;
61
+ }
62
+
63
+ .binding-columns, .binding-v2-columns {
64
+ isolation: isolate;
65
+ display: flex;
66
+ gap: var(--ds-space-8, 2rem);
67
+ flex-wrap: wrap;
68
+ align-items: start;
69
+ }
70
+
71
+ .binding-main, .binding-v2-main {
72
+ flex-grow: 1;
73
+ flex-basis: var(--ds-dialog-form-min-width, 32rem);
74
+ padding-bottom: var(--ds-space-12, 3rem);
75
+ }
76
+
77
+ .binding-main, .binding-stack, .binding-v2-main, .binding-v2-stack {
78
+ display: flex;
79
+ gap: var(--ds-space-4, 1rem);
80
+ flex-direction: column;
81
+ min-width: 0;
82
+ }
83
+
84
+ .binding-section, .binding-v2-section {
85
+ padding-bottom: var(--ds-space-6, 1.5rem);
86
+ display: flex;
87
+ gap: var(--ds-space-4, 1rem);
88
+ border-bottom-width: var(--ds-screen-surface-border-width, 1px);
89
+ border-bottom-style: solid;
90
+ border-bottom-color: var(--ds-color-border, #e2e8f0);
91
+ flex-direction: column;
92
+ }
93
+
94
+ .binding-section-title, .binding-v2-section-title {
95
+ display: flex;
96
+ justify-content: space-between;
97
+ align-items: center;
98
+ gap: var(--ds-space-4, 1rem);
99
+ }
100
+
101
+ .binding-muted, .binding-v2-muted {
102
+ color: var(--ds-color-muted-foreground, #64748b);
103
+ font-size: var(--ds-font-size-sm, .8125rem);
104
+ }
105
+
106
+ .binding-preview, .binding-v2-preview {
107
+ flex-basis: var(--ds-dialog-min-width, 24rem);
108
+ position: sticky;
109
+ background: var(--ds-color-surface, #fff);
110
+ border-width: var(--ds-screen-surface-border-width, 1px);
111
+ border-style: solid;
112
+ border-color: var(--ds-color-border, #e2e8f0);
113
+ border-radius: var(--ds-radius-md, 6px);
114
+ padding: var(--ds-space-6, 1.5rem);
115
+ display: flex;
116
+ gap: var(--ds-space-4, 1rem);
117
+ flex-direction: column;
118
+ flex-grow: 0;
119
+ max-width: 100%;
120
+ top: 0;
121
+ }
122
+
123
+ .binding-panel, .binding-v2-panel {
124
+ position: absolute;
125
+ width: var(--ds-dialog-form-min-width, 32rem);
126
+ background: var(--ds-color-background, #fff);
127
+ border-left-width: var(--ds-screen-surface-border-width, 1px);
128
+ border-left-style: solid;
129
+ border-left-color: var(--ds-color-border, #e2e8f0);
130
+ box-shadow: var(--ds-shadow-md, 0 4px 6px -1px #0000001a);
131
+ padding: var(--ds-space-6, 1.5rem);
132
+ display: flex;
133
+ gap: var(--ds-space-6, 1.5rem);
134
+ z-index: var(--ds-focus-z-index, 50);
135
+ flex-direction: column;
136
+ max-width: 100%;
137
+ min-height: 100%;
138
+ top: 0;
139
+ right: 0;
140
+ }
141
+
142
+ .binding-details, .binding-v2-details {
143
+ display: flex;
144
+ gap: var(--ds-space-2, .5rem);
145
+ font-size: var(--ds-font-size-sm, .8125rem);
146
+ overflow-wrap: anywhere;
147
+ flex-direction: column;
148
+ }
149
+
150
+ .binding-details summary, .binding-v2-details summary {
151
+ cursor: pointer;
152
+ color: var(--ds-color-muted-foreground, #64748b);
153
+ }
154
+
155
+ .binding-footer, .binding-v2-footer {
156
+ border-top-width: var(--ds-screen-surface-border-width, 1px);
157
+ border-top-style: solid;
158
+ border-top-color: var(--ds-color-border, #e2e8f0);
159
+ background: var(--ds-color-background, #fff);
160
+ }
161
+
162
+ .binding-simulation, .binding-v2-simulation {
163
+ display: flex;
164
+ gap: var(--ds-space-4, 1rem);
165
+ flex-direction: column;
166
+ }
167
+
168
+ .binding-empty, .binding-v2-empty {
169
+ padding: var(--ds-space-12, 3rem);
170
+ margin: auto;
171
+ }
172
+
173
+ .binding-error, .binding-v2-error {
174
+ color: var(--ds-color-destructive, #ef4444);
175
+ }
176
+
177
+ .binding-stack-tight, .binding-v2-stack-tight {
178
+ display: flex;
179
+ align-items: flex-start;
180
+ gap: var(--ds-space-1, .25rem);
181
+ flex-direction: column;
182
+ }
183
+
184
+ .binding-list, .binding-v2-list {
185
+ padding-left: var(--ds-space-4, 1rem);
186
+ margin: 0;
187
+ }
188
+
189
+ .binding-panel-wide, .binding-v2-panel-wide {
190
+ width: var(--ds-dialog-width-large, 48rem);
191
+ overflow: auto;
192
+ }
193
+
194
+ .binding-call, .binding-v2-call {
195
+ display: flex;
196
+ gap: var(--ds-space-3, .75rem);
197
+ padding: var(--ds-space-4, 1rem);
198
+ border-width: var(--ds-screen-surface-border-width, 1px);
199
+ border-style: solid;
200
+ border-color: var(--ds-color-border, #e2e8f0);
201
+ border-radius: var(--ds-radius-md, 6px);
202
+ flex-direction: column;
203
+ min-width: 0;
204
+ }
205
+
206
+ .binding-call-grid, .binding-v2-call-grid {
207
+ display: grid;
208
+ grid-template-columns: repeat(auto-fill, minmax(var(--ds-menu-min-width, 12rem), 1fr));
209
+ gap: var(--ds-space-3, .75rem);
210
+ }
211
+
212
+ .binding-params, .binding-v2-params {
213
+ display: flex;
214
+ gap: var(--ds-space-2, .5rem);
215
+ flex-direction: column;
216
+ }
217
+
218
+ .binding-param, .binding-v2-param {
219
+ display: grid;
220
+ grid-template-columns: repeat(3, minmax(0, 1fr));
221
+ gap: var(--ds-space-3, .75rem);
222
+ overflow-wrap: anywhere;
223
+ align-items: start;
224
+ }
225
+
226
+ .binding-endpoint, .binding-v2-endpoint {
227
+ font-family: var(--ds-font-family-mono, monospace);
228
+ font-size: var(--ds-font-size-sm, .8125rem);
229
+ overflow-wrap: anywhere;
230
+ }
231
+
232
+ .binding-preview-parts, .binding-v2-preview-parts {
233
+ display: grid;
234
+ grid-template-columns: repeat(auto-fill, minmax(var(--ds-menu-min-width, 12rem), 1fr));
235
+ gap: var(--ds-space-3, .75rem);
236
+ }
237
+
238
+ .binding-pre, .binding-v2-pre {
239
+ font-family: var(--ds-font-family-mono, monospace);
240
+ font-size: var(--ds-font-size-sm, .8125rem);
241
+ white-space: pre-wrap;
242
+ overflow-wrap: anywhere;
243
+ margin: 0;
244
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * API Binding Studio - Public Package Entry Point
3
+ */
4
+ import "./styles/index.css";
5
+ export * from "./types";
6
+ export { CONFIG_VERSION, SUBMIT, CANCEL, CUSTOMER_PARAM, draftKey, appliedKey, fingerprint, newCallId, definitionFor, methodsFor, apisOf, fieldId, reconcileCallParams, proposeConfig, reconcileConfig, migrateConfig, callsFor, changeCallTarget, droppedBy, populated, changePurpose, newCall, moveCall, setParamSource, gridPaths, componentLabel, endpointLabel, callIssues, issuesFor, actionContext, snapshotForm, resolutionIssues, previewRequests, isNoteContract, isSimulated, simulatorGaps, simulationErrors, simulationForm, simulateSave, canApply, fieldSummary, isButton, } from "./core/model";
7
+ export { contextKey, storeBindingContext, readBindingContext, validBindingContext, validContext, openBindingStudio, notifyApplied, notifySelectionUpdate, type OpenStudioOptions, } from "./core/transport";
8
+ export { friendlyLabel, buildCatalogFromRegistry, type RawBindings, } from "./core/catalog";
9
+ export { FREE_TEXT_SOURCE, FREE_TEXT_OPTION, storageKey, storeSnapshot, readSnapshot, windowIds, gridPropertyPaths, contextComponents, sourceComponents, discoverFormComponents, discoverButtons, buildSnapshot, } from "./core/bindingContext";
10
+ export { componentId, isButtonId, parseComponentId, normalizeComponent, type ComponentDescriptor, } from "./core/componentId";
11
+ export { baseType, coerceScalar, coerce, resolveParam, buildRequest, type Scalar, } from "./core/valueCoercion";
12
+ export { useAppliedBinding } from "./hooks/useAppliedBinding";
13
+ export { BindApiButton, type BindApiButtonProps } from "./components/BindApiButton";
14
+ export { ApiBindingWorkspace, ApiBindingStudio, type ApiBindingWorkspaceProps } from "./components/ApiBindingWorkspace";
15
+ export { WorkspaceComponentsProvider, useWorkspaceComponents } from "./components/WorkspaceContext";
16
+ export { ApiMappings } from "./components/ApiMappings";
17
+ export { RequestPreview } from "./components/RequestPreview";
18
+ export { SimulationDialog } from "./components/SimulationDialog";
19
+ export { AppGrid, createActionColumn, type AppGridColDef, type AppGridProps } from "./components/ui/AppGrid";
20
+ export { Button, ButtonBar, ButtonGroup, type ButtonProps } from "./components/ui/Button";
21
+ export { Badge, type BadgeProps } from "./components/ui/Badge";
22
+ export { Banner, type BannerProps } from "./components/ui/Banner";
23
+ export { DetailCard, type DetailCardProps, type DetailCardField } from "./components/ui/Card";
24
+ export { Dialog, actionFormDialogTemplateV1, alertDialogTemplateV1, type DialogProps } from "./components/ui/Dialog";
25
+ export { Input, TextArea, Select, Checkbox, type InputProps, type TextAreaProps, type SelectProps, type CheckboxProps, type SelectOption } from "./components/ui/Input";
26
+ export * as Icons from "./components/ui/Icons";