| ... | @@ -150,7 +150,7 @@ class Observer<Args extends unknown[], Result> { | ... | @@ -150,7 +150,7 @@ class Observer<Args extends unknown[], Result> { |
| 150 | unsubscribe: (() => void) | null = null; | 150 | unsubscribe: (() => void) | null = null; |
| 151 | currentKey: string | null = null; | 151 | currentKey: string | null = null; |
| 152 | pendingTimer: Timer | null = null; | 152 | pendingTimer: Timer | null = null; |
| 153 | debounced: boolean; | 153 | debounced: boolean = false; |
| 154 | | 154 | |
| 155 | constructor(setRerender: (fn: number) => void) { | 155 | constructor(setRerender: (fn: number) => void) { |
| 156 | this.setRerender = setRerender; | 156 | this.setRerender = setRerender; |
| ... | @@ -236,7 +236,7 @@ class Observer<Args extends unknown[], Result> { | ... | @@ -236,7 +236,7 @@ class Observer<Args extends unknown[], Result> { |
| 236 | isSuccess: hasResult && !hasError, | 236 | isSuccess: hasResult && !hasError, |
| 237 | isError: hasError, | 237 | isError: hasError, |
| 238 | isOptimisticData: status === "waiting" || status === "mutating" | 238 | isOptimisticData: status === "waiting" || status === "mutating" |
| 239 | || status === "refetching" || (hasError && status !== "idle"), | 239 | || status === "refetching", |
| 240 | args: hasError || hasResult ? undefined : this.state.args, | 240 | args: hasError || hasResult ? undefined : this.state.args, |
| 241 | }); | 241 | }); |
| 242 | | 242 | |
| ... | @@ -317,7 +317,7 @@ class Observer<Args extends unknown[], Result> { | ... | @@ -317,7 +317,7 @@ class Observer<Args extends unknown[], Result> { |
| 317 | isSuccess: hasResult && !hasError, | 317 | isSuccess: hasResult && !hasError, |
| 318 | isError: hasError, | 318 | isError: hasError, |
| 319 | isOptimisticData: status === "waiting" || status === "mutating" | 319 | isOptimisticData: status === "waiting" || status === "mutating" |
| 320 | || status === "refetching" || (hasError && status !== "idle"), | 320 | || status === "refetching", |
| 321 | args: hasError || hasResult ? undefined : this.state.args, | 321 | args: hasError || hasResult ? undefined : this.state.args, |
| 322 | }); | 322 | }); |
| 323 | }, | 323 | }, |
| ... | @@ -420,14 +420,17 @@ export interface MutationButtonProps<Args extends unknown[], Result> { | ... | @@ -420,14 +420,17 @@ export interface MutationButtonProps<Args extends unknown[], Result> { |
| 420 | | Mutation<Args, Result> | 420 | | Mutation<Args, Result> |
| 421 | | UseMutateResult<Args, Result>; | 421 | | UseMutateResult<Args, Result>; |
| 422 | /** Preventing default will interrupt the mutation */ | 422 | /** Preventing default will interrupt the mutation */ |
| 423 | args: Args | ((e: MouseEvent) => Args | null); | 423 | args: Args | null | ((e: MouseEvent) => Args | null); |
| 424 | /** Preventing default will interrupt the mutation */ | 424 | /** Preventing default will interrupt the mutation */ |
| 425 | onClick?: (e: MouseEvent) => void; | 425 | onClick?: (e: MouseEvent) => void; |
| | 426 | disabled?: boolean; |
| 426 | | 427 | |
| 427 | /** Omitting this will use the global error handler */ | 428 | /** Omitting this will use the global error handler */ |
| 428 | onError?: (result: unknown) => void; | 429 | onError?: (result: unknown) => void; |
| 429 | /** Omitting this will use the global success handler */ | 430 | /** Omitting this will use the global success handler */ |
| 430 | onSuccess?: (result: Result) => void; | 431 | onSuccessUi?: (result: Result) => void; |
| | 432 | /** Does not prevent the global handler */ |
| | 433 | onSuccessData?: (result: Result) => void; |
| 431 | | 434 | |
| 432 | /** Global event handlers will still be called! */ | 435 | /** Global event handlers will still be called! */ |
| 433 | onSettled?: ( | 436 | onSettled?: ( |
| ... | @@ -471,6 +474,7 @@ type Flatten<T> = Identity<{ [K in keyof T]: T[K] }>; | ... | @@ -471,6 +474,7 @@ type Flatten<T> = Identity<{ [K in keyof T]: T[K] }>; |
| 471 | type ResolveMutationButtonFc<Props, Args extends unknown[], Result> = FC< | 474 | type ResolveMutationButtonFc<Props, Args extends unknown[], Result> = FC< |
| 472 | & Omit<Props, keyof MutationButtonProps<Args, Result>> | 475 | & Omit<Props, keyof MutationButtonProps<Args, Result>> |
| 473 | & BaseButtonProps | 476 | & BaseButtonProps |
| | 477 | & { disabled?: boolean } |
| 474 | >; | 478 | >; |
| 475 | | 479 | |
| 476 | function GenericMutationButton< | 480 | function GenericMutationButton< |
| ... | @@ -485,8 +489,10 @@ function GenericMutationButton< | ... | @@ -485,8 +489,10 @@ function GenericMutationButton< |
| 485 | mutation, | 489 | mutation, |
| 486 | args, | 490 | args, |
| 487 | onClick, | 491 | onClick, |
| | 492 | disabled: disabledAttr, |
| 488 | onError, | 493 | onError, |
| 489 | onSuccess, | 494 | onSuccessUi, |
| | 495 | onSuccessData, |
| 490 | onSettled, | 496 | onSettled, |
| 491 | ...forwarded | 497 | ...forwarded |
| 492 | } = props; | 498 | } = props; |
| ... | @@ -494,22 +500,25 @@ function GenericMutationButton< | ... | @@ -494,22 +500,25 @@ function GenericMutationButton< |
| 494 | | 500 | |
| 495 | const localHook = useMutate("subscribe" in mutation ? mutation : null); | 501 | const localHook = useMutate("subscribe" in mutation ? mutation : null); |
| 496 | const state = "subscribe" in mutation ? localHook : mutation; | 502 | const state = "subscribe" in mutation ? localHook : mutation; |
| | 503 | const disabled = disabledAttr || args == null || state.isDisabled; |
| | 504 | const handleClick = useCallback((e: MouseEvent) => { |
| | 505 | onClick?.(e); |
| | 506 | if (e.defaultPrevented) return; |
| | 507 | const computedArgs = typeof args === "function" ? args(e) : args; |
| | 508 | if (!computedArgs || e.defaultPrevented) return; |
| | 509 | state.runWithOptions( |
| | 510 | ...computedArgs, |
| | 511 | { onSuccessUi, onSuccessData, onError, onSettled }, |
| | 512 | ); |
| | 513 | }, [args, onClick, onError, onSettled, onSuccessUi, onSuccessData, state]); |
| 497 | | 514 | |
| 498 | // NOTE: the JSR has trouble with JSX syntax for some reason. | 515 | // NOTE: the JSR has trouble with JSX syntax for some reason. |
| 499 | return jsx( | 516 | return jsx( |
| 500 | Component, | 517 | Component, |
| 501 | { | 518 | { |
| 502 | ...forwarded, | 519 | ...forwarded, |
| 503 | onClick: useCallback((e: MouseEvent) => { | 520 | disabled, |
| 504 | onClick?.(e); | 521 | onClick: disabled ? undefined : handleClick, |
| 505 | if (e.defaultPrevented) return; | | |
| 506 | const computedArgs = typeof args === "function" ? args(e) : args; | | |
| 507 | if (!computedArgs || e.defaultPrevented) return; | | |
| 508 | state.runWithOptions( | | |
| 509 | ...computedArgs, | | |
| 510 | { onSuccess, onError, onSettled }, | | |
| 511 | ); | | |
| 512 | }, [state]), | | |
| 513 | isPending: state.isPending, | 522 | isPending: state.isPending, |
| 514 | } satisfies Parameters<typeof Component>[0], | 523 | } satisfies Parameters<typeof Component>[0], |
| 515 | ); | 524 | ); |