@void-snippets/react 0.2.2 → 0.3.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.
package/dist/index.mjs CHANGED
@@ -16,40 +16,35 @@ function createResourceHooks(queryKeyPrefix, apiService, options = {}) {
16
16
  adapters = createDefaultAdapters(),
17
17
  defaultParams = DEFAULT_PAGINATION
18
18
  } = options;
19
- const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
20
- const capPrefix = capitalize(queryKeyPrefix);
21
19
  return {
22
20
  // -------------------------------------------------------------------------
23
- // useList — paginated list with invalidation helper
21
+ // useList — fixed generic shape: { list, isLoading, pagination, error, invalidate }
24
22
  // -------------------------------------------------------------------------
25
23
  useList: (params = defaultParams) => {
26
24
  var _a, _b, _c, _d, _e;
27
25
  const queryClient = useQueryClient();
28
- const queryKey = [queryKeyPrefix, params];
29
26
  const query = useQuery({
30
- queryKey,
27
+ queryKey: [queryKeyPrefix, params],
31
28
  queryFn: async () => {
32
29
  const raw = await service.list(params);
33
30
  return adapters.fromList(raw);
34
31
  }
35
32
  });
36
- const items = (_b = (_a = query.data) == null ? void 0 : _a.items) != null ? _b : [];
37
- const pagination = (_e = (_c = query.data) == null ? void 0 : _c.pagination) != null ? _e : {
38
- page: 1,
39
- limit: (_d = defaultParams.limit) != null ? _d : 10,
40
- totalPages: 0,
41
- totalDocuments: 0
42
- };
43
33
  return {
44
- [queryKeyPrefix]: items,
45
- pagination,
46
- [`is${capPrefix}Loading`]: query.isLoading || query.isFetching,
47
- [`${queryKeyPrefix}Error`]: query.error,
48
- [`invalidate${capPrefix}`]: () => queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] })
34
+ list: (_b = (_a = query.data) == null ? void 0 : _a.items) != null ? _b : [],
35
+ pagination: (_e = (_c = query.data) == null ? void 0 : _c.pagination) != null ? _e : {
36
+ page: 1,
37
+ limit: (_d = defaultParams.limit) != null ? _d : 10,
38
+ totalPages: 0,
39
+ totalDocuments: 0
40
+ },
41
+ isLoading: query.isLoading || query.isFetching,
42
+ error: query.error,
43
+ invalidate: () => queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] })
49
44
  };
50
45
  },
51
46
  // -------------------------------------------------------------------------
52
- // useGet — single item by id
47
+ // useGet — { item, isLoading, error, refetch }
53
48
  // -------------------------------------------------------------------------
54
49
  useGet: (id, staleTime = 3e4) => {
55
50
  const query = useQuery({
@@ -62,14 +57,14 @@ function createResourceHooks(queryKeyPrefix, apiService, options = {}) {
62
57
  staleTime
63
58
  });
64
59
  return {
65
- data: query.data,
60
+ item: query.data,
66
61
  isLoading: query.isLoading || query.isFetching,
67
62
  error: query.error,
68
63
  refetch: query.refetch
69
64
  };
70
65
  },
71
66
  // -------------------------------------------------------------------------
72
- // useMutations — create / update / delete with auto-invalidation
67
+ // useMutations — create / update / remove (not delete reserved keyword)
73
68
  // -------------------------------------------------------------------------
74
69
  useMutations: () => {
75
70
  const queryClient = useQueryClient();
@@ -88,7 +83,7 @@ function createResourceHooks(queryKeyPrefix, apiService, options = {}) {
88
83
  },
89
84
  onSuccess: invalidate
90
85
  });
91
- const deleteMutation = useMutation({
86
+ const removeMutation = useMutation({
92
87
  mutationFn: async (_id) => {
93
88
  const raw = await service.delete(_id);
94
89
  return adapters.fromSingle(raw);
@@ -98,7 +93,7 @@ function createResourceHooks(queryKeyPrefix, apiService, options = {}) {
98
93
  return {
99
94
  create: createMutation,
100
95
  update: updateMutation,
101
- delete: deleteMutation
96
+ remove: removeMutation
102
97
  };
103
98
  },
104
99
  // -------------------------------------------------------------------------
@@ -125,7 +120,165 @@ function createResourceHooks(queryKeyPrefix, apiService, options = {}) {
125
120
  }
126
121
  };
127
122
  }
123
+
124
+ // src/hooks/useAlertMessage.ts
125
+ import { useCallback, useState } from "react";
126
+ function useAlertMessage(autoHideDuration = 3e3) {
127
+ const [alert, setAlert] = useState({
128
+ message: null,
129
+ type: "info",
130
+ isVisible: false
131
+ });
132
+ const showAlert = useCallback(
133
+ (message, type = "info") => {
134
+ setAlert({ message, type, isVisible: true });
135
+ if (autoHideDuration) {
136
+ setTimeout(() => {
137
+ setAlert((prev) => ({ ...prev, isVisible: false }));
138
+ }, autoHideDuration);
139
+ }
140
+ },
141
+ [autoHideDuration]
142
+ );
143
+ const hideAlert = useCallback(() => {
144
+ setAlert((prev) => ({ ...prev, isVisible: false }));
145
+ }, []);
146
+ return { alert, showAlert, hideAlert };
147
+ }
148
+
149
+ // src/hooks/useAsyncState.ts
150
+ import { useCallback as useCallback2, useMemo, useState as useState2 } from "react";
151
+ import { catchError } from "@void-snippets/core";
152
+ function useAsyncState(initialData = null) {
153
+ const [state, setState] = useState2({
154
+ data: initialData,
155
+ status: "idle",
156
+ error: null
157
+ });
158
+ const setData = useCallback2((data) => {
159
+ setState({ data, status: "success", error: null });
160
+ }, []);
161
+ const setError = useCallback2((error) => {
162
+ setState((prev) => ({ ...prev, error, status: "error" }));
163
+ }, []);
164
+ const reset = useCallback2(() => {
165
+ setState({ data: initialData, status: "idle", error: null });
166
+ }, [initialData]);
167
+ const execute = useCallback2(
168
+ async (asyncFn, options) => {
169
+ var _a, _b;
170
+ setState((prev) => ({ ...prev, status: "pending", error: null }));
171
+ const [err, res] = await catchError(asyncFn());
172
+ if (err) {
173
+ setState((prev) => ({ ...prev, status: "error", error: err }));
174
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, err);
175
+ return [err, null];
176
+ }
177
+ setState({ data: res, status: "success", error: null });
178
+ (_b = options == null ? void 0 : options.onSuccess) == null ? void 0 : _b.call(options, res);
179
+ return [null, res];
180
+ },
181
+ []
182
+ );
183
+ const flags = useMemo(
184
+ () => ({
185
+ isLoading: state.status === "pending",
186
+ isSuccess: state.status === "success",
187
+ isError: state.status === "error"
188
+ }),
189
+ [state.status]
190
+ );
191
+ return { ...state, ...flags, setData, setError, reset, execute };
192
+ }
193
+
194
+ // src/hooks/useCallTimer.ts
195
+ import { useEffect, useState as useState3 } from "react";
196
+ function useCallTimer(startedAt) {
197
+ const [duration, setDuration] = useState3("00:00");
198
+ useEffect(() => {
199
+ if (!startedAt) {
200
+ setDuration("00:00");
201
+ return;
202
+ }
203
+ const interval = setInterval(() => {
204
+ const diffInSeconds = Math.floor((Date.now() - startedAt) / 1e3);
205
+ const minutes = Math.floor(diffInSeconds / 60).toString().padStart(2, "0");
206
+ const seconds = (diffInSeconds % 60).toString().padStart(2, "0");
207
+ setDuration(`${minutes}:${seconds}`);
208
+ }, 1e3);
209
+ return () => clearInterval(interval);
210
+ }, [startedAt]);
211
+ return duration;
212
+ }
213
+
214
+ // src/hooks/useModal.ts
215
+ import { useCallback as useCallback3, useState as useState4 } from "react";
216
+ function useModal() {
217
+ const [isOpen, setIsOpen] = useState4(false);
218
+ const [data, setData] = useState4(null);
219
+ const [isLoading, setIsLoading] = useState4(false);
220
+ const openCreateModal = useCallback3(() => {
221
+ setIsOpen(true);
222
+ setData(null);
223
+ }, []);
224
+ const openEditModal = useCallback3((editData) => {
225
+ setIsOpen(true);
226
+ setData(editData);
227
+ }, []);
228
+ const setLoading = useCallback3((loading) => {
229
+ setIsLoading(loading);
230
+ }, []);
231
+ const closeModal = useCallback3(() => {
232
+ setIsOpen(false);
233
+ setData(null);
234
+ }, []);
235
+ const setModal = useCallback3((open, editData) => {
236
+ setIsOpen(open);
237
+ setData(editData != null ? editData : null);
238
+ }, []);
239
+ return {
240
+ isOpen,
241
+ data,
242
+ isLoading,
243
+ openCreateModal,
244
+ openEditModal,
245
+ setLoading,
246
+ closeModal,
247
+ setModal
248
+ };
249
+ }
250
+
251
+ // src/hooks/usePagination.ts
252
+ import { useCallback as useCallback4, useState as useState5 } from "react";
253
+ function usePagination(initialPage = 1, initialLimit = 10) {
254
+ const [page, setPage] = useState5(initialPage);
255
+ const [limit, setLimit] = useState5(initialLimit);
256
+ const onPaginationChange = useCallback4(
257
+ (newPage, newLimit) => {
258
+ setPage(newPage);
259
+ setLimit(newLimit);
260
+ },
261
+ []
262
+ );
263
+ const resetPagination = useCallback4(() => {
264
+ setPage(1);
265
+ }, []);
266
+ return {
267
+ page,
268
+ limit,
269
+ onPaginationChange,
270
+ resetPagination,
271
+ setPage,
272
+ setLimit,
273
+ queryParams: { page, limit }
274
+ };
275
+ }
128
276
  export {
129
- createResourceHooks
277
+ createResourceHooks,
278
+ useAlertMessage,
279
+ useAsyncState,
280
+ useCallTimer,
281
+ useModal,
282
+ usePagination
130
283
  };
131
284
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/createResourceHooks.ts"],"sourcesContent":["import {\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport type { ResourceService } from \"@void-snippets/client\";\nimport type {\n ResourceAdapters,\n ResourceListResult,\n TPagination,\n TQueryParams,\n TDefaultPaginatedResponse,\n TDefaultSingleResponse,\n} from \"@void-snippets/core\";\nimport { createDefaultAdapters } from \"@void-snippets/core\";\n\n// ============================================================================\n// TYPE HELPERS\n// ============================================================================\n\ntype CapitalizeStr<S extends string> = S extends `${infer F}${infer Rest}`\n ? `${Uppercase<F>}${Rest}`\n : S;\n\nconst DEFAULT_PAGINATION: TQueryParams = {\n page: 1,\n limit: 10,\n};\n\n// ============================================================================\n// PHANTOM TYPE CONSTRAINT\n//\n// We constrain S only on the __types phantom property (which is readonly,\n// i.e. covariant) so that ResourceService<string, ...> is assignable to\n// WithResourceTypes. This avoids the variance issue that arises when\n// constraining against method parameter types (contravariant positions).\n//\n// Inside the function we cast apiService once to a fully-typed ResourceService\n// using the phantom generics — this is safe because S IS a ResourceService.\n// ============================================================================\n\ninterface WithResourceTypes {\n readonly __types: {\n id: unknown;\n base: unknown;\n detail: unknown;\n create: unknown;\n update: unknown;\n listRaw: unknown;\n singleRaw: unknown;\n };\n}\n\n// Aliases for reading phantom types from S — keeps the function body readable\ntype Id<S extends WithResourceTypes> = S[\"__types\"][\"id\"];\ntype Base<S extends WithResourceTypes> = S[\"__types\"][\"base\"];\ntype Detail<S extends WithResourceTypes> = S[\"__types\"][\"detail\"];\ntype Create<S extends WithResourceTypes> = S[\"__types\"][\"create\"];\ntype Update<S extends WithResourceTypes> = S[\"__types\"][\"update\"];\ntype ListRaw<S extends WithResourceTypes> = S[\"__types\"][\"listRaw\"];\ntype SingleRaw<S extends WithResourceTypes> = S[\"__types\"][\"singleRaw\"];\n\n// ============================================================================\n// RETURN TYPE — useList\n// Dynamically named keys based on the queryKeyPrefix (e.g. \"contacts\"):\n// { contacts: TBase[], isContactsLoading: boolean, contactsError: Error | null, invalidateContacts: () => void }\n// ============================================================================\n\nexport type UseListReturn<K extends string, TBase> = {\n [P in K]: TBase[];\n} & {\n pagination: TPagination;\n} & {\n [P in `is${CapitalizeStr<K>}Loading`]: boolean;\n} & {\n [P in `${K}Error`]: Error | null;\n} & {\n [P in `invalidate${CapitalizeStr<K>}`]: () => void;\n};\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport interface CreateResourceHooksOptions<\n TListRaw,\n TBase,\n TSingleRaw,\n TDetail,\n> {\n /**\n * Adapters map your API's raw response shapes to the library's internal\n * format. Omit this entirely if your API matches the default shape:\n * List: { data: { items, page, limit, totalPages, totalDocuments } }\n * Single: { data: <item> }\n *\n * @example\n * createResourceHooks(\"contacts\", ContactsApis, {\n * adapters: {\n * fromList: (raw) => ({\n * items: raw.results,\n * pagination: {\n * page: raw.meta.page,\n * limit: raw.meta.perPage,\n * totalPages: raw.meta.lastPage,\n * totalDocuments: raw.meta.total,\n * },\n * }),\n * fromSingle: (raw) => raw.payload,\n * },\n * })\n */\n adapters?: ResourceAdapters<TListRaw, TBase, TSingleRaw, TDetail>;\n\n /**\n * Default params passed to useList and useInfinite when none are provided.\n * @default { page: 1, limit: 10 }\n */\n defaultParams?: TQueryParams;\n}\n\n// ============================================================================\n// FACTORY\n// ============================================================================\n\n/**\n * Creates a set of TanStack Query hooks for a resource.\n * All types are fully inferred from the `apiService` instance — no generics\n * need to be passed manually.\n *\n * @param queryKeyPrefix - TanStack Query cache key prefix and the base name\n * for the returned hook properties.\n * e.g. \"contacts\" → { contacts, isContactsLoading, ... }\n * @param apiService - An instance of ResourceService (or a subclass).\n * @param options - Optional adapters and default params.\n *\n * @example\n * // contacts.hooks.ts\n * import { createResourceHooks } from '@void-snippets/react';\n * import { ContactsApis } from './contacts.api';\n *\n * // No generics needed — all types are inferred from ContactsApis\n * export const contactHooks = createResourceHooks('contacts', ContactsApis);\n *\n * // In a component:\n * const { contacts, isContactsLoading } = contactHooks.useList();\n * const { data } = contactHooks.useGet(id); // data: Contact.WithCreatedBy\n * const { create, update, delete: remove } = contactHooks.useMutations();\n */\nexport function createResourceHooks<\n K extends string,\n S extends WithResourceTypes,\n>(\n queryKeyPrefix: K,\n apiService: S,\n options: CreateResourceHooksOptions<\n ListRaw<S>,\n Base<S>,\n SingleRaw<S>,\n Detail<S>\n > = {},\n) {\n // One safe cast: S is guaranteed to be a ResourceService subclass because\n // __types is only present on ResourceService. Casting here lets us call\n // the service methods with the correct types extracted from the phantom.\n const service = apiService as unknown as ResourceService<\n Id<S>,\n Base<S>,\n Detail<S>,\n Create<S>,\n Update<S>,\n ListRaw<S>,\n SingleRaw<S>\n >;\n\n const {\n adapters = createDefaultAdapters<Base<S>, Detail<S>>() as ResourceAdapters<\n TDefaultPaginatedResponse<Base<S>>,\n Base<S>,\n TDefaultSingleResponse<Detail<S>>,\n Detail<S>\n > as ResourceAdapters<ListRaw<S>, Base<S>, SingleRaw<S>, Detail<S>>,\n defaultParams = DEFAULT_PAGINATION,\n } = options;\n\n const capitalize = (str: string) =>\n str.charAt(0).toUpperCase() + str.slice(1);\n const capPrefix = capitalize(queryKeyPrefix);\n\n return {\n // -------------------------------------------------------------------------\n // useList — paginated list with invalidation helper\n // -------------------------------------------------------------------------\n useList: (\n params: TQueryParams = defaultParams,\n ): UseListReturn<K, Base<S>> => {\n const queryClient = useQueryClient();\n const queryKey = [queryKeyPrefix, params];\n\n const query = useQuery<ResourceListResult<Base<S>>, Error>({\n queryKey,\n queryFn: async () => {\n const raw = await service.list(params);\n return adapters.fromList(raw as ListRaw<S>);\n },\n });\n\n const items = query.data?.items ?? [];\n const pagination: TPagination = query.data?.pagination ?? {\n page: 1,\n limit: defaultParams.limit ?? 10,\n totalPages: 0,\n totalDocuments: 0,\n };\n\n return {\n [queryKeyPrefix]: items,\n pagination,\n [`is${capPrefix}Loading`]: query.isLoading || query.isFetching,\n [`${queryKeyPrefix}Error`]: query.error,\n [`invalidate${capPrefix}`]: () =>\n queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] }),\n } as UseListReturn<K, Base<S>>;\n },\n\n // -------------------------------------------------------------------------\n // useGet — single item by id\n // -------------------------------------------------------------------------\n useGet: (id: Id<S>, staleTime = 30_000) => {\n const query = useQuery<Detail<S>, Error>({\n queryKey: [queryKeyPrefix, id],\n queryFn: async () => {\n const raw = await service.get(id);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n enabled: id !== undefined && id !== null && id !== \"\",\n staleTime,\n });\n\n return {\n data: query.data,\n isLoading: query.isLoading || query.isFetching,\n error: query.error,\n refetch: query.refetch,\n };\n },\n\n // -------------------------------------------------------------------------\n // useMutations — create / update / delete with auto-invalidation\n // -------------------------------------------------------------------------\n useMutations: () => {\n const queryClient = useQueryClient();\n const invalidate = () =>\n queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] });\n\n const createMutation = useMutation<Detail<S>, Error, Create<S>>({\n mutationFn: async (payload) => {\n const raw = await service.create(payload);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n const updateMutation = useMutation<\n Detail<S>,\n Error,\n { _id: Id<S>; payload: Update<S> }\n >({\n mutationFn: async ({ _id, payload }) => {\n const raw = await service.update(_id, payload);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n const deleteMutation = useMutation<Detail<S>, Error, Id<S>>({\n mutationFn: async (_id) => {\n const raw = await service.delete(_id);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n return {\n create: createMutation,\n update: updateMutation,\n delete: deleteMutation,\n };\n },\n\n // -------------------------------------------------------------------------\n // useInfinite — infinite scroll / load more\n // -------------------------------------------------------------------------\n useInfinite: (params: TQueryParams = defaultParams) => {\n return useInfiniteQuery<ResourceListResult<Base<S>>, Error>({\n queryKey: [queryKeyPrefix, \"INFINITE\", params],\n queryFn: async ({ pageParam }) => {\n const raw = await service.list({\n ...params,\n page: pageParam as number,\n limit: params.limit ?? 20,\n });\n return adapters.fromList(raw as ListRaw<S>);\n },\n getNextPageParam: (lastPage) => {\n const { page, totalPages } = lastPage.pagination;\n return page < totalPages ? page + 1 : undefined;\n },\n initialPageParam: 1,\n });\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/hooks/createResourceHooks.ts","../src/hooks/useAlertMessage.ts","../src/hooks/useAsyncState.ts","../src/hooks/useCallTimer.ts","../src/hooks/useModal.ts","../src/hooks/usePagination.ts"],"sourcesContent":["import {\n useInfiniteQuery,\n useMutation,\n useQuery,\n useQueryClient,\n} from \"@tanstack/react-query\";\nimport type { ResourceService } from \"@void-snippets/client\";\nimport type {\n VSAdapters,\n VSListResult,\n VSPagination,\n VSQueryParams,\n VSDefaultPaginatedResponse,\n VSDefaultSingleResponse,\n} from \"@void-snippets/core\";\nimport { createDefaultAdapters } from \"@void-snippets/core\";\n\n// ============================================================================\n// TYPE HELPERS\n// ============================================================================\n\nconst DEFAULT_PAGINATION: VSQueryParams = {\n page: 1,\n limit: 10,\n};\n\n// ============================================================================\n// PHANTOM TYPE CONSTRAINT\n//\n// We constrain S only on the __types phantom property (readonly = covariant)\n// so ResourceService<string, ...> is always assignable to WithResourceTypes.\n// This avoids the variance issue from constraining method parameter types.\n// ============================================================================\n\ninterface WithResourceTypes {\n readonly __types: {\n id: unknown;\n base: unknown;\n detail: unknown;\n create: unknown;\n update: unknown;\n listRaw: unknown;\n singleRaw: unknown;\n };\n}\n\ntype Id<S extends WithResourceTypes> = S[\"__types\"][\"id\"];\ntype Base<S extends WithResourceTypes> = S[\"__types\"][\"base\"];\ntype Detail<S extends WithResourceTypes> = S[\"__types\"][\"detail\"];\ntype Create<S extends WithResourceTypes> = S[\"__types\"][\"create\"];\ntype Update<S extends WithResourceTypes> = S[\"__types\"][\"update\"];\ntype ListRaw<S extends WithResourceTypes> = S[\"__types\"][\"listRaw\"];\ntype SingleRaw<S extends WithResourceTypes> = S[\"__types\"][\"singleRaw\"];\n\n// ============================================================================\n// RETURN TYPES\n// ============================================================================\n\nexport interface VSUseListReturn<TBase> {\n list: TBase[];\n pagination: VSPagination;\n isLoading: boolean;\n error: Error | null;\n invalidate: () => void;\n}\n\nexport interface VSUseGetReturn<TDetail> {\n item: TDetail | undefined;\n isLoading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport interface VSResourceHooksOptions<TListRaw, TBase, TSingleRaw, TDetail> {\n /**\n * Adapters map your API's raw response to the library's internal format.\n * Omit if your API matches the default shape:\n * List: { data: { items, page, limit, totalPages, totalDocuments } }\n * Single: { data: <item> }\n *\n * @example\n * createResourceHooks(\"contacts\", ContactsApis, {\n * adapters: {\n * fromList: (raw) => ({\n * items: raw.results,\n * pagination: {\n * page: raw.meta.page,\n * limit: raw.meta.perPage,\n * totalPages: raw.meta.lastPage,\n * totalDocuments: raw.meta.total,\n * },\n * }),\n * fromSingle: (raw) => raw.payload,\n * },\n * })\n */\n adapters?: VSAdapters<TListRaw, TBase, TSingleRaw, TDetail>;\n\n /**\n * Default params passed to useList and useInfinite when none are provided.\n * @default { page: 1, limit: 10 }\n */\n defaultParams?: VSQueryParams;\n}\n\n// ============================================================================\n// FACTORY\n// ============================================================================\n\n/**\n * Creates a set of TanStack Query hooks for a resource.\n * All types are fully inferred from the `apiService` instance — no generics needed.\n *\n * @param queryKeyPrefix - TanStack Query cache key. Used to scope the cache\n * and for auto-invalidation. e.g. \"contacts\"\n * @param apiService - An instance of ResourceService (or a subclass).\n * @param options - Optional adapters and default params.\n *\n * @example\n * export const contactHooks = createResourceHooks('contacts', ContactsApis);\n *\n * // useList — generic fixed shape\n * const { list, isLoading, pagination, error, invalidate } = contactHooks.useList();\n * // list is typed as Contact.Base[] ✅\n *\n * // useGet\n * const { item, isLoading, error, refetch } = contactHooks.useGet(id);\n * // item is typed as Contact.WithCreatedBy ✅\n *\n * // useMutations\n * const { create, update, remove } = contactHooks.useMutations();\n */\nexport function createResourceHooks<\n K extends string,\n S extends WithResourceTypes,\n>(\n queryKeyPrefix: K,\n apiService: S,\n options: VSResourceHooksOptions<\n ListRaw<S>,\n Base<S>,\n SingleRaw<S>,\n Detail<S>\n > = {},\n) {\n const service = apiService as unknown as ResourceService<\n Id<S>, Base<S>, Detail<S>, Create<S>, Update<S>, ListRaw<S>, SingleRaw<S>\n >;\n\n const {\n adapters = createDefaultAdapters<Base<S>, Detail<S>>() as VSAdapters<\n VSDefaultPaginatedResponse<Base<S>>,\n Base<S>,\n VSDefaultSingleResponse<Detail<S>>,\n Detail<S>\n > as VSAdapters<ListRaw<S>, Base<S>, SingleRaw<S>, Detail<S>>,\n defaultParams = DEFAULT_PAGINATION,\n } = options;\n\n return {\n // -------------------------------------------------------------------------\n // useList — fixed generic shape: { list, isLoading, pagination, error, invalidate }\n // -------------------------------------------------------------------------\n useList: (\n params: VSQueryParams = defaultParams,\n ): VSUseListReturn<Base<S>> => {\n const queryClient = useQueryClient();\n\n const query = useQuery<VSListResult<Base<S>>, Error>({\n queryKey: [queryKeyPrefix, params],\n queryFn: async () => {\n const raw = await service.list(params);\n return adapters.fromList(raw as ListRaw<S>);\n },\n });\n\n return {\n list: query.data?.items ?? [],\n pagination: query.data?.pagination ?? {\n page: 1,\n limit: defaultParams.limit ?? 10,\n totalPages: 0,\n totalDocuments: 0,\n },\n isLoading: query.isLoading || query.isFetching,\n error: query.error,\n invalidate: () =>\n queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] }),\n };\n },\n\n // -------------------------------------------------------------------------\n // useGet — { item, isLoading, error, refetch }\n // -------------------------------------------------------------------------\n useGet: (id: Id<S>, staleTime = 30_000): VSUseGetReturn<Detail<S>> => {\n const query = useQuery<Detail<S>, Error>({\n queryKey: [queryKeyPrefix, id],\n queryFn: async () => {\n const raw = await service.get(id);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n enabled: id !== undefined && id !== null && id !== \"\",\n staleTime,\n });\n\n return {\n item: query.data,\n isLoading: query.isLoading || query.isFetching,\n error: query.error,\n refetch: query.refetch,\n };\n },\n\n // -------------------------------------------------------------------------\n // useMutations — create / update / remove (not delete — reserved keyword)\n // -------------------------------------------------------------------------\n useMutations: () => {\n const queryClient = useQueryClient();\n const invalidate = () =>\n queryClient.invalidateQueries({ queryKey: [queryKeyPrefix] });\n\n const createMutation = useMutation<Detail<S>, Error, Create<S>>({\n mutationFn: async (payload) => {\n const raw = await service.create(payload);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n const updateMutation = useMutation<\n Detail<S>,\n Error,\n { _id: Id<S>; payload: Update<S> }\n >({\n mutationFn: async ({ _id, payload }) => {\n const raw = await service.update(_id, payload);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n const removeMutation = useMutation<Detail<S>, Error, Id<S>>({\n mutationFn: async (_id) => {\n const raw = await service.delete(_id);\n return adapters.fromSingle(raw as SingleRaw<S>);\n },\n onSuccess: invalidate,\n });\n\n return {\n create: createMutation,\n update: updateMutation,\n remove: removeMutation,\n };\n },\n\n // -------------------------------------------------------------------------\n // useInfinite — infinite scroll / load more\n // -------------------------------------------------------------------------\n useInfinite: (params: VSQueryParams = defaultParams) => {\n return useInfiniteQuery<VSListResult<Base<S>>, Error>({\n queryKey: [queryKeyPrefix, \"INFINITE\", params],\n queryFn: async ({ pageParam }) => {\n const raw = await service.list({\n ...params,\n page: pageParam as number,\n limit: params.limit ?? 20,\n });\n return adapters.fromList(raw as ListRaw<S>);\n },\n getNextPageParam: (lastPage) => {\n const { page, totalPages } = lastPage.pagination;\n return page < totalPages ? page + 1 : undefined;\n },\n initialPageParam: 1,\n });\n },\n };\n}\n","import { type ReactNode, useCallback, useState } from \"react\";\n\nexport type VSAlertVariant = \"success\" | \"info\" | \"error\";\n\nexport interface VSAlertState {\n message: ReactNode | string;\n type: VSAlertVariant;\n isVisible: boolean;\n}\n\n/**\n * Manages alert/toast message state with optional auto-hide.\n *\n * @param autoHideDuration - ms before alert hides automatically. Pass 0 to disable. Default: 3000\n *\n * @example\n * const { alert, showAlert, hideAlert } = useAlertMessage();\n * showAlert('Saved successfully!', 'success');\n * showAlert(<b>Something went wrong</b>, 'error');\n */\nexport function useAlertMessage(autoHideDuration = 3000) {\n const [alert, setAlert] = useState<VSAlertState>({\n message: null,\n type: \"info\",\n isVisible: false,\n });\n\n const showAlert = useCallback(\n (message: ReactNode | string, type: VSAlertVariant = \"info\") => {\n setAlert({ message, type, isVisible: true });\n if (autoHideDuration) {\n setTimeout(() => {\n setAlert((prev) => ({ ...prev, isVisible: false }));\n }, autoHideDuration);\n }\n },\n [autoHideDuration]\n );\n\n const hideAlert = useCallback(() => {\n setAlert((prev) => ({ ...prev, isVisible: false }));\n }, []);\n\n return { alert, showAlert, hideAlert };\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { catchError } from \"@void-snippets/core\";\n\nexport type VSAsyncStatus = \"idle\" | \"pending\" | \"success\" | \"error\";\n\ninterface VSAsyncState<T> {\n data: T | null;\n status: VSAsyncStatus;\n error: Error | null;\n}\n\nexport interface VSUseAsyncStateReturn<T> extends VSAsyncState<T> {\n isLoading: boolean;\n isSuccess: boolean;\n isError: boolean;\n\n setData: (data: T | null) => void;\n setError: (error: Error | null) => void;\n reset: () => void;\n\n /**\n * Executes an async function, updates state, and returns a [err, data] tuple.\n * Allows immediate result handling without try/catch.\n *\n * @example\n * const [err, data] = await execute(() => ContactsApis.create(payload));\n * if (err) return showAlert(err.message, 'error');\n * showAlert('Created!', 'success');\n */\n execute: (\n asyncFn: () => Promise<T>,\n options?: {\n onSuccess?: (data: T) => void;\n onError?: (error: Error) => void;\n }\n ) => Promise<[Error, null] | [null, T]>;\n}\n\n/**\n * Generic async state machine — tracks data, status, and error for any async operation.\n * Pair with any async function: API calls, file reads, timers, etc.\n *\n * @param initialData - Optional initial data value. Default: null\n *\n * @example\n * const { data, isLoading, isError, execute } = useAsyncState<User>();\n *\n * const handleSubmit = async () => {\n * const [err, user] = await execute(() => fetchUser(id));\n * if (err) return;\n * console.log(user.name);\n * };\n */\nexport function useAsyncState<T>(\n initialData: T | null = null\n): VSUseAsyncStateReturn<T> {\n const [state, setState] = useState<VSAsyncState<T>>({\n data: initialData,\n status: \"idle\",\n error: null,\n });\n\n const setData = useCallback((data: T | null) => {\n setState({ data, status: \"success\", error: null });\n }, []);\n\n const setError = useCallback((error: Error | null) => {\n setState((prev) => ({ ...prev, error, status: \"error\" }));\n }, []);\n\n const reset = useCallback(() => {\n setState({ data: initialData, status: \"idle\", error: null });\n }, [initialData]);\n\n const execute = useCallback(\n async (\n asyncFn: () => Promise<T>,\n options?: {\n onSuccess?: (data: T) => void;\n onError?: (error: Error) => void;\n }\n ): Promise<[Error, null] | [null, T]> => {\n setState((prev) => ({ ...prev, status: \"pending\", error: null }));\n\n const [err, res] = await catchError(asyncFn());\n\n if (err) {\n setState((prev) => ({ ...prev, status: \"error\", error: err }));\n options?.onError?.(err);\n return [err, null];\n }\n\n setState({ data: res as T, status: \"success\", error: null });\n options?.onSuccess?.(res as T);\n return [null, res as T];\n },\n []\n );\n\n const flags = useMemo(\n () => ({\n isLoading: state.status === \"pending\",\n isSuccess: state.status === \"success\",\n isError: state.status === \"error\",\n }),\n [state.status]\n );\n\n return { ...state, ...flags, setData, setError, reset, execute };\n}\n","import { useEffect, useState } from \"react\";\n\n/**\n * Tracks elapsed time from a given start timestamp — useful for call durations,\n * countdowns, or any elapsed-time display.\n *\n * @param startedAt - Unix timestamp in ms (e.g. Date.now()). Pass null/undefined to reset.\n * @returns Formatted duration string \"MM:SS\"\n *\n * @example\n * const duration = useCallTimer(call.startedAt);\n * // duration → \"02:45\"\n *\n * // Reset when no active call\n * const duration = useCallTimer(activeCall ? activeCall.startedAt : null);\n */\nexport function useCallTimer(startedAt?: number | null): string {\n const [duration, setDuration] = useState(\"00:00\");\n\n useEffect(() => {\n if (!startedAt) {\n setDuration(\"00:00\");\n return;\n }\n\n const interval = setInterval(() => {\n const diffInSeconds = Math.floor((Date.now() - startedAt) / 1000);\n const minutes = Math.floor(diffInSeconds / 60).toString().padStart(2, \"0\");\n const seconds = (diffInSeconds % 60).toString().padStart(2, \"0\");\n setDuration(`${minutes}:${seconds}`);\n }, 1000);\n\n return () => clearInterval(interval);\n }, [startedAt]);\n\n return duration;\n}\n","import { useCallback, useState } from \"react\";\n\nexport interface VSModalReturn<T> {\n isOpen: boolean;\n data: T | null;\n isLoading: boolean;\n openCreateModal: () => void;\n openEditModal: (editData: T) => void;\n setLoading: (loading: boolean) => void;\n closeModal: () => void;\n setModal: (open: boolean, editData?: T | null) => void;\n}\n\n/**\n * Manages modal open/close state with optional data payload and loading state.\n * Works for both create and edit modals — pass data to distinguish the mode.\n *\n * @typeParam T - The type of data the modal operates on (e.g. a Contact, User, etc.)\n *\n * @example\n * const modal = useModal<Contact.Base>();\n *\n * modal.openCreateModal(); // data → null (create mode)\n * modal.openEditModal(contact); // data → contact (edit mode)\n *\n * if (modal.data) {\n * // Edit mode — modal.data is Contact.Base\n * } else {\n * // Create mode\n * }\n */\nexport function useModal<T = unknown>(): VSModalReturn<T> {\n const [isOpen, setIsOpen] = useState(false);\n const [data, setData] = useState<T | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const openCreateModal = useCallback(() => {\n setIsOpen(true);\n setData(null);\n }, []);\n\n const openEditModal = useCallback((editData: T) => {\n setIsOpen(true);\n setData(editData);\n }, []);\n\n const setLoading = useCallback((loading: boolean) => {\n setIsLoading(loading);\n }, []);\n\n const closeModal = useCallback(() => {\n setIsOpen(false);\n setData(null);\n }, []);\n\n const setModal = useCallback((open: boolean, editData?: T | null) => {\n setIsOpen(open);\n setData(editData ?? null);\n }, []);\n\n return {\n isOpen,\n data,\n isLoading,\n openCreateModal,\n openEditModal,\n setLoading,\n closeModal,\n setModal,\n };\n}\n","import { useCallback, useState } from \"react\";\nimport type { VSQueryParams } from \"@void-snippets/core\";\n\nexport interface VSPaginationReturn {\n page: number;\n limit: number;\n onPaginationChange: (newPage: number, newLimit: number) => void;\n resetPagination: () => void;\n setPage: (page: number) => void;\n setLimit: (limit: number) => void;\n /** Ready-to-use query params object — pass directly to useList() */\n queryParams: VSQueryParams;\n}\n\n/**\n * Manages pagination state and produces a ready-to-use queryParams object\n * compatible with createResourceHooks' useList() and useInfinite().\n *\n * @param initialPage - Starting page. Default: 1\n * @param initialLimit - Items per page. Default: 10\n *\n * @example\n * const { queryParams, onPaginationChange } = usePagination(1, 20);\n *\n * const { list, isLoading } = contactHooks.useList(queryParams);\n *\n * <Pagination onChange={onPaginationChange} total={pagination.totalDocuments} />\n */\nexport function usePagination(\n initialPage = 1,\n initialLimit = 10\n): VSPaginationReturn {\n const [page, setPage] = useState(initialPage);\n const [limit, setLimit] = useState(initialLimit);\n\n const onPaginationChange = useCallback(\n (newPage: number, newLimit: number) => {\n setPage(newPage);\n setLimit(newLimit);\n },\n []\n );\n\n const resetPagination = useCallback(() => {\n setPage(1);\n }, []);\n\n return {\n page,\n limit,\n onPaginationChange,\n resetPagination,\n setPage,\n setLimit,\n queryParams: { page, limit },\n };\n}\n"],"mappings":"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","names":["useCallback","useState","useState","useCallback","useState","useCallback","useState"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@void-snippets/react",
3
- "version": "0.2.2",
4
- "description": "TanStack Query resource hooks factory for React",
3
+ "version": "0.3.0",
4
+ "description": "TanStack Query resource hooks factory and general-purpose React hooks",
5
5
  "homepage": "https://github.com/shahtirthhh/void-snippets",
6
6
  "repository": {
7
7
  "type": "git",
@@ -30,7 +30,12 @@
30
30
  "react-query",
31
31
  "hooks",
32
32
  "api",
33
- "void-snippets"
33
+ "void-snippets",
34
+ "useModal",
35
+ "usePagination",
36
+ "useAsyncState",
37
+ "useAlertMessage",
38
+ "useCallTimer"
34
39
  ],
35
40
  "license": "MIT",
36
41
  "peerDependencies": {
@@ -39,7 +44,7 @@
39
44
  },
40
45
  "dependencies": {
41
46
  "@tanstack/react-query": "^5.0.0",
42
- "@void-snippets/core": "0.2.2"
47
+ "@void-snippets/core": "0.3.0"
43
48
  },
44
49
  "devDependencies": {
45
50
  "@types/react": "^18.0.0",