@izumisy-tailor/tailor-data-viewer 0.2.4 → 0.2.6

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@izumisy-tailor/tailor-data-viewer",
3
3
  "private": false,
4
- "version": "0.2.4",
4
+ "version": "0.2.6",
5
5
  "type": "module",
6
6
  "description": "Flexible data viewer component for Tailor Platform",
7
7
  "files": [
@@ -1,9 +1,10 @@
1
1
  import { createContext, useContext, type ReactNode } from "react";
2
2
  import type { UseCollectionParamsReturn } from "../types";
3
3
 
4
- const CollectionParamsContext = createContext<UseCollectionParamsReturn | null>(
5
- null,
6
- );
4
+ const CollectionParamsContext = createContext<UseCollectionParamsReturn<
5
+ string,
6
+ unknown
7
+ > | null>(null);
7
8
 
8
9
  /**
9
10
  * Provider that shares collection query parameters via React Context.
@@ -23,7 +24,7 @@ export function CollectionParamsProvider({
23
24
  value,
24
25
  children,
25
26
  }: {
26
- value: UseCollectionParamsReturn;
27
+ value: UseCollectionParamsReturn<string, unknown>;
27
28
  children: ReactNode;
28
29
  }) {
29
30
  return (
@@ -10,6 +10,7 @@ import type {
10
10
  SortState,
11
11
  UseCollectionParamsOptions,
12
12
  UseCollectionParamsReturn,
13
+ ExtractQueryVariables,
13
14
  } from "../types";
14
15
  import { fieldTypeToFilterConfig } from "../types";
15
16
  import type { FieldName } from "../types";
@@ -22,29 +23,46 @@ import type { FieldName } from "../types";
22
23
  * Hook for managing collection query parameters (filters, sort, pagination)
23
24
  * with metadata-based field name typing and automatic `fieldType` detection.
24
25
  *
26
+ * When `query` is provided, the output `variables` is typed to match
27
+ * the GraphQL query's expected variables (e.g. `VariablesOf<typeof QUERY>`).
28
+ * The `query` value is only used for type inference and ignored at runtime.
29
+ *
25
30
  * @example
26
31
  * ```tsx
27
32
  * import { tableMetadata } from "./generated/data-viewer-metadata.generated";
28
33
  *
34
+ * // Without query — variables typed as QueryVariables<FieldName>
29
35
  * const params = useCollectionParams({
30
36
  * metadata: tableMetadata,
31
37
  * tableName: "task",
32
38
  * pageSize: 20,
33
39
  * });
34
40
  *
35
- * params.addFilter("title", "foo"); // field name auto-completed
36
- * params.addFilter("nonExistent", "foo"); // ❌ type error
41
+ * // With query variables typed as VariablesOf<typeof GET_TASKS>
42
+ * const params = useCollectionParams({
43
+ * metadata: tableMetadata,
44
+ * tableName: "task",
45
+ * query: GET_TASKS,
46
+ * pageSize: 20,
47
+ * });
37
48
  * ```
38
49
  */
39
50
  export function useCollectionParams<
40
51
  const TMetadata extends TableMetadataMap,
41
52
  TTableName extends string & keyof TMetadata,
53
+ TQuery = never,
42
54
  >(
43
55
  options: UseCollectionParamsOptions<FieldName<TMetadata, TTableName>> & {
44
56
  metadata: TMetadata;
45
57
  tableName: TTableName;
58
+ query?: TQuery;
46
59
  },
47
- ): UseCollectionParamsReturn<FieldName<TMetadata, TTableName>>;
60
+ ): UseCollectionParamsReturn<
61
+ FieldName<TMetadata, TTableName>,
62
+ [TQuery] extends [never]
63
+ ? QueryVariables<FieldName<TMetadata, TTableName>>
64
+ : ExtractQueryVariables<TQuery>
65
+ >;
48
66
 
49
67
  /**
50
68
  * Hook for managing collection query parameters (filters, sort, pagination).
@@ -52,15 +70,28 @@ export function useCollectionParams<
52
70
  * Produces `variables` in Tailor Platform format that can be passed directly
53
71
  * to a GraphQL query (e.g. urql's `useQuery`).
54
72
  *
73
+ * When `query` is provided, the output `variables` is typed to match
74
+ * the GraphQL query's expected variables.
75
+ *
55
76
  * @example
56
77
  * ```tsx
57
78
  * const params = useCollectionParams({ pageSize: 20 });
58
79
  * const [result] = useQuery({ query: GET_ORDERS, variables: params.variables });
80
+ *
81
+ * // With query — variables auto-typed
82
+ * const params = useCollectionParams({ query: GET_ORDERS, pageSize: 20 });
59
83
  * ```
60
84
  */
61
- export function useCollectionParams(
62
- options?: UseCollectionParamsOptions,
63
- ): UseCollectionParamsReturn;
85
+ export function useCollectionParams<TQuery = never>(
86
+ options?: UseCollectionParamsOptions & {
87
+ query?: TQuery;
88
+ metadata?: never;
89
+ tableName?: never;
90
+ },
91
+ ): UseCollectionParamsReturn<
92
+ string,
93
+ [TQuery] extends [never] ? QueryVariables : ExtractQueryVariables<TQuery>
94
+ >;
64
95
 
65
96
  // -----------------------------------------------------------------------------
66
97
  // Implementation
@@ -27,6 +27,9 @@ export type {
27
27
  DataTableRowProps,
28
28
  DataTableCellProps,
29
29
  FieldName,
30
+ ExtractOrderField,
31
+ ExtractQueryVariables,
32
+ MatchingTableName,
30
33
  MetadataFieldOptions,
31
34
  MetadataFieldsOptions,
32
35
  ColumnSelectorProps,
@@ -290,10 +290,16 @@ export interface UseCollectionParamsOptions<
290
290
  * `UseCollectionParamsReturn<string>` (bivariant method check).
291
291
  *
292
292
  * @typeParam TFieldName - Union of allowed field name strings (default: `string`).
293
+ * @typeParam TVariables - Type of the `variables` output (default: `QueryVariables<TFieldName>`).
294
+ * Pass `VariablesOf<typeof YOUR_QUERY>` (gql-tada) to get
295
+ * exact type compatibility with your GraphQL client.
293
296
  */
294
- export interface UseCollectionParamsReturn<TFieldName extends string = string> {
297
+ export interface UseCollectionParamsReturn<
298
+ TFieldName extends string = string,
299
+ TVariables = QueryVariables<TFieldName>,
300
+ > {
295
301
  /** Query variables in Tailor Platform format */
296
- variables: QueryVariables<TFieldName>;
302
+ variables: TVariables;
297
303
 
298
304
  // Filter operations
299
305
  /** Current active filters */
@@ -351,7 +357,7 @@ export interface UseDataTableOptions<TRow extends Record<string, unknown>> {
351
357
  /** Error */
352
358
  error?: Error | null;
353
359
  /** Collection params for sort integration */
354
- collectionParams?: UseCollectionParamsReturn;
360
+ collectionParams?: UseCollectionParamsReturn<string, unknown>;
355
361
  }
356
362
 
357
363
  /**
@@ -480,6 +486,66 @@ export type FieldName<
480
486
  : never
481
487
  : never;
482
488
 
489
+ /**
490
+ * Extract the `order[].field` union type from a GraphQL variables type.
491
+ *
492
+ * For gql-tada's `VariablesOf<typeof QUERY>`, this extracts the allowed
493
+ * field names from the `order` parameter.
494
+ *
495
+ * @example
496
+ * ```ts
497
+ * type Fields = ExtractOrderField<VariablesOf<typeof GET_ORDERS>>;
498
+ * // → "name" | "amount" | "status" | "createdAt"
499
+ * ```
500
+ */
501
+ export type ExtractOrderField<T> = T extends {
502
+ order?: readonly (infer O | null | undefined)[] | null | undefined;
503
+ }
504
+ ? O extends { field?: infer F | null }
505
+ ? NonNullable<F> & string
506
+ : string
507
+ : string;
508
+
509
+ /**
510
+ * Extract the variables type from a GraphQL query object.
511
+ *
512
+ * Works with `TypedDocumentNode` (used by gql-tada, graphql-codegen, etc.)
513
+ * which stores the variables type in the `__variablesType` brand property.
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * const GET_ORDERS = graphql(`query Orders($first: Int, ...) { ... }`);
518
+ * type Vars = ExtractQueryVariables<typeof GET_ORDERS>;
519
+ * // → { first?: number | null; order?: OrderInput[] | null; ... }
520
+ * ```
521
+ */
522
+ export type ExtractQueryVariables<T> = T extends {
523
+ __variablesType?: infer V;
524
+ }
525
+ ? NonNullable<V>
526
+ : never;
527
+
528
+ /**
529
+ * Find table names in metadata whose fields are a superset of `TFieldName`.
530
+ *
531
+ * Used to constrain `tableName` so that it matches the `order[].field`
532
+ * union extracted from `VariablesOf<>`.
533
+ *
534
+ * @example
535
+ * ```ts
536
+ * type T = MatchingTableName<typeof tableMetadata, "name" | "email">;
537
+ * // → "buyerContact" (if buyerContact's fields include name and email)
538
+ * ```
539
+ */
540
+ export type MatchingTableName<
541
+ TMetadata extends TableMetadataMap,
542
+ TFieldName extends string,
543
+ > = {
544
+ [K in string & keyof TMetadata]: TFieldName extends FieldName<TMetadata, K>
545
+ ? K
546
+ : never;
547
+ }[string & keyof TMetadata];
548
+
483
549
  /**
484
550
  * Options for metadata-based single field definition.
485
551
  */