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

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/README.md CHANGED
@@ -5,8 +5,8 @@ A low-level React component library for building data table interfaces with Tail
5
5
  ## Features
6
6
 
7
7
  - **Separation of Concerns**: Data fetching, query parameter management, and UI are fully decoupled
8
- - **`useCollectionParams` Hook**: Manages filter, sort, and pagination state; outputs Tailor Platform-compatible GraphQL variables
9
- - **`CollectionParams.Provider`**: Shares query parameters via React Context across sibling components
8
+ - **`useCollection` Hook**: Manages filter, sort, and pagination state; outputs Tailor Platform-compatible GraphQL variables
9
+ - **`Collection.Provider`**: Shares query parameters via React Context across sibling components
10
10
  - **`Table.*` Compound Components**: Static, unstyled table primitives (`<table>`, `<thead>`, `<tbody>`, `<tr>`, `<th>`, `<td>`)
11
11
  - **`DataTable.*` Compound Components**: Data-bound table with sort indicators, cell renderers, and `useDataTable` integration
12
12
  - **`useDataTable` Hook**: Integrates data, column visibility, row operations (optimistic updates), and props generators
@@ -15,7 +15,7 @@ A low-level React component library for building data table interfaces with Tail
15
15
  - **Utility Components**: `ColumnSelector`, `CsvButton`, `SearchFilterForm`, `Pagination` — all props-based, spreadable from hooks
16
16
  - **Multi-sort Support**: Multiple simultaneous sort fields
17
17
  - **Optimistic Updates**: `updateRow`, `deleteRow`, `insertRow` with rollback
18
- - **Presentation Agnostic**: Same `useCollectionParams` can drive tables, kanbans, calendars, etc.
18
+ - **Presentation Agnostic**: Same `useCollection` can drive tables, kanbans, calendars, etc.
19
19
 
20
20
  ## Installation
21
21
 
@@ -47,9 +47,9 @@ npm install react react-dom
47
47
 
48
48
  ```tsx
49
49
  import {
50
- useCollectionParams,
50
+ useCollection,
51
51
  useDataTable,
52
- CollectionParams,
52
+ Collection,
53
53
  DataTable,
54
54
  Pagination,
55
55
  field,
@@ -87,73 +87,76 @@ const columns = [
87
87
 
88
88
  // 2. Build a page
89
89
  function OrdersPage() {
90
- const params = useCollectionParams({ pageSize: 20 });
91
- const [result] = useQuery({ query: GET_ORDERS, variables: params.variables });
90
+ const collection = useCollection({ query: GET_ORDERS, params: { pageSize: 20 } });
91
+ const [result] = useQuery({ ...collection.toQueryArgs() });
92
92
 
93
93
  const table = useDataTable<Order>({
94
94
  columns,
95
95
  data: result.data?.orders,
96
96
  loading: result.fetching,
97
- collectionParams: params,
97
+ collection,
98
98
  });
99
99
 
100
100
  return (
101
- <CollectionParams.Provider value={params}>
101
+ <Collection.Provider value={collection}>
102
102
  <DataTable.Root {...table.rootProps}>
103
103
  <DataTable.Headers />
104
104
  <DataTable.Body />
105
105
  </DataTable.Root>
106
106
  <Pagination {...table} />
107
- </CollectionParams.Provider>
107
+ </Collection.Provider>
108
108
  );
109
109
  }
110
110
  ```
111
111
 
112
112
  ## API Overview
113
113
 
114
- ### `useCollectionParams(options?)`
114
+ ### `useCollection(options)`
115
115
 
116
- Manages filter, sort, and pagination state. Returns Tailor Platform-compatible `variables` for GraphQL queries.
116
+ Manages filter, sort, and pagination state. Returns `toQueryArgs()` which produces Tailor Platform-compatible arguments for `useQuery()`.
117
117
 
118
118
  ```tsx
119
- const params = useCollectionParams({
120
- pageSize: 20,
121
- initialSort: [{ field: "createdAt", direction: "Desc" }],
119
+ const collection = useCollection({
120
+ query: GET_ORDERS,
121
+ params: {
122
+ pageSize: 20,
123
+ initialSort: [{ field: "createdAt", direction: "Desc" }],
124
+ },
122
125
  });
123
126
 
124
- // Pass variables to any GraphQL client
125
- const [result] = useQuery({ query: GET_ORDERS, variables: params.variables });
127
+ // Spread toQueryArgs() into useQuery
128
+ const [result] = useQuery({ ...collection.toQueryArgs() });
126
129
 
127
130
  // Filter operations
128
- params.addFilter("status", "ACTIVE", "eq");
129
- params.setFilters([{ field: "status", fieldType: "enum", operator: "eq", value: "ACTIVE" }]);
130
- params.removeFilter("status");
131
- params.clearFilters();
131
+ collection.addFilter("status", "ACTIVE", "eq");
132
+ collection.setFilters([{ field: "status", fieldType: "enum", operator: "eq", value: "ACTIVE" }]);
133
+ collection.removeFilter("status");
134
+ collection.clearFilters();
132
135
 
133
136
  // Sort operations
134
- params.setSort("createdAt", "Desc");
135
- params.setSort("name", "Asc", true); // append for multi-sort
136
- params.clearSort();
137
+ collection.setSort("createdAt", "Desc");
138
+ collection.setSort("name", "Asc", true); // append for multi-sort
139
+ collection.clearSort();
137
140
 
138
141
  // Pagination
139
- params.nextPage(endCursor);
140
- params.prevPage();
141
- params.resetPage();
142
+ collection.nextPage(endCursor);
143
+ collection.prevPage();
144
+ collection.resetPage();
142
145
  ```
143
146
 
144
- ### `CollectionParams.Provider` / `useCollectionParamsContext()`
147
+ ### `Collection.Provider` / `useCollectionContext()`
145
148
 
146
- Shares `useCollectionParams` return value via Context. Child components access it with `useCollectionParamsContext()`.
149
+ Shares `useCollection` return value via Context. Child components access it with `useCollectionContext()`.
147
150
 
148
151
  ```tsx
149
- <CollectionParams.Provider value={params}>
150
- <StatusFilter /> {/* useCollectionParamsContext() inside */}
152
+ <Collection.Provider value={collection}>
153
+ <StatusFilter /> {/* useCollectionContext() inside */}
151
154
  <DataTable.Root {...table.rootProps}>
152
155
  <DataTable.Headers />
153
156
  <DataTable.Body />
154
157
  </DataTable.Root>
155
158
  <Pagination {...table} />
156
- </CollectionParams.Provider>
159
+ </Collection.Provider>
157
160
  ```
158
161
 
159
162
  Provider is optional — for simple cases, pass params directly via props.
@@ -246,7 +249,7 @@ const table = useDataTable<Order>({
246
249
  data: result.data?.orders, // CollectionResult<Order>
247
250
  loading: result.fetching,
248
251
  error: result.error,
249
- collectionParams: params,
252
+ collection,
250
253
  });
251
254
 
252
255
  // Spread props to components
@@ -320,17 +323,17 @@ Pair with `useDataTable` for automatic header sorting, cell rendering, and row o
320
323
 
321
324
  ### Utility Components
322
325
 
323
- All utility components are props-based and designed to be used with spread from `useDataTable` / `useCollectionParams`.
326
+ All utility components are props-based and designed to be used with spread from `useDataTable` / `useCollection`.
324
327
 
325
328
  | Component | Spread from | Description |
326
329
  |-----------|------------|-------------|
327
330
  | `ColumnSelector` | `{...table}` | Column visibility toggle UI |
328
331
  | `CsvButton` | `{...table}` | Export visible data as CSV |
329
- | `SearchFilterForm` | `{...table, ...params}` | Multi-field filter form with operator selection |
332
+ | `SearchFilterForm` | `{...table, ...collection}` | Multi-field filter form with operator selection |
330
333
  | `Pagination` | `{...table}` | Previous/Next page controls |
331
334
 
332
335
  ```tsx
333
- <SearchFilterForm {...table} {...params} />
336
+ <SearchFilterForm {...table} {...collection} />
334
337
  <ColumnSelector {...table} />
335
338
  <CsvButton {...table} filename="orders-export" />
336
339
  <Pagination {...table} />
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.6",
4
+ "version": "0.2.8",
5
5
  "type": "module",
6
6
  "description": "Flexible data viewer component for Tailor Platform",
7
7
  "files": [
@@ -0,0 +1,90 @@
1
+ import { createContext, useContext, type ReactNode } from "react";
2
+ import type { UseCollectionReturn } from "../types";
3
+
4
+ const CollectionContext = createContext<UseCollectionReturn<
5
+ string,
6
+ unknown,
7
+ unknown
8
+ > | null>(null);
9
+
10
+ /**
11
+ * Provider that shares collection query parameters via React Context.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const collection = useCollection({ params: { pageSize: 20 } });
16
+ *
17
+ * <CollectionProvider value={collection}>
18
+ * <FilterPanel />
19
+ * <DataTable.Root {...table.rootProps}>...</DataTable.Root>
20
+ * <Pagination {...table} />
21
+ * </CollectionProvider>
22
+ * ```
23
+ */
24
+ export function CollectionProvider({
25
+ value,
26
+ children,
27
+ }: {
28
+ value: UseCollectionReturn<string, unknown, unknown>;
29
+ children: ReactNode;
30
+ }) {
31
+ return (
32
+ <CollectionContext.Provider value={value}>
33
+ {children}
34
+ </CollectionContext.Provider>
35
+ );
36
+ }
37
+
38
+
39
+
40
+ /**
41
+ * Hook to access collection state from the nearest `Collection.Provider`.
42
+ *
43
+ * Returns the same interface as `useCollection()`. Pass a `TFieldName`
44
+ * type parameter to narrow method arguments like `addFilter` / `setSort`.
45
+ *
46
+ * @typeParam TFieldName - Union of allowed field name strings (default: `string`).
47
+ *
48
+ * @throws Error if used outside of `Collection.Provider`.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * function StatusFilter() {
53
+ * const { filters, addFilter, removeFilter } = useCollectionContext();
54
+ * // ...
55
+ * }
56
+ *
57
+ * // With typed field names:
58
+ * type TaskField = FieldName<typeof tableMetadata, "task">;
59
+ * const { addFilter } = useCollectionContext<TaskField>();
60
+ * ```
61
+ */
62
+ export function useCollectionContext<
63
+ TFieldName extends string = string,
64
+ >(): UseCollectionReturn<TFieldName> {
65
+ const ctx = useContext(CollectionContext);
66
+ if (!ctx) {
67
+ throw new Error(
68
+ "useCollectionContext must be used within <Collection.Provider>",
69
+ );
70
+ }
71
+ return ctx as UseCollectionReturn<TFieldName>;
72
+ }
73
+
74
+
75
+
76
+ /**
77
+ * `Collection` namespace object providing the Provider component.
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * <Collection.Provider value={collection}>
82
+ * ...
83
+ * </Collection.Provider>
84
+ * ```
85
+ */
86
+ export const Collection = {
87
+ Provider: CollectionProvider,
88
+ } as const;
89
+
90
+