@tapizlabs/ui 0.1.1
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/CHANGELOG.md +16 -0
- package/FRAMEWORK_BOUNDARY.md +47 -0
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/fonts.d.ts +2 -0
- package/dist/fonts.js +18 -0
- package/dist/fonts.js.map +1 -0
- package/dist/index.d.ts +576 -0
- package/dist/index.js +2028 -0
- package/dist/index.js.map +1 -0
- package/dist/theme.css +774 -0
- package/package.json +69 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@tapizlabs/ui` should be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on Keep a Changelog and the package follows Semantic Versioning for published releases.
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- npm-ready README with package setup, exports, examples, and publishing guidance
|
|
11
|
+
- shared support for landing icon exports such as `Star`, `AppleIcon`, and `GooglePlayIcon`
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- shared `Button` accepts icon component references in addition to rendered nodes
|
|
15
|
+
- shared `ConfirmDialog` supports both `description` and compatibility `message` props
|
|
16
|
+
- consumer apps are now migrated to shared theme, fonts, and shared UI primitives
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Tapiz UI Framework Boundary
|
|
2
|
+
|
|
3
|
+
This document defines what belongs in `@tapizlabs/ui` and what should remain inside consuming applications.
|
|
4
|
+
|
|
5
|
+
## Belongs In `@tapizlabs/ui`
|
|
6
|
+
|
|
7
|
+
The package is the shared UI framework layer for Tapiz frontends. It should contain:
|
|
8
|
+
|
|
9
|
+
- design tokens and global theme contract from `theme.css`
|
|
10
|
+
- shared font loading
|
|
11
|
+
- shared iconography
|
|
12
|
+
- reusable React primitives
|
|
13
|
+
- generic feedback, modal, table, and form building blocks
|
|
14
|
+
- generic page building blocks such as `PageHeader`, `Pagination`, `SearchInput`, `StatusBadge`, and `ActionMenu`
|
|
15
|
+
- generic skeleton primitives and reusable loading patterns
|
|
16
|
+
|
|
17
|
+
Add something to the package when it is:
|
|
18
|
+
|
|
19
|
+
- reused across multiple Tapiz apps
|
|
20
|
+
- visually part of the shared Tapiz language
|
|
21
|
+
- not tightly coupled to one app's routes, translations, queries, or storage rules
|
|
22
|
+
|
|
23
|
+
## Stays App-Specific
|
|
24
|
+
|
|
25
|
+
The following should remain in consumer apps unless they are intentionally generalized:
|
|
26
|
+
|
|
27
|
+
- app layout shells like `UILayout`, sidebars, drawers, tenant shells, and role-based navigation
|
|
28
|
+
- domain selectors like `SubjectSelector`
|
|
29
|
+
- app-specific translation adapters such as wrappers that inject local `i18n` labels
|
|
30
|
+
- SEO and document metadata helpers like `SEOHead`
|
|
31
|
+
- language/session/settings flows tied to app state or local storage
|
|
32
|
+
- page-specific skeleton compositions that represent one screen instead of a reusable primitive
|
|
33
|
+
- domain widgets and chart assemblies that depend on product-specific data contracts
|
|
34
|
+
|
|
35
|
+
## Current Intentional App Adapters
|
|
36
|
+
|
|
37
|
+
As of this migration, a few local adapters remain by design in `tapiz-reactjs-ui`:
|
|
38
|
+
|
|
39
|
+
- `SearchInput` wrapper for localized placeholder and clear label
|
|
40
|
+
- `Pagination` wrapper for localized labels
|
|
41
|
+
- `StatusBadge` wrapper for attendance/admin status mapping
|
|
42
|
+
|
|
43
|
+
These wrappers are acceptable because they adapt shared framework primitives to app-level language and domain semantics without forking the visual system.
|
|
44
|
+
|
|
45
|
+
## Rule Of Thumb
|
|
46
|
+
|
|
47
|
+
If removing product data, routing, and translation concerns still leaves a useful component, it probably belongs in `@tapizlabs/ui`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tapiz UI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# @tapizlabs/ui
|
|
2
|
+
|
|
3
|
+
Shared Tapiz design system package for React applications.
|
|
4
|
+
|
|
5
|
+
Repository: `https://github.com/owlCoder/tapiz-design-system`
|
|
6
|
+
|
|
7
|
+
`@tapizlabs/ui` centralizes the visual foundation used across Tapiz frontends:
|
|
8
|
+
|
|
9
|
+
- shared theme tokens and utility classes
|
|
10
|
+
- shared font loading
|
|
11
|
+
- shared icon exports
|
|
12
|
+
- shared React UI primitives
|
|
13
|
+
|
|
14
|
+
It is intended to keep multiple apps visually aligned while reducing duplicated UI code.
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @tapizlabs/ui
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- `react >= 19`
|
|
25
|
+
- `react-dom >= 19`
|
|
26
|
+
- `tailwindcss >= 4`
|
|
27
|
+
|
|
28
|
+
These are declared as peer dependencies and must be provided by the consuming app.
|
|
29
|
+
|
|
30
|
+
## Package Exports
|
|
31
|
+
|
|
32
|
+
This package exposes:
|
|
33
|
+
|
|
34
|
+
- `@tapizlabs/ui`
|
|
35
|
+
React components, icons, and exported TypeScript types
|
|
36
|
+
- `@tapizlabs/ui/theme.css`
|
|
37
|
+
Shared theme tokens, utility classes, button styles, surfaces, and animation helpers
|
|
38
|
+
- `@tapizlabs/ui/fonts`
|
|
39
|
+
Shared IBM Plex font loading entrypoint
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
Import fonts once in your application entry:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import "@tapizlabs/ui/fonts";
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Import the shared theme before your app-specific styles:
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
@import "@tapizlabs/ui/theme.css";
|
|
53
|
+
@source "../node_modules/@tapizlabs/ui/dist/**/*.js";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Then consume components directly from the package:
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { Button, EmptyState, InfoBanner } from "@tapizlabs/ui";
|
|
60
|
+
|
|
61
|
+
export function ExamplePanel() {
|
|
62
|
+
return (
|
|
63
|
+
<div className="space-y-4">
|
|
64
|
+
<InfoBanner
|
|
65
|
+
title="Shared UI"
|
|
66
|
+
description="This screen is using the shared Tapiz design system package."
|
|
67
|
+
/>
|
|
68
|
+
<Button>Save changes</Button>
|
|
69
|
+
<EmptyState
|
|
70
|
+
title="No records"
|
|
71
|
+
description="Create your first item to get started."
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Tailwind Setup
|
|
79
|
+
|
|
80
|
+
`@tapizlabs/ui` components contain Tailwind class strings inside the published JavaScript bundle. Consumer apps must include the package in Tailwind's source scan:
|
|
81
|
+
|
|
82
|
+
```css
|
|
83
|
+
@source "../node_modules/@tapizlabs/ui/dist/**/*.js";
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Without that line, some shared component classes may be omitted from the final CSS build.
|
|
87
|
+
|
|
88
|
+
## Included Components
|
|
89
|
+
|
|
90
|
+
Current exports include:
|
|
91
|
+
|
|
92
|
+
- `Button`
|
|
93
|
+
- `Input`
|
|
94
|
+
- `Select`
|
|
95
|
+
- `Textarea`
|
|
96
|
+
- `FieldLabel`
|
|
97
|
+
- `FieldHint`
|
|
98
|
+
- `Checkbox`
|
|
99
|
+
- `RadioButton`
|
|
100
|
+
- `Spinner`
|
|
101
|
+
- `PageSpinner`
|
|
102
|
+
- `Toast`
|
|
103
|
+
- `ToastProvider`
|
|
104
|
+
- `useToast`
|
|
105
|
+
- `FormError`
|
|
106
|
+
- `ErrorBoundary`
|
|
107
|
+
- `BaseModal`
|
|
108
|
+
- `ConfirmDialog`
|
|
109
|
+
- `Tooltip`
|
|
110
|
+
- `Badge`
|
|
111
|
+
- `Card`
|
|
112
|
+
- `CardHeader`
|
|
113
|
+
- `CardBody`
|
|
114
|
+
- `EmptyState`
|
|
115
|
+
- `ErrorState`
|
|
116
|
+
- `InfoBanner`
|
|
117
|
+
- `PageHeader`
|
|
118
|
+
- `SearchInput`
|
|
119
|
+
- `Pagination`
|
|
120
|
+
- `SectionTitle`
|
|
121
|
+
- `StatusBadge`
|
|
122
|
+
- `ActionMenu`
|
|
123
|
+
- `Skeleton`
|
|
124
|
+
- `SkeletonCard`
|
|
125
|
+
- `SkeletonKpiCard`
|
|
126
|
+
- `SkeletonBanner`
|
|
127
|
+
- `SkeletonPageHeader`
|
|
128
|
+
- `SkeletonTable`
|
|
129
|
+
- `DataTable`
|
|
130
|
+
|
|
131
|
+
## Component Examples
|
|
132
|
+
|
|
133
|
+
### Button
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { Button, Plus } from "@tapizlabs/ui";
|
|
137
|
+
|
|
138
|
+
export function Actions() {
|
|
139
|
+
return (
|
|
140
|
+
<div className="flex gap-3">
|
|
141
|
+
<Button>Default</Button>
|
|
142
|
+
<Button variant="secondary" icon={Plus}>
|
|
143
|
+
Create
|
|
144
|
+
</Button>
|
|
145
|
+
<Button variant="danger" loading>
|
|
146
|
+
Deleting
|
|
147
|
+
</Button>
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### ConfirmDialog
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { ConfirmDialog, Trash } from "@tapizlabs/ui";
|
|
157
|
+
|
|
158
|
+
export function DeleteDialogExample() {
|
|
159
|
+
return (
|
|
160
|
+
<ConfirmDialog
|
|
161
|
+
open
|
|
162
|
+
danger
|
|
163
|
+
title="Delete record"
|
|
164
|
+
description="This action cannot be undone."
|
|
165
|
+
icon={<Trash size={14} />}
|
|
166
|
+
confirmLabel="Delete"
|
|
167
|
+
cancelLabel="Cancel"
|
|
168
|
+
onConfirm={() => {}}
|
|
169
|
+
onCancel={() => {}}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Compatibility note:
|
|
176
|
+
|
|
177
|
+
- `ConfirmDialog` supports both `description` and legacy `message`
|
|
178
|
+
|
|
179
|
+
### Form Primitives
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { FieldHint, FieldLabel, Input, Select, Textarea } from "@tapizlabs/ui";
|
|
183
|
+
|
|
184
|
+
export function ProfileFields() {
|
|
185
|
+
return (
|
|
186
|
+
<div className="space-y-4">
|
|
187
|
+
<div className="space-y-2">
|
|
188
|
+
<FieldLabel htmlFor="name">Display name</FieldLabel>
|
|
189
|
+
<Input id="name" placeholder="Jane Doe" />
|
|
190
|
+
<FieldHint>Visible to other Tapiz users.</FieldHint>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<div className="space-y-2">
|
|
194
|
+
<FieldLabel htmlFor="role">Role</FieldLabel>
|
|
195
|
+
<Select id="role" defaultValue="assistant">
|
|
196
|
+
<option value="assistant">Assistant</option>
|
|
197
|
+
<option value="student">Student</option>
|
|
198
|
+
</Select>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div className="space-y-2">
|
|
202
|
+
<FieldLabel htmlFor="bio">Bio</FieldLabel>
|
|
203
|
+
<Textarea id="bio" rows={4} placeholder="Short description" />
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### EmptyState
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import { EmptyState, Info } from "@tapizlabs/ui";
|
|
214
|
+
|
|
215
|
+
export function NoResults() {
|
|
216
|
+
return (
|
|
217
|
+
<EmptyState
|
|
218
|
+
title="No results"
|
|
219
|
+
description="Try adjusting your filters."
|
|
220
|
+
icon={<Info size={18} />}
|
|
221
|
+
/>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### ToastProvider
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
import { ToastProvider, useToast } from "@tapizlabs/ui";
|
|
230
|
+
|
|
231
|
+
function SaveButton() {
|
|
232
|
+
const { showToast } = useToast();
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<button
|
|
236
|
+
type="button"
|
|
237
|
+
onClick={() => showToast({ message: "Saved successfully.", ok: true })}
|
|
238
|
+
>
|
|
239
|
+
Save
|
|
240
|
+
</button>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function App() {
|
|
245
|
+
return (
|
|
246
|
+
<>
|
|
247
|
+
<SaveButton />
|
|
248
|
+
<ToastProvider />
|
|
249
|
+
</>
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### DataTable
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { DataTable, type Column } from "@tapizlabs/ui";
|
|
258
|
+
|
|
259
|
+
interface User {
|
|
260
|
+
id: string;
|
|
261
|
+
name: string;
|
|
262
|
+
role: string;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const columns: Column<User>[] = [
|
|
266
|
+
{ id: "name", header: "Name", cell: (row) => row.name, sortable: true, sortAccessor: (row) => row.name },
|
|
267
|
+
{ id: "role", header: "Role", cell: (row) => row.role },
|
|
268
|
+
];
|
|
269
|
+
|
|
270
|
+
export function UsersTable({ rows }: { rows: User[] }) {
|
|
271
|
+
return (
|
|
272
|
+
<DataTable
|
|
273
|
+
data={rows}
|
|
274
|
+
columns={columns}
|
|
275
|
+
rowKey={(row) => row.id}
|
|
276
|
+
emptyState="No users"
|
|
277
|
+
/>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Included Icon Sets
|
|
283
|
+
|
|
284
|
+
The root package export also includes shared icons used across Tapiz apps, including navigation, status, auth, action, feedback, form, layout, and logo icons.
|
|
285
|
+
|
|
286
|
+
Example:
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { Button, Plus, LogoMark } from "@tapizlabs/ui";
|
|
290
|
+
|
|
291
|
+
export function Toolbar() {
|
|
292
|
+
return (
|
|
293
|
+
<div className="flex items-center gap-3">
|
|
294
|
+
<LogoMark />
|
|
295
|
+
<Button icon={Plus}>Create</Button>
|
|
296
|
+
</div>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`Button` accepts either a rendered React node or an icon component reference through the `icon` and `iconRight` props.
|
|
302
|
+
|
|
303
|
+
Additional branded/storefront icons such as `AppleIcon`, `GooglePlayIcon`, and `Star` are also exported when needed by marketing surfaces.
|
|
304
|
+
|
|
305
|
+
## Styling Contract
|
|
306
|
+
|
|
307
|
+
This package is intentionally opinionated. It provides the shared Tapiz visual language, including:
|
|
308
|
+
|
|
309
|
+
- theme color variables
|
|
310
|
+
- font variables
|
|
311
|
+
- reusable button classes
|
|
312
|
+
- surface and border tokens
|
|
313
|
+
- shared motion helpers
|
|
314
|
+
|
|
315
|
+
Consumer apps can add local styles on top, but should treat `theme.css` as the base design contract for consistency.
|
|
316
|
+
|
|
317
|
+
## Framework Boundary
|
|
318
|
+
|
|
319
|
+
`@tapizlabs/ui` is the shared framework layer for reusable Tapiz UI primitives. Layout shells, SEO helpers, language/session flows, and domain-bound selectors should usually stay in consuming apps.
|
|
320
|
+
|
|
321
|
+
See [FRAMEWORK_BOUNDARY.md](./FRAMEWORK_BOUNDARY.md) for the exact package-vs-app contract used in this workspace.
|
|
322
|
+
|
|
323
|
+
## Accessibility Notes
|
|
324
|
+
|
|
325
|
+
- modal components render through portals
|
|
326
|
+
- table components expose sortable state through appropriate semantics
|
|
327
|
+
- button and feedback primitives preserve native HTML behavior where possible
|
|
328
|
+
|
|
329
|
+
## License
|
|
330
|
+
|
|
331
|
+
This package is released under the `MIT` license.
|
|
332
|
+
|
|
333
|
+
Attribution is retained as `Tapiz UI` in the package metadata and license file.
|
package/dist/fonts.d.ts
ADDED
package/dist/fonts.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/fonts.ts
|
|
2
|
+
import "@fontsource/ibm-plex-sans/latin-400.css";
|
|
3
|
+
import "@fontsource/ibm-plex-sans/latin-400-italic.css";
|
|
4
|
+
import "@fontsource/ibm-plex-sans/latin-500.css";
|
|
5
|
+
import "@fontsource/ibm-plex-sans/latin-600.css";
|
|
6
|
+
import "@fontsource/ibm-plex-sans/latin-700.css";
|
|
7
|
+
import "@fontsource/ibm-plex-sans/cyrillic-400.css";
|
|
8
|
+
import "@fontsource/ibm-plex-sans/cyrillic-500.css";
|
|
9
|
+
import "@fontsource/ibm-plex-sans/cyrillic-600.css";
|
|
10
|
+
import "@fontsource/ibm-plex-sans/cyrillic-700.css";
|
|
11
|
+
import "@fontsource/ibm-plex-mono/latin-400.css";
|
|
12
|
+
import "@fontsource/ibm-plex-mono/latin-400-italic.css";
|
|
13
|
+
import "@fontsource/ibm-plex-mono/latin-500.css";
|
|
14
|
+
import "@fontsource/ibm-plex-mono/latin-600.css";
|
|
15
|
+
import "@fontsource/ibm-plex-mono/latin-ext-400.css";
|
|
16
|
+
import "@fontsource/ibm-plex-mono/latin-ext-500.css";
|
|
17
|
+
import "@fontsource/ibm-plex-mono/latin-ext-600.css";
|
|
18
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fonts.ts"],"sourcesContent":["import \"@fontsource/ibm-plex-sans/latin-400.css\";\nimport \"@fontsource/ibm-plex-sans/latin-400-italic.css\";\nimport \"@fontsource/ibm-plex-sans/latin-500.css\";\nimport \"@fontsource/ibm-plex-sans/latin-600.css\";\nimport \"@fontsource/ibm-plex-sans/latin-700.css\";\nimport \"@fontsource/ibm-plex-sans/cyrillic-400.css\";\nimport \"@fontsource/ibm-plex-sans/cyrillic-500.css\";\nimport \"@fontsource/ibm-plex-sans/cyrillic-600.css\";\nimport \"@fontsource/ibm-plex-sans/cyrillic-700.css\";\nimport \"@fontsource/ibm-plex-mono/latin-400.css\";\nimport \"@fontsource/ibm-plex-mono/latin-400-italic.css\";\nimport \"@fontsource/ibm-plex-mono/latin-500.css\";\nimport \"@fontsource/ibm-plex-mono/latin-600.css\";\nimport \"@fontsource/ibm-plex-mono/latin-ext-400.css\";\nimport \"@fontsource/ibm-plex-mono/latin-ext-500.css\";\nimport \"@fontsource/ibm-plex-mono/latin-ext-600.css\";\n"],"mappings":";AAAA,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;AACP,OAAO;","names":[]}
|