@ahoo-wang/fetcher-viewer 2.15.1 โ†’ 2.15.3

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