@crownpeak/dqm-react-component 1.0.0

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.
Files changed (87) hide show
  1. package/AUTHENTICATION.md +281 -0
  2. package/BACKEND-API.md +1829 -0
  3. package/CHANGELOG.md +28 -0
  4. package/DEVELOPMENT.md +339 -0
  5. package/EXAMPLES.md +194 -0
  6. package/LICENSE +22 -0
  7. package/QUICKSTART.md +200 -0
  8. package/README.md +213 -0
  9. package/dist/DQMSidebar.d.ts +5 -0
  10. package/dist/DQMSidebar.d.ts.map +1 -0
  11. package/dist/ErrorBoundary.d.ts +34 -0
  12. package/dist/ErrorBoundary.d.ts.map +1 -0
  13. package/dist/auth-ui/assets/index-CehNKFGj.js +158 -0
  14. package/dist/auth-ui/index.html +30 -0
  15. package/dist/components/auth/DQMLogin.d.ts +16 -0
  16. package/dist/components/auth/DQMLogin.d.ts.map +1 -0
  17. package/dist/components/auth/OAuth2CallbackHandler.d.ts +15 -0
  18. package/dist/components/auth/OAuth2CallbackHandler.d.ts.map +1 -0
  19. package/dist/components/auth/index.d.ts +3 -0
  20. package/dist/components/auth/index.d.ts.map +1 -0
  21. package/dist/components/cards/CategoryCard.d.ts +2 -0
  22. package/dist/components/cards/CategoryCard.d.ts.map +1 -0
  23. package/dist/components/cards/FailedCheckpointsCard.d.ts +2 -0
  24. package/dist/components/cards/FailedCheckpointsCard.d.ts.map +1 -0
  25. package/dist/components/cards/QualityOverviewCard.d.ts +2 -0
  26. package/dist/components/cards/QualityOverviewCard.d.ts.map +1 -0
  27. package/dist/components/cards/index.d.ts +4 -0
  28. package/dist/components/cards/index.d.ts.map +1 -0
  29. package/dist/components/common/CircularProgressWithLabel.d.ts +5 -0
  30. package/dist/components/common/CircularProgressWithLabel.d.ts.map +1 -0
  31. package/dist/components/common/index.d.ts +2 -0
  32. package/dist/components/common/index.d.ts.map +1 -0
  33. package/dist/components/renderers/BrowserViewRenderer.d.ts +9 -0
  34. package/dist/components/renderers/BrowserViewRenderer.d.ts.map +1 -0
  35. package/dist/components/renderers/SafeParsedHtml.d.ts +4 -0
  36. package/dist/components/renderers/SafeParsedHtml.d.ts.map +1 -0
  37. package/dist/components/renderers/ShadowDOMRenderer.d.ts +11 -0
  38. package/dist/components/renderers/ShadowDOMRenderer.d.ts.map +1 -0
  39. package/dist/components/renderers/index.d.ts +4 -0
  40. package/dist/components/renderers/index.d.ts.map +1 -0
  41. package/dist/components/sidebar/SidebarContent.d.ts +2 -0
  42. package/dist/components/sidebar/SidebarContent.d.ts.map +1 -0
  43. package/dist/components/sidebar/SidebarFooter.d.ts +5 -0
  44. package/dist/components/sidebar/SidebarFooter.d.ts.map +1 -0
  45. package/dist/components/sidebar/SidebarHeader.d.ts +2 -0
  46. package/dist/components/sidebar/SidebarHeader.d.ts.map +1 -0
  47. package/dist/components/sidebar/SidebarSkeleton.d.ts +5 -0
  48. package/dist/components/sidebar/SidebarSkeleton.d.ts.map +1 -0
  49. package/dist/components/sidebar/StyledDrawer.d.ts +2 -0
  50. package/dist/components/sidebar/StyledDrawer.d.ts.map +1 -0
  51. package/dist/components/sidebar/StyledFab.d.ts +4 -0
  52. package/dist/components/sidebar/StyledFab.d.ts.map +1 -0
  53. package/dist/components/sidebar/index.d.ts +7 -0
  54. package/dist/components/sidebar/index.d.ts.map +1 -0
  55. package/dist/index.cjs +113 -0
  56. package/dist/index.cjs.map +1 -0
  57. package/dist/index.d.ts +4 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +13712 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/server/config.js +21 -0
  62. package/dist/server/config.js.map +1 -0
  63. package/dist/server/index.js +74 -0
  64. package/dist/server/index.js.map +1 -0
  65. package/dist/server/middleware/authenticate.js +31 -0
  66. package/dist/server/middleware/authenticate.js.map +1 -0
  67. package/dist/server/middleware/errorHandler.js +8 -0
  68. package/dist/server/middleware/errorHandler.js.map +1 -0
  69. package/dist/server/routes/auth.js +142 -0
  70. package/dist/server/routes/auth.js.map +1 -0
  71. package/dist/server/routes/dqm.js +138 -0
  72. package/dist/server/routes/dqm.js.map +1 -0
  73. package/dist/server/services/dqmClient.js +127 -0
  74. package/dist/server/services/dqmClient.js.map +1 -0
  75. package/dist/server/services/sessionStore.js +250 -0
  76. package/dist/server/services/sessionStore.js.map +1 -0
  77. package/dist/server/types.js +2 -0
  78. package/dist/server/types.js.map +1 -0
  79. package/dist/types.d.ts +76 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/utils/colors/GenerateCategoryColors.d.ts +12 -0
  82. package/dist/utils/colors/GenerateCategoryColors.d.ts.map +1 -0
  83. package/dist/utils/localStorage.d.ts +4 -0
  84. package/dist/utils/localStorage.d.ts.map +1 -0
  85. package/dist/utils/storage.d.ts +28 -0
  86. package/dist/utils/storage.d.ts.map +1 -0
  87. package/package.json +124 -0
package/QUICKSTART.md ADDED
@@ -0,0 +1,200 @@
1
+ # ๐Ÿš€ Quick Start Guide
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ npm install
7
+ ```
8
+
9
+ ## Build
10
+
11
+ ```bash
12
+ npm run build
13
+ ```
14
+
15
+ ## Start Development
16
+
17
+ ```bash
18
+ npm run dev
19
+ ```
20
+
21
+ This starts:
22
+ - โœ… **Frontend**: http://localhost:5173 (Vite Dev Server)
23
+ - โœ… **Backend**: http://localhost:3001 (Express API)
24
+
25
+ ## Test the Integration
26
+
27
+ ### 1. Open Frontend
28
+ Navigate to http://localhost:5173
29
+
30
+ ### 2. Configure Backend Mode
31
+ The test harness is already configured to use the backend:
32
+
33
+ ```tsx
34
+ config={{
35
+ authBackendUrl: 'http://localhost:3001',
36
+ useLocalStorage: true,
37
+ }}
38
+ ```
39
+
40
+ ### 3. Login with Credentials
41
+ - Enter your Crownpeak DQM API Key
42
+ - Enter your Website ID
43
+ - Click "Continue"
44
+
45
+ The backend will:
46
+ 1. Validate credentials with Crownpeak DQM API
47
+ 2. Issue a session token
48
+ 3. Store token in localStorage
49
+
50
+ ### 4. Analyze HTML
51
+ - Paste HTML in the editor
52
+ - Click "Start Analysis"
53
+ - All requests go through `http://localhost:3001/dqm/*`
54
+
55
+ ## Architecture
56
+
57
+ ```mermaid
58
+ graph LR
59
+ A[React App<br/>Port 5173]
60
+ B[Express API<br/>Port 3001]
61
+ C[Crownpeak DQM<br/>API]
62
+
63
+ A -->|HTTP Requests| B
64
+ B -->|Proxied Requests| C
65
+
66
+ A -.->|sessionToken<br/>localStorage| A
67
+ B -.->|apiKey + websiteId<br/>in-memory ยท Redis-ready| B
68
+
69
+ subgraph Frontend
70
+ A
71
+ A1[DQMSidebar]
72
+ A2[Login UI]
73
+ A3[HTML Editor]
74
+ end
75
+
76
+ subgraph Backend
77
+ B
78
+ B1[Auth Routes]
79
+ B2[DQM Proxy]
80
+ B3[Sessions]
81
+ end
82
+
83
+ subgraph External
84
+ C
85
+ C1[Analysis]
86
+ C2[Highlights]
87
+ C3[Checkpoints]
88
+ end
89
+ ```
90
+
91
+ ## Two Authentication Modes
92
+
93
+ ### Backend Mode (Production)
94
+ ```tsx
95
+ config={{
96
+ authBackendUrl: 'http://localhost:3001',
97
+ }}
98
+ ```
99
+ - โœ… Secure session tokens
100
+ - โœ… API keys never exposed to client
101
+ - โœ… Centralized access control
102
+
103
+ ### Direct Mode (Development)
104
+ ```tsx
105
+ config={{
106
+ apiKey: 'YOUR_API_KEY',
107
+ websiteId: 'YOUR_WEBSITE_ID',
108
+ }}
109
+ ```
110
+ - โœ… No backend required
111
+ - โœ… Quick testing
112
+ - โœ… Props or localStorage
113
+
114
+ ## API Endpoints
115
+
116
+ ### Authentication
117
+ - `POST /auth/login` - Login with credentials
118
+ - `POST /auth/logout` - Invalidate session
119
+ - `GET /auth/session` - Get session info
120
+
121
+ ### DQM Proxy
122
+ - `POST /dqm/assets` - Start analysis
123
+ - `GET /dqm/assets/:id` - Get results
124
+ - `GET /dqm/assets/:id/pagehighlight/all` - All highlights
125
+ - `GET /dqm/assets/:id/pagehighlight/:cpId` - Single highlight
126
+
127
+ All DQM endpoints require `Authorization: Bearer <sessionToken>`
128
+
129
+ ## Scripts
130
+
131
+ ```bash
132
+ # Development
133
+ npm run dev # Start both servers
134
+ npm run dev:client # Frontend only
135
+ npm run dev:server # Backend only
136
+
137
+ # Build
138
+ npm run build # Build all
139
+ npm run build:lib # Build React library
140
+ npm run build:server # Build Express server
141
+
142
+ # Production
143
+ npm run start:server # Run built server
144
+ ```
145
+
146
+ ## Environment Setup
147
+
148
+ Copy `.env.example` to `.env`:
149
+
150
+ ```env
151
+ PORT=3001
152
+ CORS_ORIGINS=http://localhost:5173
153
+ DQM_API_BASE_URL=https://api.crownpeak.net/dqm-cms/v1
154
+ JWT_SECRET=your-secret-key
155
+ ```
156
+
157
+ ## Documentation
158
+
159
+ - **[BACKEND-API.md](./BACKEND-API.md)** - Backend API specification
160
+ - **[DEVELOPMENT.md](./DEVELOPMENT.md)** - Development guide
161
+ - **[server/README.md](./server/README.md)** - Server documentation
162
+ - **[AUTHENTICATION.md](./AUTHENTICATION.md)** - Auth flow details
163
+ - **[EXAMPLES.md](./EXAMPLES.md)** - Integration examples
164
+
165
+ ## Testing
166
+
167
+ ### Test Backend Health
168
+ ```bash
169
+ curl http://localhost:3001/health
170
+ ```
171
+
172
+ ### Test Login
173
+ ```bash
174
+ curl -X POST http://localhost:3001/auth/login \
175
+ -H "Content-Type: application/json" \
176
+ -d '{"apiKey":"YOUR_KEY","websiteId":"YOUR_ID"}'
177
+ ```
178
+
179
+ ### Test Analysis
180
+ ```bash
181
+ curl -X POST http://localhost:3001/dqm/assets \
182
+ -H "Authorization: Bearer YOUR_TOKEN" \
183
+ -H "Content-Type: application/json" \
184
+ -d '{"html":"<html><body>Test</body></html>"}'
185
+ ```
186
+
187
+ ## Features
188
+
189
+ โœ… **Modular Backend** - Express.js with clean architecture
190
+ โœ… **Session Management** - In-memory store (Redis-ready)
191
+ โœ… **DQM API Proxy** - All analysis endpoints
192
+ โœ… **CORS & Security** - Helmet.js, CORS whitelist
193
+ โœ… **Auto-reload** - TSX watch mode for development
194
+ โœ… **Concurrent Servers** - Frontend + Backend in one command
195
+ โœ… **TypeScript** - Full type safety
196
+ โœ… **Error Handling** - Centralized middleware
197
+
198
+ ## License
199
+
200
+ MIT
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # Crownpeak DQM React Component
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@crownpeak/dqm-react-component.svg)](https://www.npmjs.com/package/@crownpeak/dqm-react-component)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue)](https://www.typescriptlang.org/)
6
+ [![React](https://img.shields.io/badge/React-18%2B-blue)](https://reactjs.org/)
7
+
8
+ A React component library for integrating [Crownpeak Digital Quality Management (DQM)](https://www.crownpeak.com/) into
9
+ your React applications. Display quality analysis, accessibility violations, and checkpoint errors with visual
10
+ highlighting capabilities.
11
+
12
+ ## ๐ŸŒŸ Features
13
+
14
+ - **๐Ÿ“Š Quality Analysis** - Comprehensive quality metrics and scores
15
+ - **โ™ฟ Accessibility Checks** - WCAG compliance validation
16
+ - **๐ŸŽฏ Error Highlighting** - Visual highlighting of issues in HTML
17
+ - **๐ŸŽจ Material-UI Design** - Beautiful, responsive sidebar interface
18
+ - **๐Ÿ” OAuth 2.0 Authentication** - Secure Crownpeak SSO integration
19
+ - **โšก Real-time Analysis** - Live quality assessment as you edit
20
+ - **๐Ÿ“ฑ Responsive** - Works on desktop, tablet, and mobile
21
+ - **๐Ÿ”ง TypeScript Support** - Full type definitions included
22
+
23
+ ## ๐Ÿ“ฆ Installation
24
+
25
+ ```bash
26
+ npm install @crownpeak/dqm-react-component
27
+ ```
28
+
29
+ ## ๐Ÿš€ Quick Start
30
+
31
+ ```tsx
32
+ import React, {useState} from 'react';
33
+ import {DQMSidebar} from '@crownpeak/dqm-react-component';
34
+
35
+ function App() {
36
+ const [open, setOpen] = useState(false);
37
+
38
+ const customHtml = `<html>
39
+ <head><title>Test Page</title></head>
40
+ <body>
41
+ <h1>Hello World</h1>
42
+ <img src="image.jpg" />
43
+ </body>`
44
+
45
+ return (
46
+ <div>
47
+ <button onClick={() => setOpen(true)}>Check Quality</button>
48
+
49
+ <DQMSidebar
50
+ open={sidebarOpen}
51
+ onOpen={() => setOpen(true)}
52
+ onClose={() => setOpen(false)}
53
+ debugHtml={customHtml}
54
+ config={{
55
+ // ... authentication options here
56
+ // look for "๐Ÿ”‘ Authentication Setup" below
57
+ }}
58
+ />
59
+ </div>
60
+ );
61
+ }
62
+
63
+ export default App;
64
+ ```
65
+
66
+ ## ๐Ÿ“– Documentation
67
+
68
+ - **[Quick Start Guide](./QUICKSTART.md)** - Get up and running in 5 minutes
69
+ - **[Examples](./EXAMPLES.md)** - Integration examples for React, Next.js, TypeScript
70
+ - **[Authentication Guide](./AUTHENTICATION.md)** - OAuth 2.0 setup and configuration
71
+ - **[Backend API](./BACKEND-API.md)** - API endpoints and usage
72
+ - **[Development Guide](./DEVELOPMENT.md)** - Contributing and local development
73
+
74
+ ## ๐Ÿ”‘ Authentication Setup
75
+
76
+ The component requires authentication with Crownpeak DQM. 3 options are available:
77
+
78
+ ```tsx
79
+ import {DQMSidebar} from '@crownpeak/dqm-react-component';
80
+
81
+ <DQMSidebar
82
+ {/* ... */}
83
+ config={{
84
+ // -- Direct API Key and Website ID (not recommended for production)
85
+ // websiteId: 'your-website-id',
86
+ // apiKey: 'your-api-key',
87
+
88
+ // -- Auth Backend for API Key management
89
+ authBackendUrl: 'http://localhost:3001',
90
+ useLocalStorage: true,
91
+
92
+ // -- Oauth2: backend not yet implemented ...
93
+ // oauth2Config: {
94
+ // authUrl: 'https://dqm.crownpeak.com/oauth2/authorize',
95
+ // clientId: 'crownpeak-dqm-react-component',
96
+ // scope: 'dqm_api',
97
+ // redirectUri: 'http://localhost:5173/',
98
+ // tokenUrl: 'https://dqm.crownpeak.com/oauth2/token',
99
+ // }
100
+ }}
101
+ ```
102
+
103
+ ### Direct Backend Integration
104
+
105
+ Run the included backend server for session management:
106
+
107
+ ```bash
108
+ npm run server
109
+ ```
110
+
111
+ See [AUTHENTICATION.md](./AUTHENTICATION.md) for detailed setup instructions.
112
+
113
+ ## ๐Ÿ› ๏ธ Development Server
114
+
115
+ For local development with test harness:
116
+
117
+ ```bash
118
+ npm install
119
+ npm run dev
120
+ ```
121
+
122
+ This starts:
123
+
124
+ - Frontend on `http://localhost:5173`
125
+ - Backend on `http://localhost:3001`
126
+
127
+ ### Backend Requirements (Optional)
128
+
129
+ If using the included backend server:
130
+
131
+ - Node.js 18+ or 20+
132
+ - Redis (for session storage)
133
+
134
+ See [REDIS-SETUP.md](./REDIS-SETUP.md) for Redis installation.
135
+
136
+ ## ๐Ÿ“Š API Reference
137
+
138
+ ### DQMSidebar Props
139
+
140
+ | Prop | Type | Required | Description |
141
+ |-------------|--------------|----------|------------------------------|
142
+ | `open` | `boolean` | โœ… | Controls sidebar visibility |
143
+ | `onClose` | `() => void` | โœ… | Callback when sidebar closes |
144
+ | `onOpen` | `() => void` | โœ… | Callback when sidebar opens |
145
+ | `debugHtml` | `string` | โŒ | HTML for testing (dev only) |
146
+
147
+ ### Exported Types
148
+
149
+ ```typescript
150
+ import type {
151
+ AnalysisState,
152
+ Checkpoint,
153
+ AnalysisData,
154
+ DQMSidebarProps
155
+ } from '@crownpeak/dqm-react-component';
156
+ ```
157
+
158
+ See [TypeScript examples](./EXAMPLES.md#typescript-configuration) for full type definitions.
159
+
160
+ ## ๐Ÿงช Testing
161
+
162
+ ```bash
163
+ # Lint code
164
+ npm run lint
165
+
166
+ # Build library
167
+ npm run build:lib
168
+
169
+ # Test as package
170
+ npm pack
171
+ npm install ./crownpeak-dqm-react-component-1.0.0.tgz
172
+ ```
173
+
174
+ ## ๐Ÿค Contributing
175
+
176
+ We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.
177
+
178
+ 1. Fork the repository
179
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
180
+ 3. Commit your changes (`git commit -m 'feat: Add amazing feature'`)
181
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
182
+ 5. Open a Pull Request
183
+
184
+ ## ๐Ÿ“œ License
185
+
186
+ MIT ยฉ [Crownpeak Technology GmbH](https://www.crownpeak.com/)
187
+
188
+ See [LICENSE](./LICENSE) file for details.
189
+
190
+ ## ๐Ÿ› Issues
191
+
192
+ Found a bug or have a feature request?
193
+ Please [open an issue](https://github.com/Crownpeak/dqm-react-component/issues/new/choose).
194
+
195
+ ## ๐Ÿ“ž Support
196
+
197
+ - **Documentation**: Check the [docs folder](.)
198
+ - **Issues**: [GitHub Issues](https://github.com/Crownpeak/dqm-react-component/issues)
199
+ - **Website**: [crownpeak.com](https://www.crownpeak.com/)
200
+
201
+ ## ๐Ÿ”— Links
202
+
203
+ - [NPM Package](https://www.npmjs.com/package/@crownpeak/dqm-react-component)
204
+ - [GitHub Repository](https://github.com/Crownpeak/dqm-react-component)
205
+ - [Material-UI Documentation](https://mui.com/)
206
+
207
+ ## ๐Ÿ“ Changelog
208
+
209
+ See [CHANGELOG.md](./CHANGELOG.md) for release history.
210
+
211
+ ---
212
+
213
+ Made with โค๏ธ by the Crownpeak team
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ import { DQMSidebarProps } from './types';
3
+ export declare const DQMSidebar: React.FC<DQMSidebarProps>;
4
+ export default DQMSidebar;
5
+ //# sourceMappingURL=DQMSidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DQMSidebar.d.ts","sourceRoot":"","sources":["../src/DQMSidebar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAuC9D,OAAO,KAAK,EAA8B,eAAe,EAAc,MAAM,SAAS,CAAC;AAkBvF,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAonEhD,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { default as React } from 'react';
2
+ import { ErrorBoundaryProps } from './types';
3
+ /**
4
+ * ErrorBoundary
5
+ * Catches render / lifecycle errors in the React tree below.
6
+ * Provides a user friendly fallback UI and a way to inspect details.
7
+ * Async errors (event handlers, promises) must be caught manually.
8
+ */
9
+ interface ErrorBoundaryState {
10
+ hasError: boolean;
11
+ error?: Error | null;
12
+ errorInfo?: React.ErrorInfo | null;
13
+ showDetails: boolean;
14
+ errorId?: string;
15
+ }
16
+ export declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
17
+ state: ErrorBoundaryState;
18
+ static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState>;
19
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
20
+ componentDidUpdate(prevProps: ErrorBoundaryProps): void;
21
+ private reset;
22
+ private generateErrorId;
23
+ private logErrorToService;
24
+ private handleReload;
25
+ private handleToggleDetails;
26
+ render(): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode>> | import("react/jsx-runtime").JSX.Element;
27
+ }
28
+ /**
29
+ * Simple helper to wrap children with ErrorBoundary while computing reset keys.
30
+ * Can be used in layouts where hooks are available.
31
+ */
32
+ export declare const withErrorBoundary: (children: React.ReactNode, resetKeys?: unknown[]) => import("react/jsx-runtime").JSX.Element;
33
+ export {};
34
+ //# sourceMappingURL=ErrorBoundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../src/ErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAW1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;;GAKG;AAEH,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IACxF,KAAK,EAAE,kBAAkB,CAMvB;IAEF,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAI1E,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS;IAO1D,kBAAkB,CAAC,SAAS,EAAE,kBAAkB;IAShD,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,YAAY,CAElB;IAEF,OAAO,CAAC,mBAAmB,CAEzB;IAEF,MAAM;CAiEP;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,CAAC,SAAS,EAAE,YAAY,OAAO,EAAE,4CAEjF,CAAC"}