@apcrda/ui 0.5.8 → 0.5.10
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 +270 -113
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,228 +1,385 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @apcrda/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@apcrda/ui)
|
|
4
|
+
[](https://www.npmjs.com/package/@apcrda/ui)
|
|
5
|
+
[](https://www.npmjs.com/package/@apcrda/ui)
|
|
6
|
+
|
|
7
|
+
Production-ready React 19 component library for APCRDA government applications. 49 accessible components covering forms, data display, navigation, feedback, and layout — built on Tailwind CSS v4 with full dark-mode and theming support.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **49 components** — forms, tables, modals, navigation, charts, and more
|
|
12
|
+
- **Accessible** — WCAG 2.1 AA target; keyboard navigation; ARIA semantics via Radix UI primitives
|
|
13
|
+
- **Fully typed** — complete TypeScript types exported for every component and prop
|
|
14
|
+
- **Themeable** — CSS custom properties, `data-theme` attribute, light and dark modes out of the box
|
|
15
|
+
- **Tree-shakeable** — ESM build with preserved module boundaries; only the components you import are bundled
|
|
16
|
+
- **FormField integration** — label, hint, and error wiring handled automatically via React context
|
|
17
|
+
- **DataTable** — sort, filter, paginate, pin, resize, reorder, virtual scroll (1 000+ rows), CSV/Excel export
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
4
22
|
|
|
5
23
|
```bash
|
|
6
24
|
npm install @apcrda/ui
|
|
7
25
|
```
|
|
8
26
|
|
|
9
|
-
|
|
27
|
+
**Peer dependencies** — install these in your project if not already present:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install react@^19 react-dom@^19
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
10
34
|
|
|
11
|
-
|
|
35
|
+
## Setup
|
|
36
|
+
|
|
37
|
+
### 1. Import the stylesheet
|
|
38
|
+
|
|
39
|
+
Add this once in your application entry point (e.g. `main.tsx`):
|
|
12
40
|
|
|
13
41
|
```tsx
|
|
14
42
|
import '@apcrda/ui/styles.css'
|
|
15
43
|
```
|
|
16
44
|
|
|
17
|
-
|
|
45
|
+
### 2. Wrap with ThemeProvider
|
|
18
46
|
|
|
19
47
|
```tsx
|
|
20
|
-
import {
|
|
48
|
+
import { ThemeProvider } from '@apcrda/ui'
|
|
21
49
|
|
|
22
|
-
export default function
|
|
50
|
+
export default function Root() {
|
|
23
51
|
return (
|
|
24
52
|
<ThemeProvider defaultTheme="light">
|
|
25
|
-
<
|
|
26
|
-
<CardContent className="space-y-4">
|
|
27
|
-
<Input placeholder="Employee Name" />
|
|
28
|
-
<Button>Save</Button>
|
|
29
|
-
</CardContent>
|
|
30
|
-
</Card>
|
|
53
|
+
<App />
|
|
31
54
|
</ThemeProvider>
|
|
32
55
|
)
|
|
33
56
|
}
|
|
34
57
|
```
|
|
35
58
|
|
|
36
|
-
|
|
59
|
+
`ThemeProvider` sets the `data-theme` attribute on `<html>` and persists the user's preference to `localStorage` automatically.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
### Basic form
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { Button, FormField, Input, PasswordInput, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@apcrda/ui'
|
|
69
|
+
|
|
70
|
+
export function LoginForm() {
|
|
71
|
+
return (
|
|
72
|
+
<form className="flex flex-col gap-4">
|
|
73
|
+
<FormField label="Employee ID" required>
|
|
74
|
+
<Input placeholder="EMP-0001" />
|
|
75
|
+
</FormField>
|
|
76
|
+
|
|
77
|
+
<FormField label="Password" required>
|
|
78
|
+
<PasswordInput placeholder="Enter password" />
|
|
79
|
+
</FormField>
|
|
80
|
+
|
|
81
|
+
<FormField label="Department">
|
|
82
|
+
<Select>
|
|
83
|
+
<SelectTrigger>
|
|
84
|
+
<SelectValue placeholder="Select department" />
|
|
85
|
+
</SelectTrigger>
|
|
86
|
+
<SelectContent>
|
|
87
|
+
<SelectItem value="revenue">Revenue</SelectItem>
|
|
88
|
+
<SelectItem value="survey">Survey</SelectItem>
|
|
89
|
+
</SelectContent>
|
|
90
|
+
</Select>
|
|
91
|
+
</FormField>
|
|
92
|
+
|
|
93
|
+
<Button type="submit">Sign in</Button>
|
|
94
|
+
</form>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### FormField with validation error
|
|
100
|
+
|
|
101
|
+
`FormField` wires label, hint text, and error message to the input automatically — no manual `id`, `aria-describedby`, or `aria-invalid` threading required.
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<FormField
|
|
105
|
+
label="Aadhaar Number"
|
|
106
|
+
hint="12-digit number printed on your Aadhaar card"
|
|
107
|
+
error="Aadhaar number must be 12 digits"
|
|
108
|
+
required
|
|
109
|
+
>
|
|
110
|
+
<Input placeholder="XXXX XXXX XXXX" />
|
|
111
|
+
</FormField>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### DataTable
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { DataTable } from '@apcrda/ui'
|
|
118
|
+
import type { ColumnDef } from '@apcrda/ui'
|
|
119
|
+
|
|
120
|
+
type Application = {
|
|
121
|
+
id: string
|
|
122
|
+
applicantName: string
|
|
123
|
+
status: string
|
|
124
|
+
submittedOn: string
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const columns: ColumnDef<Application>[] = [
|
|
128
|
+
{ accessorKey: 'id', header: 'Application ID', size: 160 },
|
|
129
|
+
{ accessorKey: 'applicantName', header: 'Applicant Name', size: 260 },
|
|
130
|
+
{ accessorKey: 'status', header: 'Status', size: 160 },
|
|
131
|
+
{ accessorKey: 'submittedOn', header: 'Submitted On', size: 160 },
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
export function ApplicationsTable({ data }: { data: Application[] }) {
|
|
135
|
+
return (
|
|
136
|
+
<DataTable
|
|
137
|
+
data={data}
|
|
138
|
+
columns={columns}
|
|
139
|
+
pagination
|
|
140
|
+
selectable
|
|
141
|
+
columnFilters
|
|
142
|
+
exportCsv
|
|
143
|
+
stickyHeader
|
|
144
|
+
/>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Notifications
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import { Button } from '@apcrda/ui'
|
|
153
|
+
import { useToast } from '@apcrda/ui'
|
|
154
|
+
|
|
155
|
+
export function SaveButton() {
|
|
156
|
+
const { toast } = useToast()
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<Button
|
|
160
|
+
onClick={() =>
|
|
161
|
+
toast({ title: 'Saved', description: 'Application updated successfully.', variant: 'success' })
|
|
162
|
+
}
|
|
163
|
+
>
|
|
164
|
+
Save
|
|
165
|
+
</Button>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
```
|
|
37
169
|
|
|
38
|
-
|
|
39
|
-
| --------------- | -------- |
|
|
40
|
-
| react | ^19.0.0 |
|
|
41
|
-
| react-dom | ^19.0.0 |
|
|
170
|
+
---
|
|
42
171
|
|
|
43
172
|
## Components
|
|
44
173
|
|
|
45
174
|
### Form & Input
|
|
175
|
+
|
|
46
176
|
| Component | Description |
|
|
47
177
|
| --- | --- |
|
|
48
|
-
| `Input` | Text input
|
|
49
|
-
| `Textarea` | Multi-line input with
|
|
178
|
+
| `Input` | Text input — sizes sm/md/lg, left/right icons, loading spinner |
|
|
179
|
+
| `Textarea` | Multi-line input with optional character counter |
|
|
50
180
|
| `PasswordInput` | Password field with show/hide toggle |
|
|
51
|
-
| `NumberInput` | Numeric stepper with min
|
|
52
|
-
| `FileUpload` | File picker — button or drag-and-drop dropzone |
|
|
181
|
+
| `NumberInput` | Numeric stepper with min, max, step |
|
|
182
|
+
| `FileUpload` | File picker — button or drag-and-drop dropzone variant |
|
|
53
183
|
| `Checkbox` | Accessible checkbox with indeterminate state |
|
|
54
|
-
| `RadioGroup` | Controlled radio group |
|
|
184
|
+
| `RadioGroup` | Controlled radio button group |
|
|
55
185
|
| `Switch` | Toggle switch |
|
|
56
|
-
| `Select` |
|
|
186
|
+
| `Select` | Single-value dropdown |
|
|
57
187
|
| `MultiSelect` | Multi-value select with chip display |
|
|
58
188
|
| `Combobox` | Searchable single-select dropdown |
|
|
59
|
-
| `Autocomplete` | Free-text input with suggestions |
|
|
189
|
+
| `Autocomplete` | Free-text input with suggestions list |
|
|
60
190
|
| `DatePicker` | Single-date calendar picker |
|
|
61
191
|
| `DateRangePicker` | Date range calendar picker |
|
|
62
|
-
| `FormField` | Label + input + hint + error wrapper |
|
|
192
|
+
| `FormField` | Label + input + hint + error wrapper (context-based) |
|
|
63
193
|
| `Label` | Accessible form label |
|
|
64
194
|
|
|
65
195
|
### Data Display
|
|
196
|
+
|
|
66
197
|
| Component | Description |
|
|
67
198
|
| --- | --- |
|
|
68
|
-
| `DataTable` | Full-featured table
|
|
199
|
+
| `DataTable` | Full-featured table with 30+ capabilities |
|
|
69
200
|
| `StatCard` | KPI metric card with trend indicator |
|
|
70
|
-
| `Calendar` | Standalone calendar
|
|
201
|
+
| `Calendar` | Standalone month calendar |
|
|
71
202
|
| `Timeline` | Vertical event timeline |
|
|
72
203
|
| `ScrollArea` | Styled scrollable container |
|
|
73
204
|
| `Progress` | Linear and indeterminate progress bar |
|
|
74
|
-
| `Skeleton` |
|
|
205
|
+
| `Skeleton` | Loading placeholder shimmer |
|
|
75
206
|
|
|
76
207
|
### Navigation
|
|
208
|
+
|
|
77
209
|
| Component | Description |
|
|
78
210
|
| --- | --- |
|
|
79
211
|
| `Navbar` | Top application bar |
|
|
80
|
-
| `Sidebar` | Collapsible side navigation |
|
|
212
|
+
| `Sidebar` | Collapsible side navigation with nested items |
|
|
81
213
|
| `Breadcrumb` | Page hierarchy trail |
|
|
82
214
|
| `Tabs` | Horizontal tab panels |
|
|
83
215
|
| `Pagination` | Page navigation controls |
|
|
84
216
|
| `Stepper` | Multi-step workflow indicator |
|
|
85
|
-
| `Accordion` | Expand/collapse sections |
|
|
217
|
+
| `Accordion` | Expand/collapse content sections |
|
|
86
218
|
|
|
87
219
|
### Feedback & Overlay
|
|
220
|
+
|
|
88
221
|
| Component | Description |
|
|
89
222
|
| --- | --- |
|
|
90
|
-
| `Alert` | Inline status message |
|
|
91
|
-
| `AlertDialog` |
|
|
92
|
-
| `Dialog` |
|
|
223
|
+
| `Alert` | Inline status message — info, success, warning, error |
|
|
224
|
+
| `AlertDialog` | Blocking confirmation modal with cancel/confirm actions |
|
|
225
|
+
| `Dialog` | General-purpose modal dialog |
|
|
93
226
|
| `Drawer` | Slide-in side panel |
|
|
94
|
-
| `Toast` | Ephemeral notification |
|
|
95
|
-
| `Tooltip` | Hover
|
|
96
|
-
| `Popover` | Anchored floating panel |
|
|
227
|
+
| `Toast` | Ephemeral notification — top-right stack |
|
|
228
|
+
| `Tooltip` | Hover hint on any element |
|
|
229
|
+
| `Popover` | Anchored floating content panel |
|
|
97
230
|
| `NotificationCenter` | Notification feed with read/unread state |
|
|
98
|
-
| `EmptyState` | Zero-data placeholder |
|
|
231
|
+
| `EmptyState` | Zero-data placeholder with icon and action |
|
|
99
232
|
|
|
100
233
|
### Layout & Display
|
|
234
|
+
|
|
101
235
|
| Component | Description |
|
|
102
236
|
| --- | --- |
|
|
103
|
-
| `Card` | Elevated surface container |
|
|
237
|
+
| `Card` | Elevated surface container with optional header and footer |
|
|
104
238
|
| `Divider` | Horizontal or vertical separator |
|
|
105
|
-
| `Typography` | Heading and
|
|
106
|
-
| `Avatar` | User avatar with fallback initials |
|
|
107
|
-
| `Badge` | Status and count
|
|
239
|
+
| `Typography` | `Heading` and `Text` variants with size and weight props |
|
|
240
|
+
| `Avatar` | User avatar with image or fallback initials |
|
|
241
|
+
| `Badge` | Status and count pill |
|
|
108
242
|
| `Tag` | Removable label chip |
|
|
109
|
-
| `Spinner` |
|
|
110
|
-
| `Skeleton` | Placeholder shimmer |
|
|
243
|
+
| `Spinner` | Accessible loading indicator |
|
|
111
244
|
| `Kbd` | Keyboard shortcut key display |
|
|
112
245
|
|
|
113
246
|
### Utility
|
|
247
|
+
|
|
114
248
|
| Component | Description |
|
|
115
249
|
| --- | --- |
|
|
116
250
|
| `CommandPalette` | `⌘K` command search overlay |
|
|
117
251
|
| `ContextMenu` | Right-click context menu |
|
|
118
252
|
|
|
253
|
+
---
|
|
254
|
+
|
|
119
255
|
## Theming
|
|
120
256
|
|
|
121
|
-
|
|
257
|
+
### Light and dark mode
|
|
258
|
+
|
|
259
|
+
APCRDA UI uses CSS custom properties scoped to a `data-theme` attribute:
|
|
122
260
|
|
|
123
261
|
```html
|
|
124
262
|
<html data-theme="light">…</html>
|
|
125
263
|
<html data-theme="dark">…</html>
|
|
126
264
|
```
|
|
127
265
|
|
|
128
|
-
`ThemeProvider` manages the attribute
|
|
266
|
+
`ThemeProvider` manages the attribute and syncs it with `localStorage`:
|
|
129
267
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
// tailwind.config.ts
|
|
136
|
-
import apcrdaPlugin from '@apcrda/ui/plugin.css'
|
|
268
|
+
```tsx
|
|
269
|
+
// Force a specific theme
|
|
270
|
+
<ThemeProvider defaultTheme="dark">…</ThemeProvider>
|
|
137
271
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
272
|
+
// Follow system preference
|
|
273
|
+
<ThemeProvider defaultTheme="system">…</ThemeProvider>
|
|
141
274
|
```
|
|
142
275
|
|
|
143
276
|
### Custom tokens
|
|
144
277
|
|
|
145
|
-
Override any design token
|
|
278
|
+
Override any design token after importing the stylesheet:
|
|
146
279
|
|
|
147
280
|
```css
|
|
148
281
|
@import '@apcrda/ui/styles.css';
|
|
149
282
|
|
|
150
283
|
:root {
|
|
151
|
-
--apcrda-color-primary:
|
|
152
|
-
--apcrda-
|
|
284
|
+
--apcrda-color-primary: #0052cc;
|
|
285
|
+
--apcrda-color-primary-foreground: #ffffff;
|
|
286
|
+
--apcrda-radius-md: 0.25rem;
|
|
287
|
+
--apcrda-font-sans: 'Noto Sans Telugu', system-ui, sans-serif;
|
|
153
288
|
}
|
|
154
289
|
```
|
|
155
290
|
|
|
156
|
-
|
|
291
|
+
### Tailwind CSS plugin
|
|
157
292
|
|
|
158
|
-
|
|
293
|
+
If you use Tailwind CSS in your app, register the APCRDA tokens as a plugin so your own classes can reference the same variables:
|
|
159
294
|
|
|
160
|
-
```
|
|
161
|
-
|
|
295
|
+
```ts
|
|
296
|
+
// tailwind.config.ts
|
|
297
|
+
import apcrdaPlugin from '@apcrda/ui/plugin.css'
|
|
162
298
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
299
|
+
export default {
|
|
300
|
+
plugins: [apcrdaPlugin],
|
|
301
|
+
}
|
|
166
302
|
```
|
|
167
303
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## DataTable
|
|
171
|
-
|
|
172
|
-
```tsx
|
|
173
|
-
import { DataTable } from '@apcrda/ui'
|
|
174
|
-
import type { ColumnDef } from '@apcrda/ui'
|
|
175
|
-
|
|
176
|
-
const columns: ColumnDef<Application>[] = [
|
|
177
|
-
{ accessorKey: 'id', header: 'Application ID' },
|
|
178
|
-
{ accessorKey: 'name', header: 'Applicant Name' },
|
|
179
|
-
]
|
|
180
|
-
|
|
181
|
-
<DataTable
|
|
182
|
-
data={applications}
|
|
183
|
-
columns={columns}
|
|
184
|
-
pagination
|
|
185
|
-
selectable
|
|
186
|
-
exportCsv
|
|
187
|
-
stickyHeader
|
|
188
|
-
/>
|
|
189
|
-
```
|
|
304
|
+
---
|
|
190
305
|
|
|
191
|
-
|
|
306
|
+
## TypeScript
|
|
192
307
|
|
|
193
|
-
|
|
308
|
+
All components, props, and utility types are fully typed and exported from the package root:
|
|
194
309
|
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
310
|
+
```ts
|
|
311
|
+
import type {
|
|
312
|
+
ButtonVariant,
|
|
313
|
+
ColumnDef,
|
|
314
|
+
DataTableProps,
|
|
315
|
+
DataTableRowAction,
|
|
316
|
+
InputProps,
|
|
317
|
+
InputSize,
|
|
318
|
+
} from '@apcrda/ui'
|
|
202
319
|
```
|
|
203
320
|
|
|
204
|
-
|
|
321
|
+
The package ships `.d.ts` declaration files alongside the ESM bundle — no `@types/` package needed.
|
|
205
322
|
|
|
206
|
-
|
|
323
|
+
---
|
|
207
324
|
|
|
208
|
-
|
|
209
|
-
npm run build
|
|
210
|
-
npm publish
|
|
211
|
-
```
|
|
325
|
+
## Accessibility
|
|
212
326
|
|
|
213
|
-
|
|
327
|
+
- **Target:** WCAG 2.1 AA
|
|
328
|
+
- **Keyboard navigation:** all interactive components are fully keyboard-accessible
|
|
329
|
+
- **Screen readers:** semantic HTML and Radix UI ARIA patterns throughout
|
|
330
|
+
- **Focus management:** visible focus rings, focus trapping in modals and drawers
|
|
331
|
+
- **Motion:** animations respect `prefers-reduced-motion`
|
|
332
|
+
- **Form errors:** error messages are linked to inputs via `aria-describedby` and announced as `role="alert"`
|
|
214
333
|
|
|
215
|
-
|
|
216
|
-
npm run publish:gitlab
|
|
217
|
-
```
|
|
334
|
+
---
|
|
218
335
|
|
|
219
|
-
|
|
336
|
+
## DataTable capabilities
|
|
220
337
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
338
|
+
| Feature | Prop |
|
|
339
|
+
| --- | --- |
|
|
340
|
+
| Client-side pagination | `pagination` |
|
|
341
|
+
| Server-side pagination | `serverPagination` |
|
|
342
|
+
| Infinite scroll | `infiniteScroll` |
|
|
343
|
+
| Global search | built-in |
|
|
344
|
+
| Column filters (text / select / range / date) | `columnFilters` |
|
|
345
|
+
| Multi-column sort | `multiSort` |
|
|
346
|
+
| Column visibility toggle | `columnVisibility` |
|
|
347
|
+
| Column resize | `columnResize` |
|
|
348
|
+
| Column pinning | `columnPinning` |
|
|
349
|
+
| Column reorder (drag and drop) | `columnReorder` |
|
|
350
|
+
| Row grouping | `grouping` |
|
|
351
|
+
| Row expand / sub-rows | `getRowCanExpand` + `renderSubRow` |
|
|
352
|
+
| Tree data | `getSubRows` |
|
|
353
|
+
| Row selection + bulk actions | `selectable` + `bulkActions` |
|
|
354
|
+
| Row actions menu | `rowActions` |
|
|
355
|
+
| Virtual scroll (1 000+ rows) | `virtualize` |
|
|
356
|
+
| CSV export | `exportCsv` |
|
|
357
|
+
| Excel export | `exportExcel` |
|
|
358
|
+
| Print | `print` |
|
|
359
|
+
| Copy to clipboard | `copy` |
|
|
360
|
+
| Density toggle (compact / normal / spacious) | `density` |
|
|
361
|
+
| Sticky header | `stickyHeader` |
|
|
362
|
+
| Striped rows | `striped` |
|
|
363
|
+
| Loading skeleton | `loading` |
|
|
364
|
+
| Empty state | `emptyMessage` / `emptyDescription` |
|
|
365
|
+
| Footer aggregations | column `footer` + `aggregationFn` |
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## Bundle size
|
|
370
|
+
|
|
371
|
+
The package is built as ESM with Vite in library mode. Unused components are tree-shaken automatically by your bundler. Runtime dependencies (Radix UI primitives, CVA, date-fns, etc.) are bundled. React and ReactDOM are peer dependencies and are **not** included.
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Links
|
|
376
|
+
|
|
377
|
+
- [Repository](https://gitlab.apcrda.org/crda/apcrda-design-system)
|
|
378
|
+
- [Issues](https://gitlab.apcrda.org/crda/apcrda-design-system/-/issues)
|
|
379
|
+
- [Changelog](https://gitlab.apcrda.org/crda/apcrda-design-system/-/blob/main/CHANGELOG.md)
|
|
380
|
+
|
|
381
|
+
---
|
|
225
382
|
|
|
226
383
|
## License
|
|
227
384
|
|
|
228
|
-
MIT
|
|
385
|
+
MIT © APCRDA
|