@frontmcp/ui 1.8.2 → 1.8.3

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/auth/index.js CHANGED
@@ -212,6 +212,24 @@ var currentNavigator = defaultNavigator;
212
212
  function setAuthNavigator(navigator) {
213
213
  currentNavigator = navigator ?? defaultNavigator;
214
214
  }
215
+ function hasDocument() {
216
+ return typeof document !== "undefined" && typeof document.createElement === "function" && !!document.body;
217
+ }
218
+ function submitAsForm(url, entries) {
219
+ const form = document.createElement("form");
220
+ form.method = "post";
221
+ form.action = url;
222
+ form.style.display = "none";
223
+ for (const [name, value] of entries) {
224
+ const input = document.createElement("input");
225
+ input.type = "hidden";
226
+ input.name = name;
227
+ input.value = value;
228
+ form.appendChild(input);
229
+ }
230
+ document.body.appendChild(form);
231
+ form.submit();
232
+ }
215
233
  async function submitFinish(formOrData, options = {}) {
216
234
  const state = options.state ?? getAuthFlow();
217
235
  if (!state.submitUrl) {
@@ -219,8 +237,16 @@ async function submitFinish(formOrData, options = {}) {
219
237
  }
220
238
  const method = state.submitMethod ?? DEFAULT_SUBMIT_METHOD;
221
239
  const entries = withControlFields(state, toEntries(formOrData), finishMarkers(state));
222
- const response = await dispatch(method, state.submitUrl, entries);
223
240
  const shouldNavigate = options.navigate ?? (typeof window !== "undefined" && !!window.location);
241
+ if (shouldNavigate && method === "GET") {
242
+ currentNavigator(buildGetUrl(state.submitUrl, entries));
243
+ return new Response(null, { status: 204 });
244
+ }
245
+ if (shouldNavigate && hasDocument()) {
246
+ submitAsForm(state.submitUrl, entries);
247
+ return new Response(null, { status: 204 });
248
+ }
249
+ const response = await dispatch(method, state.submitUrl, entries);
224
250
  if (shouldNavigate && response.redirected && response.url) {
225
251
  currentNavigator(response.url);
226
252
  }
@@ -34,10 +34,12 @@ export declare function getAddedItems<T = unknown>(name: string): T[];
34
34
  */
35
35
  export interface SubmitFinishOptions {
36
36
  /**
37
- * When true (the default in a real browser), a non-redirected/non-JSON HTML
38
- * response causes a full navigation to `response.url` (the OAuth code
39
- * redirect). Set false to suppress navigation and inspect the {@link Response}
40
- * yourself (used by tests and SPA-style pages).
37
+ * Submit as a real top-level navigation (the default in a browser): a POST is
38
+ * a form submission, a GET a navigation to the callback URL, and the browser
39
+ * follows the server's redirect to the client's `redirect_uri` itself. Set
40
+ * false to send the request with `fetch()` and inspect the {@link Response}
41
+ * yourself (SPA-style pages and tests); that request can't follow a redirect
42
+ * to another origin.
41
43
  */
42
44
  navigate?: boolean;
43
45
  /**
@@ -48,15 +50,16 @@ export interface SubmitFinishOptions {
48
50
  state?: AuthFlowState;
49
51
  }
50
52
  /**
51
- * How {@link submitFinish} performs a top-level navigation to the OAuth
52
- * redirect. Defaults to `window.location.assign`. Exposed so SPA-style pages
53
- * (and tests) can override it via {@link setAuthNavigator} without fighting a
54
- * non-configurable `window.location`.
53
+ * How {@link submitFinish} performs a top-level navigation (a GET submission,
54
+ * or following a redirect outside a browser). Defaults to
55
+ * `window.location.assign`. Exposed so SPA-style pages (and tests) can override
56
+ * it via {@link setAuthNavigator} without fighting a non-configurable
57
+ * `window.location`.
55
58
  */
56
59
  export type AuthNavigator = (url: string) => void;
57
60
  /**
58
- * Override the navigation function used to follow the OAuth redirect after a
59
- * successful {@link submitFinish}. Pass no argument to reset to the default
61
+ * Override the navigation function {@link submitFinish} uses for a GET
62
+ * submission. Pass no argument to reset to the default
60
63
  * (`window.location.assign`).
61
64
  */
62
65
  export declare function setAuthNavigator(navigator?: AuthNavigator): void;
@@ -65,17 +68,24 @@ export declare function setAuthNavigator(navigator?: AuthNavigator): void;
65
68
  * server's callback (`submitUrl`), carrying `pending_auth_id`, `csrf`, and the
66
69
  * slot's marker fields (e.g. `consent_submitted=1` for consent).
67
70
  *
68
- * On success the server responds with the OAuth redirect to the client's
69
- * `redirect_uri`; in a browser this helper follows it via a full navigation
70
- * unless {@link SubmitFinishOptions.navigate} is false.
71
+ * In a browser this is a real top-level navigation: a POST submits a form, a
72
+ * GET navigates to the callback URL. The page is replaced by the server's
73
+ * answer: the redirect to the client's `redirect_uri` (on another origin,
74
+ * which only the browser can follow under the page's CSP), or the page again
75
+ * with an error. The returned promise then resolves with an empty `204`
76
+ * {@link Response}, since the real one goes to the browser.
77
+ *
78
+ * With {@link SubmitFinishOptions.navigate} `false`, or outside a browser, the
79
+ * request is sent with `fetch()` and its {@link Response} returned (outside a
80
+ * browser a redirect it followed is then passed to the navigator).
71
81
  *
72
82
  * @param formOrData The developer's form/fields (identity inputs, selected
73
83
  * `tools`/`providers` checkboxes, etc.).
74
84
  * @param options Submit options. `options.state` lets a caller (e.g. the React
75
85
  * hooks) drive the submit from an explicit flow state instead of re-reading the
76
86
  * injected global; when omitted the injected `window.__FRONTMCP_AUTH__` is used.
77
- * @returns The raw {@link Response} (so callers can branch on a re-rendered
78
- * error page vs. a redirect).
87
+ * @returns An empty `204` response once a navigation has started, else the
88
+ * `fetch()` {@link Response}.
79
89
  */
80
90
  export declare function submitFinish(formOrData?: AuthFormInput, options?: SubmitFinishOptions): Promise<Response>;
81
91
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"auth-flow.d.ts","sourceRoot":"","sources":["../../../src/auth/vanilla/auth-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,aAAa,CAAC;AAgBrB;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,aAAa,CAS3C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,aAAa,GAAG,SAAS,CAO1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,CAG5D;AAwJD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAUlD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,YAAY,CAAC,UAAU,CAAC,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAenH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAarH"}
1
+ {"version":3,"file":"auth-flow.d.ts","sourceRoot":"","sources":["../../../src/auth/vanilla/auth-flow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,aAAa,EAEnB,MAAM,aAAa,CAAC;AAgBrB;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,aAAa,CAS3C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,aAAa,GAAG,SAAS,CAO1D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,CAG5D;AAwJD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAUlD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAEhE;AA4BD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,YAAY,CAAC,UAAU,CAAC,EAAE,aAAa,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwBnH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAarH"}
@@ -205,6 +205,24 @@ var currentNavigator = defaultNavigator;
205
205
  function setAuthNavigator(navigator) {
206
206
  currentNavigator = navigator ?? defaultNavigator;
207
207
  }
208
+ function hasDocument() {
209
+ return typeof document !== "undefined" && typeof document.createElement === "function" && !!document.body;
210
+ }
211
+ function submitAsForm(url, entries) {
212
+ const form = document.createElement("form");
213
+ form.method = "post";
214
+ form.action = url;
215
+ form.style.display = "none";
216
+ for (const [name, value] of entries) {
217
+ const input = document.createElement("input");
218
+ input.type = "hidden";
219
+ input.name = name;
220
+ input.value = value;
221
+ form.appendChild(input);
222
+ }
223
+ document.body.appendChild(form);
224
+ form.submit();
225
+ }
208
226
  async function submitFinish(formOrData, options = {}) {
209
227
  const state = options.state ?? getAuthFlow();
210
228
  if (!state.submitUrl) {
@@ -212,8 +230,16 @@ async function submitFinish(formOrData, options = {}) {
212
230
  }
213
231
  const method = state.submitMethod ?? DEFAULT_SUBMIT_METHOD;
214
232
  const entries = withControlFields(state, toEntries(formOrData), finishMarkers(state));
215
- const response = await dispatch(method, state.submitUrl, entries);
216
233
  const shouldNavigate = options.navigate ?? (typeof window !== "undefined" && !!window.location);
234
+ if (shouldNavigate && method === "GET") {
235
+ currentNavigator(buildGetUrl(state.submitUrl, entries));
236
+ return new Response(null, { status: 204 });
237
+ }
238
+ if (shouldNavigate && hasDocument()) {
239
+ submitAsForm(state.submitUrl, entries);
240
+ return new Response(null, { status: 204 });
241
+ }
242
+ const response = await dispatch(method, state.submitUrl, entries);
217
243
  if (shouldNavigate && response.redirected && response.url) {
218
244
  currentNavigator(response.url);
219
245
  }
@@ -15,7 +15,7 @@ export interface ModalProps {
15
15
  slotProps?: ModalSlotProps;
16
16
  children: React.ReactNode;
17
17
  }
18
- declare const StyledDialogTitle: import("@emotion/styled").StyledComponent<Pick<import("@mui/material/DialogTitle").DialogTitleOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "children" | "className" | "color" | "style" | "classes" | "sx" | "variant" | "align" | "gutterBottom" | "noWrap" | "variantMapping">, "id" | "children" | "onError" | "ref" | "content" | "key" | "slot" | "resource" | "className" | "hidden" | "color" | "style" | "title" | "dir" | "classes" | "sx" | "tabIndex" | "variant" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "enterKeyHint" | "lang" | "nonce" | "spellCheck" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "popover" | "popoverTargetAction" | "popoverTarget" | "inert" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onScrollEnd" | "onScrollEndCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onToggle" | "onBeforeToggle" | "onTransitionCancel" | "onTransitionCancelCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "onTransitionRun" | "onTransitionRunCapture" | "onTransitionStart" | "onTransitionStartCapture" | "align" | "gutterBottom" | "noWrap" | "variantMapping"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
18
+ declare const StyledDialogTitle: import("@emotion/styled").StyledComponent<Pick<import("@mui/material/DialogTitle").DialogTitleOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "children" | "style" | "className" | "color" | "classes" | "sx" | "variant" | "align" | "gutterBottom" | "noWrap" | "variantMapping">, "id" | "children" | "onError" | "ref" | "content" | "key" | "slot" | "style" | "title" | "hidden" | "resource" | "className" | "color" | "dir" | "classes" | "sx" | "tabIndex" | "variant" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "enterKeyHint" | "lang" | "nonce" | "spellCheck" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "popover" | "popoverTargetAction" | "popoverTarget" | "inert" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onScrollEnd" | "onScrollEndCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onToggle" | "onBeforeToggle" | "onTransitionCancel" | "onTransitionCancelCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "onTransitionRun" | "onTransitionRunCapture" | "onTransitionStart" | "onTransitionStartCapture" | "align" | "gutterBottom" | "noWrap" | "variantMapping"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
19
19
  declare const StyledDialogContent: import("@emotion/styled").StyledComponent<Pick<import("@mui/material/DialogContent").DialogContentProps, keyof import("@mui/material/DialogContent").DialogContentProps> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
20
20
  export declare function Modal({ open, onClose, title, actions, maxWidth, fullWidth, slotProps, children, }: ModalProps): React.ReactElement;
21
21
  export {};
@@ -167,6 +167,24 @@ var currentNavigator = defaultNavigator;
167
167
  function setAuthNavigator(navigator) {
168
168
  currentNavigator = navigator ?? defaultNavigator;
169
169
  }
170
+ function hasDocument() {
171
+ return typeof document !== "undefined" && typeof document.createElement === "function" && !!document.body;
172
+ }
173
+ function submitAsForm(url, entries) {
174
+ const form = document.createElement("form");
175
+ form.method = "post";
176
+ form.action = url;
177
+ form.style.display = "none";
178
+ for (const [name, value] of entries) {
179
+ const input = document.createElement("input");
180
+ input.type = "hidden";
181
+ input.name = name;
182
+ input.value = value;
183
+ form.appendChild(input);
184
+ }
185
+ document.body.appendChild(form);
186
+ form.submit();
187
+ }
170
188
  async function submitFinish(formOrData, options = {}) {
171
189
  const state = options.state ?? getAuthFlow();
172
190
  if (!state.submitUrl) {
@@ -174,8 +192,16 @@ async function submitFinish(formOrData, options = {}) {
174
192
  }
175
193
  const method = state.submitMethod ?? DEFAULT_SUBMIT_METHOD;
176
194
  const entries = withControlFields(state, toEntries(formOrData), finishMarkers(state));
177
- const response = await dispatch(method, state.submitUrl, entries);
178
195
  const shouldNavigate = options.navigate ?? (typeof window !== "undefined" && !!window.location);
196
+ if (shouldNavigate && method === "GET") {
197
+ currentNavigator(buildGetUrl(state.submitUrl, entries));
198
+ return new Response(null, { status: 204 });
199
+ }
200
+ if (shouldNavigate && hasDocument()) {
201
+ submitAsForm(state.submitUrl, entries);
202
+ return new Response(null, { status: 204 });
203
+ }
204
+ const response = await dispatch(method, state.submitUrl, entries);
179
205
  if (shouldNavigate && response.redirected && response.url) {
180
206
  currentNavigator(response.url);
181
207
  }
@@ -167,6 +167,24 @@ var currentNavigator = defaultNavigator;
167
167
  function setAuthNavigator(navigator) {
168
168
  currentNavigator = navigator ?? defaultNavigator;
169
169
  }
170
+ function hasDocument() {
171
+ return typeof document !== "undefined" && typeof document.createElement === "function" && !!document.body;
172
+ }
173
+ function submitAsForm(url, entries) {
174
+ const form = document.createElement("form");
175
+ form.method = "post";
176
+ form.action = url;
177
+ form.style.display = "none";
178
+ for (const [name, value] of entries) {
179
+ const input = document.createElement("input");
180
+ input.type = "hidden";
181
+ input.name = name;
182
+ input.value = value;
183
+ form.appendChild(input);
184
+ }
185
+ document.body.appendChild(form);
186
+ form.submit();
187
+ }
170
188
  async function submitFinish(formOrData, options = {}) {
171
189
  const state = options.state ?? getAuthFlow();
172
190
  if (!state.submitUrl) {
@@ -174,8 +192,16 @@ async function submitFinish(formOrData, options = {}) {
174
192
  }
175
193
  const method = state.submitMethod ?? DEFAULT_SUBMIT_METHOD;
176
194
  const entries = withControlFields(state, toEntries(formOrData), finishMarkers(state));
177
- const response = await dispatch(method, state.submitUrl, entries);
178
195
  const shouldNavigate = options.navigate ?? (typeof window !== "undefined" && !!window.location);
196
+ if (shouldNavigate && method === "GET") {
197
+ currentNavigator(buildGetUrl(state.submitUrl, entries));
198
+ return new Response(null, { status: 204 });
199
+ }
200
+ if (shouldNavigate && hasDocument()) {
201
+ submitAsForm(state.submitUrl, entries);
202
+ return new Response(null, { status: 204 });
203
+ }
204
+ const response = await dispatch(method, state.submitUrl, entries);
179
205
  if (shouldNavigate && response.redirected && response.url) {
180
206
  currentNavigator(response.url);
181
207
  }
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/ui",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "FrontMCP UI - MUI-based React components, renderers, and MCP bridge for MCP applications",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -439,7 +439,7 @@
439
439
  }
440
440
  },
441
441
  "optionalDependencies": {
442
- "@frontmcp/uipack": "1.8.2"
442
+ "@frontmcp/uipack": "1.8.3"
443
443
  },
444
444
  "devDependencies": {
445
445
  "@types/dompurify": "^3.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/ui",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "FrontMCP UI - MUI-based React components, renderers, and MCP bridge for MCP applications",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -439,7 +439,7 @@
439
439
  }
440
440
  },
441
441
  "optionalDependencies": {
442
- "@frontmcp/uipack": "1.8.2"
442
+ "@frontmcp/uipack": "1.8.3"
443
443
  },
444
444
  "devDependencies": {
445
445
  "@types/dompurify": "^3.0.0",