@unitedstatespowersquadrons/components 1.0.8 → 1.0.10

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/ActionButton.tsx CHANGED
@@ -76,7 +76,7 @@ const ActionButton = (props: ActionButtonProps) => {
76
76
  const buttonContents = () => {
77
77
  return(
78
78
  <>
79
- <FontAwesomeIcon icon={icon} fa={fa} mode={mode} style={style} />
79
+ <FontAwesomeIcon fa={fa} icon={icon} mode={mode} style={style} />
80
80
  <span>{text}</span>
81
81
  {subtext && <small className={classes.subText}>({subtext})</small>}
82
82
  </>
@@ -89,10 +89,10 @@ const ActionButton = (props: ActionButtonProps) => {
89
89
  return(
90
90
  <BaseActionButton
91
91
  className={classNames(classes.button, colorClassName, sizeClassName(), className)}
92
+ confirm={confirm}
92
93
  id={id}
93
94
  onClick={onClick}
94
95
  title={title}
95
- confirm={confirm}
96
96
  >
97
97
  {buttonContents()}
98
98
  </BaseActionButton>
@@ -103,11 +103,11 @@ const ActionButton = (props: ActionButtonProps) => {
103
103
  return(
104
104
  <BaseActionButton
105
105
  className={classNames(classes.button, colorClassName, sizeClassName(), className)}
106
+ confirm={confirm}
106
107
  href={href}
107
108
  id={id}
108
109
  method={method}
109
110
  title={title}
110
- confirm={confirm}
111
111
  >
112
112
  {buttonContents()}
113
113
  </BaseActionButton>
@@ -139,10 +139,10 @@ const ActionButton = (props: ActionButtonProps) => {
139
139
  return(
140
140
  <BaseActionButton
141
141
  className={classNames(classes.button, colorClassName, sizeClassName(), className)}
142
+ confirm={confirm}
142
143
  id={id}
143
144
  onClick={onClick}
144
145
  title={title}
145
- confirm={confirm}
146
146
  >
147
147
  {buttonContents()}
148
148
  </BaseActionButton>
@@ -47,11 +47,11 @@ const BaseActionButton = (props: BaseActionButtonProps) => {
47
47
 
48
48
  return(
49
49
  <button
50
- type="button"
51
- id={id}
52
50
  className={classNames("action-button", classes.button, className)}
51
+ id={id}
53
52
  onClick={wrappedOnClick}
54
53
  title={title}
54
+ type="button"
55
55
  >
56
56
  {children}
57
57
  </button>
@@ -66,8 +66,8 @@ const BaseActionButton = (props: BaseActionButtonProps) => {
66
66
 
67
67
  return(
68
68
  <form action={href} method="POST" ref={formRef}>
69
- <input type="hidden" name="authenticity_token" value={getCsrfTokenHeader()} />
70
- <input type="hidden" name="_method" value={method.toUpperCase()} />
69
+ <input name="authenticity_token" type="hidden" value={getCsrfTokenHeader()} />
70
+ <input name="_method" type="hidden" value={method.toUpperCase()} />
71
71
  </form>
72
72
  );
73
73
  };
@@ -86,11 +86,11 @@ const BaseActionButton = (props: BaseActionButtonProps) => {
86
86
  <>
87
87
  {form()}
88
88
  <button
89
- type="button"
90
- id={id}
91
89
  className={classNames("action-button", classes.button, className)}
90
+ id={id}
92
91
  onClick={submitForm}
93
92
  title={title}
93
+ type="button"
94
94
  >
95
95
  {children}
96
96
  </button>
@@ -109,11 +109,11 @@ const BaseActionButton = (props: BaseActionButtonProps) => {
109
109
 
110
110
  return(
111
111
  <button
112
- type="button"
113
- onClick={onClick}
114
- id={id}
115
112
  className={classNames("action-button", classes.button, className)}
113
+ id={id}
114
+ onClick={onClick}
116
115
  title={title}
116
+ type="button"
117
117
  >
118
118
  {children}
119
119
  </button>
package/Flags/Officer.tsx CHANGED
@@ -80,7 +80,7 @@ const OfficerFlag = (props: Props) => {
80
80
 
81
81
  const combinedPath = `${flagBaseUrl}/${formatDir}/${subDirectory()}${displayRank}${sizeExtension}.${extension}`;
82
82
 
83
- return <img className={className} src={combinedPath} alt={displayRank} />;
83
+ return <img alt={displayRank} className={className} src={combinedPath} />;
84
84
  };
85
85
 
86
86
  export default OfficerFlag;
package/Flags/Signal.tsx CHANGED
@@ -52,7 +52,7 @@ const SignalFlag = (props: Props) => {
52
52
  const combinedUrl = `${signalBaseUrl}/${formatDir}/${dir()}/${flagValue()}.${extension}`;
53
53
 
54
54
  return (
55
- <img className={className} src={combinedUrl} alt={alt || flag} />
55
+ <img alt={alt || flag} className={className} src={combinedUrl} />
56
56
  );
57
57
  };
58
58
 
package/IconButton.tsx CHANGED
@@ -33,7 +33,7 @@ const IconButton = (props: IconButtonProps) => {
33
33
  const { className, fa, icon, id, mode, style, title } = props;
34
34
  const classes = useStyles();
35
35
 
36
- const configuredIcon = <FontAwesomeIcon icon={icon} fa={fa} mode={mode} style={style} css={className} />;
36
+ const configuredIcon = <FontAwesomeIcon css={className} fa={fa} icon={icon} mode={mode} style={style} />;
37
37
 
38
38
  const combinedClassName = classNames(classes.icon, className);
39
39
 
@@ -43,10 +43,10 @@ const IconButton = (props: IconButtonProps) => {
43
43
  return(
44
44
  <BaseActionButton
45
45
  className={combinedClassName}
46
+ confirm={confirm}
46
47
  id={id}
47
48
  onClick={onClick}
48
49
  title={title}
49
- confirm={confirm}
50
50
  >
51
51
  {configuredIcon}
52
52
  </BaseActionButton>
@@ -57,11 +57,11 @@ const IconButton = (props: IconButtonProps) => {
57
57
  return(
58
58
  <BaseActionButton
59
59
  className={combinedClassName}
60
+ confirm={confirm}
60
61
  href={href}
61
62
  id={id}
62
63
  method={method}
63
64
  title={title}
64
- confirm={confirm}
65
65
  >
66
66
  {configuredIcon}
67
67
  </BaseActionButton>
@@ -0,0 +1,64 @@
1
+ import { createContext } from "react";
2
+ import { Draft } from "immer";
3
+ import { AppState, ServerResponse } from "./types";
4
+ import {
5
+ buildReducer,
6
+ DispatchFunc,
7
+ DispatchHandler,
8
+ RailsAppAction,
9
+ ReducerHandler,
10
+ wrapDispatch,
11
+ } from "../";
12
+
13
+ // If you want to add additional data to the server response, use type `RailsAppAction<ExampleServerResponse>`.
14
+ // Otherwise, just use type `RailsAppAction`.
15
+ //
16
+ // If you need to access the available `type`s for your defined AppAction, use `AppActionType<AppAction>`
17
+ //
18
+ type AppAction =
19
+ | RailsAppAction<ServerResponse>
20
+ | { type: "doSomething"; something: string };
21
+
22
+ export const exampleReducer = (draft: Draft<AppState>, action: AppAction): void => {
23
+ const { type } = action;
24
+
25
+ switch (type) {
26
+ case "doSomething":
27
+ draft.something = "changed";
28
+
29
+ break;
30
+ case "saveComplete": break;
31
+ case "saveFailed": break;
32
+ default: return type satisfies never;
33
+ }
34
+ };
35
+
36
+ export const doSomething: ReducerHandler<AppAction> = (
37
+ dispatch: DispatchFunc<AppAction>
38
+ ): DispatchFunc<AppAction> => {
39
+ const actionType = "doSomething";
40
+
41
+ const handler: DispatchHandler<AppAction> = (action: AppAction) => {
42
+ if (action.type !== actionType) return {};
43
+
44
+ const { something } = action;
45
+
46
+ const bodyJson = { something };
47
+ const href = "/do_something";
48
+
49
+ return { bodyJson, href };
50
+ };
51
+
52
+ // If you want to add additional data to the server response, pass in type `ServerResponse`.
53
+ // Otherwise, just leave the second type parameter unspecified.
54
+ return wrapDispatch<AppAction, ServerResponse>(dispatch, [actionType], handler);
55
+ };
56
+
57
+ export const { AppProvider, useAppDispatch, useAppState } = buildReducer(
58
+ exampleReducer,
59
+ createContext<AppState | null>(null),
60
+ createContext<React.Dispatch<AppAction> | null>(null),
61
+ [
62
+ doSomething,
63
+ ]
64
+ );
@@ -0,0 +1,9 @@
1
+ import { RailsResponse } from "../types";
2
+
3
+ export interface AppState {
4
+ something: string;
5
+ }
6
+
7
+ export interface ServerResponse extends RailsResponse {
8
+ update: AppState;
9
+ }
@@ -0,0 +1,60 @@
1
+ import React, { useContext, useMemo } from "react";
2
+ import { Draft, produce } from "immer";
3
+ import { useImmerReducer } from "use-immer";
4
+ import { ReducerHandler } from "./types";
5
+
6
+ interface InitialAppProps<AppState> {
7
+ initialState: AppState;
8
+ children: React.ReactNode;
9
+ }
10
+
11
+ export default function buildReducer<AppState, AppAction>(
12
+ reducer: (draft: Draft<AppState>, action: AppAction) => void,
13
+ StateContext: React.Context<AppState | null>,
14
+ DispatchContext: React.Context<React.Dispatch<AppAction> | null>,
15
+ handlers: ReducerHandler<AppAction>[] = []
16
+ ) {
17
+ function AppProvider(props: InitialAppProps<AppState>) {
18
+ const [providerState, dispatch] = useImmerReducer(reducer, props.initialState, (state: AppState) => {
19
+ return produce(state, draft => draft);
20
+ });
21
+
22
+ const wrappedDispatch = useMemo(() => {
23
+ let d = dispatch;
24
+
25
+ handlers.forEach(handler => d = handler(d));
26
+
27
+ return d;
28
+ }, [dispatch]);
29
+
30
+ return (
31
+ <StateContext.Provider value={providerState}>
32
+ <DispatchContext.Provider value={wrappedDispatch}>
33
+ {props.children}
34
+ </DispatchContext.Provider>
35
+ </StateContext.Provider>
36
+ );
37
+ }
38
+
39
+ function useAppState() {
40
+ const context = useContext(StateContext);
41
+ if (!context) {
42
+ throw new Error("useAppState has to be used within AppProvider");
43
+ }
44
+ return context;
45
+ }
46
+
47
+ function useAppDispatch() {
48
+ const context = useContext(DispatchContext);
49
+ if (!context) {
50
+ throw new Error("useAppDispatch has to be used within AppProvider");
51
+ }
52
+ return context;
53
+ }
54
+
55
+ return {
56
+ AppProvider,
57
+ useAppDispatch,
58
+ useAppState,
59
+ };
60
+ }
@@ -0,0 +1,3 @@
1
+ export { default as wrapDispatch } from "./wrapDispatch";
2
+ export { default as buildReducer } from "./buildReducer";
3
+ export type * from "./types";
@@ -0,0 +1,34 @@
1
+ import { Toast } from "../Toasts";
2
+
3
+ export interface RailsResponse {
4
+ reload?: boolean;
5
+ status: "OK" | "ERROR";
6
+ toasts: Toast[];
7
+ }
8
+
9
+ export type DispatchFunc<T> = (action: T) => void;
10
+ export type DispatchHandler<T> = (action: T) => {
11
+ body?: string;
12
+ bodyJson?: object;
13
+ headers?: { [key: string]: string };
14
+ href?: string;
15
+ method?: string;
16
+ };
17
+
18
+ export type ReducerHandler<AppAction> = (dispatch: DispatchFunc<AppAction>) => DispatchFunc<AppAction>;
19
+
20
+ export interface GenericAppAction {
21
+ type: string;
22
+ }
23
+
24
+ export type RailsAppAction<R extends RailsResponse = RailsResponse> =
25
+ | { type: "saveComplete"; res: R }
26
+ | { type: "saveFailed" };
27
+
28
+ type ExtractField<T, K extends string> = T extends { [key in K]: infer U } ? U : never;
29
+ export type AppActionType<
30
+ A extends GenericAppAction,
31
+ Res extends RailsResponse = RailsResponse
32
+ > =
33
+ | ExtractField<A, "type">
34
+ | ExtractField<RailsAppAction<Res>, "type">;
@@ -0,0 +1,74 @@
1
+ import {
2
+ AppActionType,
3
+ DispatchFunc,
4
+ DispatchHandler,
5
+ GenericAppAction,
6
+ RailsAppAction,
7
+ RailsResponse,
8
+ } from "./types";
9
+ import railsFetchJson from "../railsFetchJson";
10
+
11
+ type AppAction<Res extends RailsResponse = RailsResponse> =
12
+ | GenericAppAction
13
+ | RailsAppAction<Res>;
14
+
15
+ export default function wrapDispatch<
16
+ A extends AppAction<ServerResponse>,
17
+ ServerResponse extends RailsResponse = RailsResponse
18
+ >(
19
+ dispatch: DispatchFunc<A>,
20
+ appActionTypes: AppActionType<A>[],
21
+ handler: DispatchHandler<A>
22
+ ): DispatchFunc<A> {
23
+ const updateDebounceTime = (("testEnv" in window) && window.testEnv) ? 50 : 250;
24
+
25
+ const updateHandler = async (action: A, signal: AbortSignal) => {
26
+ const { bodyJson, headers, href, method } = handler(action);
27
+
28
+ if (!href || !bodyJson) return;
29
+
30
+ const requestHeaders = headers || {};
31
+
32
+ try {
33
+ const res = await railsFetchJson<ServerResponse>(
34
+ href,
35
+ { bodyJson, headers: requestHeaders, method: method || "POST", signal }
36
+ );
37
+
38
+ dispatch({ res, type: "saveComplete" } as A);
39
+ } catch(e) {
40
+ // Ignore request aborts
41
+ if (e instanceof DOMException) return;
42
+
43
+ dispatch({ type: "saveFailed" } as A);
44
+ }
45
+ };
46
+
47
+ const timers: { [id: string]: number } = {};
48
+ const abortControllers: { [id: string]: AbortController } = {};
49
+
50
+ return (action: A) => {
51
+ // Run it like normal
52
+ dispatch(action);
53
+
54
+ // Skip if it's not one of the appActionTypes we care about
55
+ if (!appActionTypes.includes(action.type as AppActionType<A>)) return;
56
+
57
+ const timeoutKey = "userTimeout";
58
+
59
+ // Stop previous request
60
+ const timer = timers[timeoutKey];
61
+ if (timer) clearTimeout(timer);
62
+ delete timers[timeoutKey];
63
+ const oldAbortController = abortControllers[timeoutKey];
64
+ if (oldAbortController) oldAbortController.abort();
65
+ delete abortControllers[timeoutKey];
66
+
67
+ // Make request
68
+ const abortController = abortControllers[timeoutKey] = new AbortController();
69
+ const signal = abortController.signal;
70
+ timers[timeoutKey] = setTimeout(() => {
71
+ void updateHandler(action, signal);
72
+ }, updateDebounceTime);
73
+ };
74
+ }
@@ -22,12 +22,12 @@ const SelectionIconButton = (props: Props) => {
22
22
 
23
23
  return(
24
24
  <IconButton
25
+ className={classNames(classes.icon, className)}
25
26
  icon={icon}
26
27
  id={id}
28
+ mode="duotone"
27
29
  onClick={onClick}
28
30
  title={title}
29
- className={classNames(classes.icon, className)}
30
- mode="duotone"
31
31
  />
32
32
  );
33
33
  };
@@ -18,7 +18,7 @@ const Table = (props: Props) => {
18
18
  const classes = useStyles();
19
19
 
20
20
  return(
21
- <table id={id} className={classNames(className, classes.table)}>
21
+ <table className={classNames(className, classes.table)} id={id}>
22
22
  {children}
23
23
  </table>
24
24
  );
package/Toasts/Toast.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import classNames from "classnames";
3
3
  import { createUseStyles } from "react-jss";
4
- import { DismissFunc, ToastProps, Toast_Status } from "./types";
4
+ import { DismissFunc, Toast_Status, ToastProps } from "./types";
5
5
  import FontAwesomeIcon from "../FontAwesomeIcon";
6
6
 
7
7
  interface Props {
@@ -122,12 +122,12 @@ const Toast = (props: Props) => {
122
122
  return (
123
123
  <div className={classNames(classes.toast, statusClassName, opacityClass)} key={`toast-${id}`}>
124
124
  <div className={classes.toastTitle}>
125
- <FontAwesomeIcon icon={icon} mode="duotone" fa="fw" />
125
+ <FontAwesomeIcon fa="fw" icon={icon} mode="duotone" />
126
126
  <span>{title}</span>
127
127
  </div>
128
128
  <div className={classes.toastBody}>{renderBody()}</div>
129
- <a className={classes.toastDismiss} title="Dismiss this message" onClick={handleDismiss}>
130
- <FontAwesomeIcon icon="times" mode="duotone" fa="fw" css={classes.toastDismissIcon} />
129
+ <a className={classes.toastDismiss} onClick={handleDismiss} title="Dismiss this message">
130
+ <FontAwesomeIcon css={classes.toastDismissIcon} fa="fw" icon="times" mode="duotone" />
131
131
  </a>
132
132
  </div>
133
133
  );
package/Toasts/Toasts.tsx CHANGED
@@ -2,9 +2,9 @@ import React from "react";
2
2
  import classNames from "classnames";
3
3
  import { createUseStyles } from "react-jss";
4
4
  import Toast from "./Toast";
5
- import createDismissToast from "./createDismissToast";
5
+ import { createDismissToast } from "./toastHelpers";
6
6
  import { DismissFunc, ToastProps, ToastRemoveAppAction } from "./types";
7
- import { DispatchFunc } from "../types";
7
+ import { DispatchFunc } from "../";
8
8
 
9
9
  interface BaseProps {
10
10
  toasts?: ToastProps[];
@@ -50,7 +50,7 @@ const Toasts = (props: Props) => {
50
50
 
51
51
  return (
52
52
  <div className={classNames("toastsContainer", classes.toastsContainer)}>
53
- {toasts?.map(toast => <Toast dismiss={dismissFunc()} toast={toast} key={toast.id} />)}
53
+ {toasts?.map(toast => <Toast dismiss={dismissFunc()} key={toast.id} toast={toast} />)}
54
54
  </div>
55
55
  );
56
56
  };
package/Toasts/index.tsx CHANGED
@@ -1,5 +1,8 @@
1
1
  export { default as Toasts } from "./Toasts";
2
- export { default as createDismissToast } from "./createDismissToast";
2
+ export * from "./toastHelpers";
3
3
 
4
- export { Toast_Status } from "./types";
5
- export type { Toast, ToastAppAction, ToastProps } from "./types";
4
+ export * from "./types";
5
+ export type * from "./types";
6
+
7
+ // Legacy exports for compatibility
8
+ export { createDismissToast } from "./toastHelpers";
@@ -0,0 +1,47 @@
1
+ import { Draft } from "immer";
2
+ import { Toast, ToastProps, ToastRemoveAppAction } from "./types";
3
+ import { AppStateWithToasts, DispatchFunc } from "../";
4
+
5
+ export function createDismissToast(dispatch: DispatchFunc<ToastRemoveAppAction>) {
6
+ const dismissToast = (toastId: number) => {
7
+ dispatch({ toastId, type: "dismissToast" });
8
+
9
+ setTimeout(() => dispatch({ toastId, type: "removeToast" }), 2000);
10
+ };
11
+
12
+ return dismissToast;
13
+ }
14
+
15
+ export function handleToasts<T extends AppStateWithToasts>(draft: Draft<T>, toasts: Toast[]) {
16
+ const handleToastsFunc = () => {
17
+ if (toasts.length > 0) {
18
+ toasts.forEach(toast => addToast(draft, toast));
19
+ }
20
+ };
21
+
22
+ return handleToastsFunc;
23
+ }
24
+
25
+ export function addToast<T extends AppStateWithToasts>(draft: Draft<T>, toastOptions: Toast) {
26
+ const { body, status, timeout, title } = toastOptions;
27
+
28
+ // Increment current toastId to prevent collisions
29
+ const id = draft.toastId ? draft.toastId + 1 : 1;
30
+ draft.toastId = id;
31
+
32
+ const toast = { body, id, status, timeout, title } as ToastProps;
33
+
34
+ // Initialize toasts array if not provided by the server
35
+ if (!draft.toasts) draft.toasts = [];
36
+
37
+ // Do not store multiple identical toasts
38
+ if (draft.toasts.some(t => {
39
+ return (
40
+ toast.body === t.body &&
41
+ toast.status === t.status &&
42
+ toast.title === t.title
43
+ );
44
+ })) return;
45
+
46
+ draft.toasts.push(toast);
47
+ }
package/eslint.config.mjs CHANGED
@@ -30,6 +30,13 @@ export default tseslint.config(
30
30
  "quotes": ["error", "double"],
31
31
  "semi": ["error", "always"],
32
32
  "sort-keys": ["error", "asc", { caseSensitive: true, minKeys: 2, natural: false }],
33
+ "sort-imports": [
34
+ "error",
35
+ {
36
+ "ignoreCase": true,
37
+ "ignoreDeclarationSort": true,
38
+ }
39
+ ],
33
40
  "arrow-parens": ["error", "as-needed"],
34
41
  "comma-dangle": [
35
42
  "error",
@@ -145,11 +152,12 @@ export default tseslint.config(
145
152
  "stylistic/no-extra-semi": "error",
146
153
  "stylistic/semi": ["error", "always"],
147
154
  "stylistic/no-multiple-empty-lines": "error",
155
+ "stylistic/jsx-sort-props": "error",
148
156
  "stylistic/array-element-newline": [
149
157
  "error",
150
158
  {
151
159
  "ArrayExpression": "consistent",
152
- "ArrayPattern": { "minItems": 3 },
160
+ "ArrayPattern": { "minItems": 5 },
153
161
  }
154
162
  ],
155
163
  "stylistic/object-property-newline": [
package/index.tsx CHANGED
@@ -1,3 +1,5 @@
1
+ export * from "./Reducer";
2
+
1
3
  export { default as FontAwesomeIcon } from "./FontAwesomeIcon";
2
4
 
3
5
  export { default as railsFetchJson } from "./railsFetchJson";
@@ -17,6 +19,7 @@ export { default as Colors } from "./Colors";
17
19
  export { default as Styles } from "./Styles";
18
20
 
19
21
  export type * from "./types";
22
+ export type * from "./Reducer";
20
23
  export type * from "./Colors";
21
24
  export type * from "./FontAwesomeIcon";
22
25
  export type * from "./ActionButton";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unitedstatespowersquadrons/components",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "USPS shared React components library",
5
5
  "main": "index.tsx",
6
6
  "scripts": {
@@ -18,9 +18,11 @@
18
18
  "homepage": "https://github.com/unitedstatespowersquadrons/components#readme",
19
19
  "dependencies": {
20
20
  "classnames": "^2.5.1",
21
+ "immer": "^10.1.1",
21
22
  "react": "^19.1.0",
22
23
  "react-jss": "^10.10.0",
23
- "typescript": "^5.8.3"
24
+ "typescript": "^5.8.3",
25
+ "use-immer": "^0.11.0"
24
26
  },
25
27
  "devDependencies": {
26
28
  "@stylistic/eslint-plugin": "^5.1.0",
package/types.ts CHANGED
@@ -1,20 +1,11 @@
1
1
  import React from "react";
2
- import { Toast, ToastProps } from "./Toasts";
2
+ import { ToastProps } from "./Toasts";
3
3
 
4
4
  export interface AppStateWithToasts {
5
5
  toasts: ToastProps[];
6
6
  toastId?: number;
7
7
  }
8
8
 
9
- export type DispatchFunc<T> = (action: T) => void;
10
- export type DispatchHandler<T> = (action: T) => {
11
- body?: string;
12
- bodyJson?: object;
13
- headers?: { [key: string]: string };
14
- href?: string;
15
- method?: string;
16
- };
17
-
18
9
  export type OnClickHandler = (event: React.MouseEvent<HTMLButtonElement>) => void;
19
10
  export type OnInputChangeHandler = (event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => void;
20
11
  export type OnClickOrKeyboardHandler = (event: OnClickOrKeyboardEvent) => void;
@@ -44,9 +35,3 @@ export interface OnClickProps {
44
35
  confirm?: string | undefined;
45
36
  onClick: OnClickHandler;
46
37
  }
47
-
48
- export interface RailsResponse {
49
- reload?: boolean;
50
- status: "OK" | "ERROR";
51
- toasts: Toast[];
52
- }
@@ -1,16 +0,0 @@
1
- import { ToastRemoveAppAction } from "./types";
2
- import { DispatchFunc } from "../types";
3
-
4
- const createDismissToast = (dispatch: DispatchFunc<ToastRemoveAppAction>) => {
5
- const dismissToast = (toastId: number) => {
6
- dispatch({ toastId, type: "dismissToast" });
7
-
8
- setTimeout(() => {
9
- dispatch({ toastId, type: "removeToast" });
10
- }, 2000);
11
- };
12
-
13
- return dismissToast;
14
- };
15
-
16
- export default createDismissToast;