@ahoo-wang/fetcher-viewer 2.15.0 โ†’ 2.15.2

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
@@ -1,49 +1,413 @@
1
- ## Viewer
2
-
3
- - views
4
- - personal views
5
- - public views
6
- - current view
7
- - actions
8
- - add
9
- - delete
10
- - edit name
11
- - sort
12
-
13
- ## View
14
-
15
- - type
16
- - system
17
- - user
18
- - filter
19
- - table
20
- - actions
21
- - refresh
22
- - timedRefresh
23
- - trigger
24
- - extra
25
-
26
-
27
- ## Filter Panel
28
-
29
- - availableFilters
30
- - filters
31
- - actions
32
- - search
33
- - addFilter
34
- - removeFilter
35
- - addGroupFilter
36
- - group: and , or , nor
37
-
38
- ### Filter
39
-
40
- - type
41
-
42
- ## Table
43
-
44
- - columns
45
- - field
46
- - actions
47
- - projection
48
- - pagination
49
- - data
1
+ # @ahoo-wang/fetcher-viewer
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ahoo-wang/fetcher-viewer.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-viewer)
4
+ [![Build Status](https://github.com/Ahoo-Wang/fetcher/actions/workflows/ci.yml/badge.svg)](https://github.com/Ahoo-Wang/fetcher/actions)
5
+ [![codecov](https://codecov.io/gh/Ahoo-Wang/fetcher/graph/badge.svg?token=JGiWZ52CvJ)](https://codecov.io/gh/Ahoo-Wang/fetcher)
6
+ [![License](https://img.shields.io/npm/l/@ahoo-wang/fetcher-viewer.svg)](https://github.com/Ahoo-Wang/fetcher/blob/main/LICENSE)
7
+ [![npm downloads](https://img.shields.io/npm/dm/@ahoo-wang/fetcher-viewer.svg)](https://www.npmjs.com/package/@ahoo-wang/fetcher-viewer)
8
+ [![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40ahoo-wang%2Ffetcher-viewer)](https://www.npmjs.com/package/@ahoo-wang/fetcher-viewer)
9
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Ahoo-Wang/fetcher)
10
+
11
+ A comprehensive React component library for data visualization and filtering, built on top of Ant Design and the Fetcher ecosystem. Provides reusable UI components for building rich data-driven applications with advanced filtering capabilities.
12
+
13
+ ## โœจ Features
14
+
15
+ - **๐Ÿ” Advanced Filtering System**: Complete filter panel with dynamic filter types, operators, and state management
16
+ - **๐Ÿ“Š Data Components**: Remote search select, tag input, number range inputs
17
+ - **๐ŸŽจ Ant Design Integration**: Seamless integration with Ant Design components
18
+ - **๐Ÿ”ง TypeScript First**: Full TypeScript support with comprehensive type definitions
19
+ - **โšก Performance Optimized**: Debounced search, efficient rendering, and optimized state management
20
+ - **๐Ÿงช Well Tested**: Comprehensive test coverage with Vitest and React Testing Library
21
+
22
+ ## ๐Ÿ“ฆ Installation
23
+
24
+ ```bash
25
+ # Using npm
26
+ npm install @ahoo-wang/fetcher-viewer
27
+
28
+ # Using yarn
29
+ yarn add @ahoo-wang/fetcher-viewer
30
+
31
+ # Using pnpm
32
+ pnpm add @ahoo-wang/fetcher-viewer
33
+ ```
34
+
35
+ ## ๐Ÿš€ Quick Start
36
+
37
+ ```tsx
38
+ import {
39
+ RemoteSelect,
40
+ TagInput,
41
+ NumberRange,
42
+ FilterPanel,
43
+ } from '@ahoo-wang/fetcher-viewer';
44
+ import { useFilterState } from '@ahoo-wang/fetcher-viewer';
45
+
46
+ // Basic usage
47
+ function App() {
48
+ const { filters, addFilter, removeFilter, updateFilter } = useFilterState();
49
+
50
+ return (
51
+ <div>
52
+ {/* Remote search select */}
53
+ <RemoteSelect
54
+ search={async query => {
55
+ const response = await fetch(`/api/search?q=${query}`);
56
+ return response.json();
57
+ }}
58
+ placeholder="Search for items..."
59
+ />
60
+
61
+ {/* Tag input */}
62
+ <TagInput value={['tag1', 'tag2']} onChange={tags => console.log(tags)} />
63
+
64
+ {/* Number range */}
65
+ <NumberRange value={[100, 500]} onChange={range => console.log(range)} />
66
+
67
+ {/* Advanced filter panel */}
68
+ <FilterPanel
69
+ filters={filters}
70
+ onAddFilter={addFilter}
71
+ onRemoveFilter={removeFilter}
72
+ onUpdateFilter={updateFilter}
73
+ />
74
+ </div>
75
+ );
76
+ }
77
+ ```
78
+
79
+ ## ๐Ÿ“š API Reference
80
+
81
+ ### Components
82
+
83
+ #### RemoteSelect
84
+
85
+ A debounced search select component that fetches options from a remote API.
86
+
87
+ ```tsx
88
+ import { RemoteSelect } from '@ahoo-wang/fetcher-viewer';
89
+
90
+ <RemoteSelect
91
+ search={async (query: string) => {
92
+ // Return array of options
93
+ return [
94
+ { label: 'Option 1', value: '1' },
95
+ { label: 'Option 2', value: '2' },
96
+ ];
97
+ }}
98
+ debounce={{ delay: 300 }}
99
+ placeholder="Search..."
100
+ onChange={value => console.log(value)}
101
+ />;
102
+ ```
103
+
104
+ **Props:**
105
+
106
+ - `search: (query: string) => Promise<RemoteSelectOption[]>` - Search function
107
+ - `debounce?: UseDebouncedCallbackOptions` - Debounce configuration
108
+ - `...SelectProps` - All Ant Design Select props
109
+
110
+ #### TagInput
111
+
112
+ A tag input component with serialization support for different value types.
113
+
114
+ ```tsx
115
+ import { TagInput, StringTagValueItemSerializer, NumberTagValueItemSerializer } from '@ahoo-wang/fetcher-viewer';
116
+
117
+ // String tags
118
+ <TagInput
119
+ value={['tag1', 'tag2']}
120
+ onChange={(tags) => console.log(tags)}
121
+ />
122
+
123
+ // Number tags
124
+ <TagInput<number>
125
+ value={[1, 2, 3]}
126
+ serializer={NumberTagValueItemSerializer}
127
+ onChange={(tags) => console.log(tags)}
128
+ />
129
+ ```
130
+
131
+ **Props:**
132
+
133
+ - `value?: ValueItemType[]` - Current tag values
134
+ - `serializer?: TagValueItemSerializer` - Value serializer
135
+ - `onChange?: (value: ValueItemType[]) => void` - Change handler
136
+ - `...SelectProps` - Additional Ant Design Select props
137
+
138
+ #### NumberRange
139
+
140
+ A number range input component with min/max validation.
141
+
142
+ ```tsx
143
+ import { NumberRange } from '@ahoo-wang/fetcher-viewer';
144
+
145
+ <NumberRange
146
+ value={[100, 500]}
147
+ min={0}
148
+ max={1000}
149
+ precision={2}
150
+ placeholder={['Min', 'Max']}
151
+ onChange={range => console.log(range)}
152
+ />;
153
+ ```
154
+
155
+ **Props:**
156
+
157
+ - `value?: number | NumberRangeValue` - Current range value
158
+ - `min?: number` - Minimum allowed value
159
+ - `max?: number` - Maximum allowed value
160
+ - `precision?: number` - Decimal precision
161
+ - `placeholder?: string[]` - Input placeholders
162
+ - `onChange?: (value: NumberRangeValue) => void` - Change handler
163
+
164
+ ### Filter System
165
+
166
+ #### FilterPanel
167
+
168
+ A comprehensive filter panel with dynamic filter management.
169
+
170
+ ```tsx
171
+ import { FilterPanel, useFilterState } from '@ahoo-wang/fetcher-viewer';
172
+
173
+ function MyFilterComponent() {
174
+ const { filters, addFilter, removeFilter, updateFilter } = useFilterState();
175
+
176
+ return (
177
+ <FilterPanel
178
+ filters={filters}
179
+ availableFilters={[
180
+ { name: 'name', label: 'Name', type: 'text' },
181
+ { name: 'age', label: 'Age', type: 'number' },
182
+ { name: 'status', label: 'Status', type: 'select' },
183
+ ]}
184
+ onAddFilter={addFilter}
185
+ onRemoveFilter={removeFilter}
186
+ onUpdateFilter={updateFilter}
187
+ />
188
+ );
189
+ }
190
+ ```
191
+
192
+ #### useFilterState Hook
193
+
194
+ State management hook for filter operations.
195
+
196
+ ```tsx
197
+ import { useFilterState } from '@ahoo-wang/fetcher-viewer';
198
+
199
+ const {
200
+ filters, // Current filters array
201
+ addFilter, // Add new filter
202
+ removeFilter, // Remove filter
203
+ updateFilter, // Update filter
204
+ clearFilters, // Clear all filters
205
+ getFilterValue, // Get filter value
206
+ setFilterValue, // Set filter value
207
+ resetFilters, // Reset to initial state
208
+ } = useFilterState(initialFilters);
209
+ ```
210
+
211
+ #### Filter Types
212
+
213
+ The library provides several built-in filter types:
214
+
215
+ - **TextFilter**: Text input with various operators (=, !=, contains, etc.)
216
+ - **NumberFilter**: Number input with comparison operators
217
+ - **SelectFilter**: Dropdown selection filter
218
+ - **IdFilter**: ID-based filter
219
+ - **AssemblyFilter**: Composite filter combining multiple conditions
220
+
221
+ #### Custom Filters
222
+
223
+ Create custom filter components by implementing the `FilterProps` interface:
224
+
225
+ ```tsx
226
+ import { FilterProps, FilterValue } from '@ahoo-wang/fetcher-viewer';
227
+
228
+ function CustomFilter({ field, onChange, value }: FilterProps) {
229
+ return (
230
+ <div>
231
+ <label>{field.label}</label>
232
+ <input
233
+ value={value?.value || ''}
234
+ onChange={e =>
235
+ onChange?.({
236
+ field: field.name,
237
+ operator: 'eq',
238
+ value: e.target.value,
239
+ })
240
+ }
241
+ />
242
+ </div>
243
+ );
244
+ }
245
+ ```
246
+
247
+ ## ๐ŸŽจ Theming & Styling
248
+
249
+ The components inherit Ant Design's theming system. You can customize the appearance using Ant Design's theme configuration:
250
+
251
+ ```tsx
252
+ import { ConfigProvider } from 'antd';
253
+
254
+ <ConfigProvider
255
+ theme={
256
+ {
257
+ /* your theme config */
258
+ }
259
+ }
260
+ >
261
+ <RemoteSelect search={searchFunction} />
262
+ </ConfigProvider>;
263
+ ```
264
+
265
+ ## ๐ŸŒ Internationalization
266
+
267
+ The filter system supports multiple languages. Currently supported locales:
268
+
269
+ - **English** (default)
270
+ - **Chinese** (`zh_CN`)
271
+
272
+ ```tsx
273
+ import { FilterPanel } from '@ahoo-wang/fetcher-viewer';
274
+ import { zh_CN } from '@ahoo-wang/fetcher-viewer/locale';
275
+
276
+ <FilterPanel
277
+ locale={zh_CN}
278
+ // ... other props
279
+ />;
280
+ ```
281
+
282
+ ## ๐Ÿงช Testing
283
+
284
+ The library includes comprehensive tests. Run tests with:
285
+
286
+ ```bash
287
+ # Run all tests
288
+ npm test
289
+
290
+ # Run tests with coverage
291
+ npm run test:coverage
292
+
293
+ # Run tests in UI mode
294
+ npm run test:ui
295
+ ```
296
+
297
+ ## ๐Ÿ“– Examples
298
+
299
+ ### Basic Data Table with Filters
300
+
301
+ ```tsx
302
+ import React, { useState, useEffect } from 'react';
303
+ import {
304
+ FilterPanel,
305
+ useFilterState,
306
+ RemoteSelect,
307
+ } from '@ahoo-wang/fetcher-viewer';
308
+ import { Table } from 'antd';
309
+
310
+ function DataTable() {
311
+ const [data, setData] = useState([]);
312
+ const [loading, setLoading] = useState(false);
313
+ const { filters, addFilter, removeFilter, updateFilter } = useFilterState();
314
+
315
+ useEffect(() => {
316
+ fetchData();
317
+ }, [filters]);
318
+
319
+ const fetchData = async () => {
320
+ setLoading(true);
321
+ try {
322
+ const query = buildQueryFromFilters(filters);
323
+ const response = await fetch(`/api/data?${query}`);
324
+ const result = await response.json();
325
+ setData(result);
326
+ } finally {
327
+ setLoading(false);
328
+ }
329
+ };
330
+
331
+ return (
332
+ <div>
333
+ <FilterPanel
334
+ filters={filters}
335
+ availableFilters={FILTER_CONFIG}
336
+ onAddFilter={addFilter}
337
+ onRemoveFilter={removeFilter}
338
+ onUpdateFilter={updateFilter}
339
+ />
340
+
341
+ <Table dataSource={data} loading={loading} columns={COLUMNS} />
342
+ </div>
343
+ );
344
+ }
345
+ ```
346
+
347
+ ### Advanced Search Component
348
+
349
+ ```tsx
350
+ import { RemoteSelect, TagInput } from '@ahoo-wang/fetcher-viewer';
351
+
352
+ function AdvancedSearch() {
353
+ const [selectedTags, setSelectedTags] = useState([]);
354
+ const [selectedItems, setSelectedItems] = useState([]);
355
+
356
+ return (
357
+ <div className="search-container">
358
+ <RemoteSelect
359
+ search={async query => {
360
+ const response = await api.search(query);
361
+ return response.map(item => ({
362
+ label: item.name,
363
+ value: item.id,
364
+ }));
365
+ }}
366
+ mode="multiple"
367
+ placeholder="Search items..."
368
+ value={selectedItems}
369
+ onChange={setSelectedItems}
370
+ />
371
+
372
+ <TagInput
373
+ placeholder="Add tags..."
374
+ value={selectedTags}
375
+ onChange={setSelectedTags}
376
+ />
377
+ </div>
378
+ );
379
+ }
380
+ ```
381
+
382
+ ## ๐Ÿค Contributing
383
+
384
+ We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
385
+
386
+ 1. Fork the repository
387
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
388
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
389
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
390
+ 5. Open a Pull Request
391
+
392
+ ## ๐Ÿ“„ License
393
+
394
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](../../LICENSE) file for details.
395
+
396
+ ## ๐Ÿ™ Acknowledgments
397
+
398
+ - [Ant Design](https://ant.design/) - UI component library
399
+ - [Fetcher](https://github.com/Ahoo-Wang/fetcher) - HTTP client ecosystem
400
+ - [React](https://reactjs.org/) - UI framework
401
+ - [TypeScript](https://www.typescriptlang.org/) - Type safety
402
+
403
+ ## ๐Ÿ“ž Support
404
+
405
+ - ๐Ÿ“– [Documentation](https://github.com/Ahoo-Wang/fetcher/tree/master/packages/fetcher-viewer)
406
+ - ๐Ÿ› [Issues](https://github.com/Ahoo-Wang/fetcher/issues)
407
+ - ๐Ÿ’ฌ [Discussions](https://github.com/Ahoo-Wang/fetcher/discussions)
408
+
409
+ ---
410
+
411
+ Made with โค๏ธ by the Fetcher team</content>
412
+ </xai:function_call">Now I need to create the Chinese version of the README as well. Let me create README.zh-CN.md</content>
413
+ </xai:function_call">Now I need to create the Chinese version of the README as well. Let me create README.zh-CN.md