diff --git a/.changeset/unlucky-carrots-punch.md b/.changeset/unlucky-carrots-punch.md new file mode 100644 index 0000000000..ab24a238ec --- /dev/null +++ b/.changeset/unlucky-carrots-punch.md @@ -0,0 +1,6 @@ +--- +"@zag-js/file-upload": patch +"@zag-js/docs": patch +--- + +Fix reopening the system file picker in file-upload on browsers other than Chrome diff --git a/.xstate/file-upload.js b/.xstate/file-upload.js index 66a8b8a2a3..8abfec690d 100644 --- a/.xstate/file-upload.js +++ b/.xstate/file-upload.js @@ -13,6 +13,7 @@ const fetchMachine = createMachine({ id: "fileupload", initial: "idle", context: { + "!isWithinRange": false, "!isWithinRange": false }, on: { @@ -31,8 +32,12 @@ const fetchMachine = createMachine({ states: { idle: { on: { - OPEN: "open", - "DROPZONE.CLICK": "open", + OPEN: { + actions: ["openFilePicker"] + }, + "DROPZONE.CLICK": { + actions: ["openFilePicker"] + }, "DROPZONE.FOCUS": "focused", "DROPZONE.DRAG_OVER": [{ cond: "!isWithinRange", @@ -45,10 +50,19 @@ const fetchMachine = createMachine({ }, focused: { on: { - OPEN: "open", - "DROPZONE.CLICK": "open", - "DROPZONE.ENTER": "open", - "DROPZONE.BLUR": "idle" + OPEN: { + actions: ["openFilePicker"] + }, + "DROPZONE.CLICK": { + actions: ["openFilePicker"] + }, + "DROPZONE.DRAG_OVER": [{ + cond: "!isWithinRange", + target: "dragging", + actions: ["setInvalid"] + }, { + target: "dragging" + }] } }, dragging: { @@ -62,13 +76,6 @@ const fetchMachine = createMachine({ actions: ["clearInvalid"] } } - }, - open: { - activities: ["trackWindowFocus"], - entry: ["openFilePicker"], - on: { - CLOSE: "idle" - } } } }, { diff --git a/packages/docs/api.json b/packages/docs/api.json index 98a04469a5..1a14d8fd4a 100644 --- a/packages/docs/api.json +++ b/packages/docs/api.json @@ -1096,7 +1096,7 @@ }, "isFocused": { "type": "boolean", - "description": "Whether the user is focused on the root element" + "description": "Whether the user is focused on the dropzone element" }, "open": { "type": "() => void", diff --git a/packages/machines/file-upload/src/file-upload.machine.ts b/packages/machines/file-upload/src/file-upload.machine.ts index b2a025c1ef..939291f9ce 100644 --- a/packages/machines/file-upload/src/file-upload.machine.ts +++ b/packages/machines/file-upload/src/file-upload.machine.ts @@ -38,8 +38,12 @@ export function machine(userContext: UserDefinedContext) { states: { idle: { on: { - OPEN: "open", - "DROPZONE.CLICK": "open", + OPEN: { + actions: ["openFilePicker"], + }, + "DROPZONE.CLICK": { + actions: ["openFilePicker"], + }, "DROPZONE.FOCUS": "focused", "DROPZONE.DRAG_OVER": [ { @@ -53,10 +57,20 @@ export function machine(userContext: UserDefinedContext) { }, focused: { on: { - OPEN: "open", - "DROPZONE.CLICK": "open", - "DROPZONE.ENTER": "open", - "DROPZONE.BLUR": "idle", + OPEN: { + actions: ["openFilePicker"], + }, + "DROPZONE.CLICK": { + actions: ["openFilePicker"], + }, + "DROPZONE.DRAG_OVER": [ + { + guard: not("isWithinRange"), + target: "dragging", + actions: ["setInvalid"], + }, + { target: "dragging" }, + ], }, }, dragging: { @@ -71,29 +85,12 @@ export function machine(userContext: UserDefinedContext) { }, }, }, - open: { - activities: ["trackWindowFocus"], - entry: ["openFilePicker"], - on: { - CLOSE: "idle", - }, - }, }, }, { guards: { isWithinRange: (ctx, evt) => isFilesWithinRange(ctx, evt.count), }, - activities: { - trackWindowFocus(ctx, _evt, { send }) { - const win = dom.getWin(ctx) - const onWindowFocus = () => { - raf(() => send("CLOSE")) - } - win.addEventListener("focus", onWindowFocus) - return () => win.removeEventListener("focus", onWindowFocus) - }, - }, actions: { openFilePicker(ctx) { raf(() => { diff --git a/packages/machines/file-upload/src/file-upload.types.ts b/packages/machines/file-upload/src/file-upload.types.ts index 0513cde4a7..45e7e91adc 100644 --- a/packages/machines/file-upload/src/file-upload.types.ts +++ b/packages/machines/file-upload/src/file-upload.types.ts @@ -110,7 +110,7 @@ export interface MachineApi { */ isDragging: boolean /** - * Whether the user is focused on the root element + * Whether the user is focused on the dropzone element */ isFocused: boolean /**