@wandelbots/wandelbots-js-react-components 2.34.2 → 2.35.0-pr.feature-replace-forward-trigger-build.377.c42fff6
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 +141 -151
- package/dist/components/AppHeader.d.ts +34 -0
- package/dist/components/AppHeader.d.ts.map +1 -0
- package/dist/components/CopyableText.d.ts +3 -2
- package/dist/components/CopyableText.d.ts.map +1 -1
- package/dist/components/CycleTimer.d.ts +33 -16
- package/dist/components/CycleTimer.d.ts.map +1 -1
- package/dist/components/DataGrid.d.ts +66 -0
- package/dist/components/DataGrid.d.ts.map +1 -0
- package/dist/components/LogPanel.d.ts +38 -0
- package/dist/components/LogPanel.d.ts.map +1 -0
- package/dist/components/LogStore.d.ts +12 -0
- package/dist/components/LogStore.d.ts.map +1 -0
- package/dist/components/LogViewer.d.ts +46 -0
- package/dist/components/LogViewer.d.ts.map +1 -0
- package/dist/components/ProgramControl.d.ts +8 -2
- package/dist/components/ProgramControl.d.ts.map +1 -1
- package/dist/components/ProgramStateIndicator.d.ts +1 -1
- package/dist/components/ProgramStateIndicator.d.ts.map +1 -1
- package/dist/components/RobotCard.d.ts +103 -0
- package/dist/components/RobotCard.d.ts.map +1 -0
- package/dist/components/RobotListItem.d.ts +34 -0
- package/dist/components/RobotListItem.d.ts.map +1 -0
- package/dist/components/RobotSetupReadinessIndicator.d.ts +31 -0
- package/dist/components/RobotSetupReadinessIndicator.d.ts.map +1 -0
- package/dist/components/RobotSetupReadinessIndicator.test.d.ts +2 -0
- package/dist/components/RobotSetupReadinessIndicator.test.d.ts.map +1 -0
- package/dist/components/SelectableFab.d.ts +2 -1
- package/dist/components/SelectableFab.d.ts.map +1 -1
- package/dist/components/TabBar.d.ts +32 -0
- package/dist/components/TabBar.d.ts.map +1 -0
- package/dist/components/robots/Robot.d.ts +3 -2
- package/dist/components/robots/Robot.d.ts.map +1 -1
- package/dist/components/robots/manufacturerHomePositions.d.ts +21 -0
- package/dist/components/robots/manufacturerHomePositions.d.ts.map +1 -0
- package/dist/icons/DropdownArrowIcon.d.ts +3 -0
- package/dist/icons/DropdownArrowIcon.d.ts.map +1 -0
- package/dist/icons/index.d.ts +1 -0
- package/dist/icons/index.d.ts.map +1 -1
- package/dist/index.cjs +50 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11381 -9522
- package/dist/index.js.map +1 -1
- package/dist/themes/createDarkTheme.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/components/AppHeader.md +84 -0
- package/src/components/AppHeader.tsx +199 -0
- package/src/components/CopyableText.tsx +70 -73
- package/src/components/CycleTimer.tsx +384 -159
- package/src/components/DataGrid.tsx +659 -0
- package/src/components/LogPanel.tsx +69 -0
- package/src/components/LogStore.ts +44 -0
- package/src/components/LogViewer.tsx +370 -0
- package/src/components/ProgramControl.tsx +27 -12
- package/src/components/ProgramStateIndicator.tsx +25 -8
- package/src/components/RobotCard.tsx +568 -0
- package/src/components/RobotListItem.tsx +150 -0
- package/src/components/RobotSetupReadinessIndicator.test.tsx +60 -0
- package/src/components/RobotSetupReadinessIndicator.tsx +124 -0
- package/src/components/SelectableFab.tsx +14 -15
- package/src/components/TabBar.tsx +147 -0
- package/src/components/robots/Robot.tsx +5 -2
- package/src/components/robots/manufacturerHomePositions.ts +76 -0
- package/src/i18n/locales/de/translations.json +8 -1
- package/src/i18n/locales/en/translations.json +8 -1
- package/src/icons/DropdownArrowIcon.tsx +13 -0
- package/src/icons/chevronDown.svg +3 -0
- package/src/icons/index.ts +1 -0
- package/src/index.ts +14 -0
- package/src/themes/createDarkTheme.ts +75 -1
package/README.md
CHANGED
|
@@ -2,207 +2,197 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://npmjs.org/package/@wandelbots/wandelbots-js-react-components) [](https://bundlephobia.com/package/@wandelbots/wandelbots-js-react-components) [](https://github.com/wandelbotsgmbh/wandelbots-js-react-components/actions/workflows/release.yml) [](https://wandelbotsgmbh.github.io/wandelbots-js-react-components)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
React UI components for building robotics applications on the [Wandelbots Nova platform](https://www.wandelbots.com/).
|
|
6
|
+
|
|
7
|
+
Built with TypeScript, Material-UI, and React Three Fiber. Provides robot control interfaces, 3D visualizations, and automation components that integrate with the Nova ecosystem.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
12
|
npm install @wandelbots/wandelbots-js-react-components
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
## Getting Started
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
For setup instructions, integration examples, and basic usage patterns, visit the **[Getting Started Guide](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/gettingstarted--docs)** in our Storybook documentation.
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
import { JoggingPanel, ... } from '@wandelbots/wandelbots-js-react-components'
|
|
17
|
-
```
|
|
19
|
+
## Documentation
|
|
18
20
|
|
|
19
|
-
See the [Storybook](https://wandelbotsgmbh.github.io/wandelbots-js-react-components) for
|
|
20
|
-
|
|
21
|
-
### Index
|
|
22
|
-
|
|
23
|
-
<table>
|
|
24
|
-
<tr>
|
|
25
|
-
<td valign="top">
|
|
26
|
-
<ul>
|
|
27
|
-
<li><a href="#ui">UI</a></li>
|
|
28
|
-
<ul>
|
|
29
|
-
<li><a href="#joggingpanel">JoggingPanel</a></li>
|
|
30
|
-
<li><a href="#wandelscripteditor">WandelscriptEditor</a></li>
|
|
31
|
-
<li><a href="#theming">Theming</a></li>
|
|
32
|
-
</ul>
|
|
33
|
-
<li><a href="#viewport">3D Viewport</a></li>
|
|
34
|
-
<ul>
|
|
35
|
-
<li><a href="#robot">Robot</a></li>
|
|
36
|
-
<li><a href="#lightning">Lightning</a></li>
|
|
37
|
-
<li><a href="#safety">Safety Zones</a></li>
|
|
38
|
-
</ul>
|
|
39
|
-
</ul>
|
|
40
|
-
</td>
|
|
41
|
-
</tr>
|
|
42
|
-
</table>
|
|
43
|
-
|
|
44
|
-
### UI
|
|
45
|
-
|
|
46
|
-
#### JoggingPanel
|
|
47
|
-
|
|
48
|
-
<a href="https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/jogging-joggingpanel--docs">
|
|
49
|
-
<img width="20%" alt="jogging" src="https://github.com/user-attachments/assets/07d8bd72-9378-4199-8f54-d101c857797c">
|
|
50
|
-
</a>
|
|
51
|
-
|
|
52
|
-
The JoggingPanel is a high-level user interface for manually moving a robot using the Wandelbots stack. It needs only a `NovaClient` instance from [wandelbots-js](https://github.com/wandelbotsgmbh/wandelbots-js) and the id of a motion group to connect to.
|
|
53
|
-
|
|
54
|
-
```tsx
|
|
55
|
-
type JoggingPanelProps = {
|
|
56
|
-
/** Connection to a Nova instance to use for jogging */
|
|
57
|
-
nova: NovaClient
|
|
58
|
-
/** Id of the motion group to move e.g. 0@ur5e **/
|
|
59
|
-
motionGroupId: string
|
|
60
|
-
/** Callback with the jogging panel's state store for further customization/config */
|
|
61
|
-
onSetup: (store: JoggingStore) => void
|
|
62
|
-
/** Any children will go at the bottom of the panel under the default components */
|
|
63
|
-
children?: React.ReactNode
|
|
64
|
-
}
|
|
65
|
-
```
|
|
21
|
+
See the [Storybook](https://wandelbotsgmbh.github.io/wandelbots-js-react-components) for interactive examples and API documentation.
|
|
66
22
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
The WandelscriptEditor provides an interface for editing snippets of Wandelscript code with the appropriate syntax highlighting. It uses the [Monaco](https://microsoft.github.io/monaco-editor/) editor under the hood.
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
type WandelscriptEditorProps = {
|
|
73
|
-
/** The current Wandelscript content of the code editor (controlled component) */
|
|
74
|
-
code?: string
|
|
75
|
-
/** What to do when the user edits the code */
|
|
76
|
-
onChange?: (
|
|
77
|
-
code: string | undefined,
|
|
78
|
-
ev: editor.IModelContentChangedEvent,
|
|
79
|
-
) => void
|
|
80
|
-
/** Callback to further configure monaco on startup if needed */
|
|
81
|
-
monacoSetup?: (monaco: Monaco) => void
|
|
82
|
-
}
|
|
83
|
-
```
|
|
23
|
+
## Components
|
|
84
24
|
|
|
85
|
-
|
|
25
|
+
### Robot Control & Jogging
|
|
86
26
|
|
|
87
|
-
|
|
27
|
+
Manual robot control interfaces.
|
|
88
28
|
|
|
89
|
-
|
|
90
|
-
To make the components look exactly like they do in the storybook, pass the [Wandelbots MUI theme](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/theming-wandelbots-mui-theme--docs) to ThemeProvider.
|
|
29
|
+
**[JoggingPanel](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/jogging-joggingpanel--docs)** - Complete jogging interface with cartesian and joint controls
|
|
91
30
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
31
|
+
- Dual-mode operation (Cartesian & Joint space)
|
|
32
|
+
- Real-time velocity control
|
|
33
|
+
- Multiple coordinate systems support
|
|
95
34
|
|
|
96
|
-
|
|
35
|
+
**Individual Jogging Controls**
|
|
97
36
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
```
|
|
37
|
+
- **[JoggingCartesianAxisControl](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/jogging-joggingcartesianaxiscontrol--docs)** - Single-axis cartesian movement
|
|
38
|
+
- **[JoggingJointRotationControl](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/jogging-joggingjointrotationcontrol--docs)** - Individual joint controls
|
|
39
|
+
- **[VelocitySlider](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/jogging-velocityslider--docs)** - Speed adjustment interface
|
|
102
40
|
|
|
103
|
-
###
|
|
41
|
+
### Program Execution
|
|
104
42
|
|
|
105
|
-
|
|
43
|
+
Program control and monitoring components.
|
|
106
44
|
|
|
107
|
-
|
|
108
|
-
<img width="20%" alt="Robot" src="https://github.com/user-attachments/assets/da661136-8b53-48ba-85de-63b09e3b51f3">
|
|
109
|
-
</a>
|
|
45
|
+
**[ProgramControl](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-programcontrol--docs)** - Program lifecycle management
|
|
110
46
|
|
|
111
|
-
|
|
47
|
+
- Play, pause, stop functionality
|
|
48
|
+
- State machine integration
|
|
49
|
+
- Manual reset capabilities
|
|
112
50
|
|
|
113
|
-
|
|
114
|
-
<Robot connectedMotionGroup={connectedMotionGroup} />
|
|
115
|
-
```
|
|
51
|
+
**[ProgramStateIndicator](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-programstateindicator--docs)** - Visual program status
|
|
116
52
|
|
|
117
|
-
|
|
53
|
+
- Live execution state monitoring
|
|
54
|
+
- Error state visualization
|
|
118
55
|
|
|
119
|
-
|
|
56
|
+
### 3D Visualization & Robotics
|
|
120
57
|
|
|
121
|
-
|
|
122
|
-
<Robot
|
|
123
|
-
getModel={() => `public/${connectedMotionGroup.modelFromController}.glb`}
|
|
124
|
-
connectedMotionGroup={connectedMotionGroup}
|
|
125
|
-
/>
|
|
126
|
-
```
|
|
58
|
+
3D components for robot visualization.
|
|
127
59
|
|
|
128
|
-
|
|
129
|
-
export type ConnectecMotionGroupRobotProps = {
|
|
130
|
-
connectedMotionGroup: ConnectedMotionGroup // The connected motion group from wandelbots-js
|
|
131
|
-
getModel?: (modelFromController: string) => string // A function that returns the URL of the robot model
|
|
132
|
-
transparentColor?: string // Whether the robot should be displayed transparently
|
|
133
|
-
} & GroupProps
|
|
134
|
-
```
|
|
60
|
+
**[Robot](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/3d-view-robot--docs)** - Real-time 3D robot rendering
|
|
135
61
|
|
|
136
|
-
|
|
62
|
+
- Live pose updates from motion groups
|
|
63
|
+
- Extensive robot model support from major manufacturers
|
|
64
|
+
- [Supported Models](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/story/3d-view-robot-supported-models--abb-1010-037-15) - ABB, FANUC, KUKA, Universal Robots, Yaskawa (100+ models)
|
|
65
|
+
- Automatic model loading from CDN
|
|
137
66
|
|
|
138
|
-
|
|
67
|
+
**[SafetyZonesRenderer](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/3d-view-safetyzonesrenderer--docs)** - 3D safety visualization
|
|
139
68
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
rapidlyChangingMotionState={rapidlyChangingMotionState}
|
|
143
|
-
dhParameters={dhParameters as any}
|
|
144
|
-
modelFromController={modelFromController || ""}
|
|
145
|
-
getModel={() => `./robot-pad/models/${modelFromController}.glb`}
|
|
146
|
-
/>
|
|
147
|
-
```
|
|
69
|
+
- Real-time safety zone rendering
|
|
70
|
+
- Visual collision boundaries
|
|
148
71
|
|
|
149
|
-
|
|
150
|
-
export type SupportedRobotProps = {
|
|
151
|
-
rapidlyChangingMotionState: MotionGroupStateResponse // The motion state of the robot
|
|
152
|
-
modelFromController: string // The model name of the robot
|
|
153
|
-
dhParameters: DHParameter[] // The DH parameters of the robot
|
|
154
|
-
getModel?: (modelFromController: string) => string // A function that returns the URL of the robot model
|
|
155
|
-
transparentColor?: string // Whether the robot should be displayed transparently
|
|
156
|
-
} & GroupProps
|
|
157
|
-
```
|
|
72
|
+
**[TrajectoryRenderer](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/3d-view-trajectoryrenderer--docs)** - Motion path visualization
|
|
158
73
|
|
|
159
|
-
|
|
74
|
+
- Real-time trajectory display
|
|
75
|
+
- Path planning visualization
|
|
160
76
|
|
|
161
|
-
|
|
77
|
+
### Safety & Monitoring
|
|
162
78
|
|
|
163
|
-
|
|
164
|
-
<PresetEnvironment>
|
|
165
|
-
```
|
|
79
|
+
Safety components for production environments.
|
|
166
80
|
|
|
167
|
-
|
|
81
|
+
**[SafetyBar](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/safety-safetybar--docs)** - Centralized safety status
|
|
168
82
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
</a>
|
|
83
|
+
- Real-time safety monitoring
|
|
84
|
+
- Emergency stop integration
|
|
172
85
|
|
|
173
|
-
|
|
86
|
+
### Code Editing
|
|
174
87
|
|
|
175
|
-
|
|
176
|
-
<SafetyZonesRenderer safetyZones={connectedMotionGroup.safetyZones || []} />
|
|
177
|
-
```
|
|
88
|
+
Code editing capabilities for robot programming.
|
|
178
89
|
|
|
179
|
-
|
|
90
|
+
**[WandelscriptEditor](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/wandelscript-wandelscripteditor--docs)** - Code editor
|
|
180
91
|
|
|
181
|
-
|
|
92
|
+
- Monaco editor integration
|
|
93
|
+
- Wandelscript syntax highlighting
|
|
94
|
+
- IntelliSense support
|
|
182
95
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
96
|
+
### Data & Interface Components
|
|
97
|
+
|
|
98
|
+
UI components for data display and user interaction.
|
|
99
|
+
|
|
100
|
+
**Data Components**
|
|
101
|
+
|
|
102
|
+
- **[DataGrid](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-datagrid--docs)** - Data tables with robotics data formatting
|
|
103
|
+
- **[LogPanel](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-logpanel--docs)** - Real-time log display and filtering
|
|
104
|
+
- **[CycleTimer](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-cycletimer--docs)** - Production cycle timing and metrics
|
|
105
|
+
|
|
106
|
+
**Robot Management**
|
|
107
|
+
|
|
108
|
+
- **[RobotCard](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-robotcard--docs)** - Robot overview cards with status
|
|
109
|
+
- **[RobotListItem](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-robotlistitem--docs)** - List view for multiple robots
|
|
110
|
+
- **[RobotSetupReadinessIndicator](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/components-robotsetupreadinessindicator--docs)** - Setup validation status
|
|
111
|
+
|
|
112
|
+
**Navigation**
|
|
113
|
+
|
|
114
|
+
- **[AppHeader](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/navigation-appheader--docs)** - Application header with branding
|
|
115
|
+
- **[TabBar](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/navigation-tabbar--docs)** - Multi-section navigation
|
|
116
|
+
|
|
117
|
+
### Theming & Styling
|
|
118
|
+
|
|
119
|
+
Styling system for consistent robotics applications.
|
|
186
120
|
|
|
187
|
-
|
|
121
|
+
**[Theming components](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/theming-theming-components--docs)** - Interactive theming examples
|
|
122
|
+
|
|
123
|
+
- Component theming demonstrations
|
|
124
|
+
- Customization patterns
|
|
125
|
+
|
|
126
|
+
**[Wandelbots MUI Theme](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/theming-wandelbots-mui-theme--docs)** - Material-UI theme
|
|
127
|
+
|
|
128
|
+
- Dark/light mode support
|
|
129
|
+
- Robotics-specific color schemes
|
|
130
|
+
- Material Design integration
|
|
131
|
+
|
|
132
|
+
## Architecture & Integration
|
|
133
|
+
|
|
134
|
+
### Nova Platform Integration
|
|
135
|
+
|
|
136
|
+
Components integrate with the Wandelbots Nova ecosystem:
|
|
137
|
+
|
|
138
|
+
- **NovaClient Integration** - Components accept either `NovaClient` instances or URL strings
|
|
139
|
+
- **Real-time Updates** - WebSocket connections for live robot state updates
|
|
140
|
+
- **Motion Group Management** - Direct integration with `ConnectedMotionGroup` objects
|
|
141
|
+
- **State Synchronization** - Automatic state management with MobX reactivity
|
|
142
|
+
|
|
143
|
+
### Technical Foundation
|
|
144
|
+
|
|
145
|
+
- **TypeScript** - Full type safety and enhanced developer experience
|
|
146
|
+
- **Material-UI v6/v7** - Professional design system and theming
|
|
147
|
+
- **React Three Fiber** - High-performance 3D rendering for robotics visualization
|
|
148
|
+
- **MobX** - Reactive state management for real-time updates
|
|
149
|
+
- **i18next** - Internationalization support for global deployment
|
|
150
|
+
|
|
151
|
+
## Installation & Setup
|
|
152
|
+
|
|
153
|
+
### Prerequisites
|
|
154
|
+
|
|
155
|
+
- React 18+ or 19+
|
|
156
|
+
- Material-UI v6 or v7
|
|
157
|
+
- @emotion/react and @emotion/styled
|
|
158
|
+
|
|
159
|
+
### Optional Dependencies (for 3D components)
|
|
160
|
+
|
|
161
|
+
- @react-three/fiber, @react-three/drei, three, three-stdlib
|
|
162
|
+
|
|
163
|
+
See the [Getting Started Guide](https://wandelbotsgmbh.github.io/wandelbots-js-react-components/?path=/docs/gettingstarted--docs) for complete setup instructions and integration examples.
|
|
164
|
+
|
|
165
|
+
## Development
|
|
166
|
+
|
|
167
|
+
To set up the project for development:
|
|
188
168
|
|
|
189
169
|
```bash
|
|
190
|
-
|
|
170
|
+
git clone https://github.com/wandelbotsgmbh/wandelbots-js-react-components.git
|
|
171
|
+
cd wandelbots-js-react-components
|
|
172
|
+
npm install
|
|
173
|
+
npm run dev # Start Storybook development server
|
|
191
174
|
```
|
|
192
175
|
|
|
193
176
|
### Local Testing
|
|
194
177
|
|
|
195
|
-
|
|
178
|
+
Build and test the package locally:
|
|
196
179
|
|
|
197
180
|
```bash
|
|
198
181
|
npm run build
|
|
199
182
|
npm pack
|
|
183
|
+
npm install /path/to/wandelbots-wandelbots-js-react-components-x.x.x.tgz
|
|
200
184
|
```
|
|
201
185
|
|
|
202
|
-
|
|
186
|
+
> **Note:** Use `npm install` with the `.tgz` file instead of `npm link` due to peer dependency requirements with React Three Fiber components.
|
|
203
187
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
188
|
+
## Contributing
|
|
189
|
+
|
|
190
|
+
We welcome contributions! Please see our contributing guidelines and feel free to submit issues and pull requests.
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
This project is licensed under the terms specified in the LICENSE file.
|
|
195
|
+
|
|
196
|
+
---
|
|
207
197
|
|
|
208
|
-
|
|
198
|
+
[Explore the Storybook](https://wandelbotsgmbh.github.io/wandelbots-js-react-components) • [Visit Wandelbots.com](https://www.wandelbots.com/)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type SxProps } from "@mui/material";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
export type AppItem = {
|
|
4
|
+
/** Unique identifier for the app */
|
|
5
|
+
id: string;
|
|
6
|
+
/** Display name of the app */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Icon component to display */
|
|
9
|
+
icon: ReactNode;
|
|
10
|
+
/** URL or callback to navigate to the app */
|
|
11
|
+
href?: string;
|
|
12
|
+
/** Click handler for the app */
|
|
13
|
+
onClick?: () => void;
|
|
14
|
+
};
|
|
15
|
+
export type AppHeaderProps = {
|
|
16
|
+
/** Current app icon */
|
|
17
|
+
appIcon: ReactNode;
|
|
18
|
+
/** Current app name */
|
|
19
|
+
appName: string;
|
|
20
|
+
/** List of other available apps */
|
|
21
|
+
apps?: AppItem[];
|
|
22
|
+
/** Callback when an app is selected */
|
|
23
|
+
onAppSelect?: (app: AppItem) => void;
|
|
24
|
+
/** Additional styling */
|
|
25
|
+
sx?: SxProps;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* A top navigation header component that displays the current app and provides
|
|
29
|
+
* a dropdown menu to navigate to other apps.
|
|
30
|
+
*/
|
|
31
|
+
export declare const AppHeader: ((props: AppHeaderProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
32
|
+
displayName: string;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=AppHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../src/components/AppHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,OAAO,EAGb,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAmB,KAAK,SAAS,EAAY,MAAM,OAAO,CAAA;AAIjE,MAAM,MAAM,OAAO,GAAG;IACpB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,gCAAgC;IAChC,IAAI,EAAE,SAAS,CAAA;IACf,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,uBAAuB;IACvB,OAAO,EAAE,SAAS,CAAA;IAClB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,mCAAmC;IACnC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAA;IAChB,uCAAuC;IACvC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC,yBAAyB;IACzB,EAAE,CAAC,EAAE,OAAO,CAAA;CACb,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,WACH,cAAc;;CAsJhC,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export declare const CopyableText:
|
|
1
|
+
export declare const CopyableText: (props: {
|
|
2
2
|
label?: string;
|
|
3
3
|
value: string;
|
|
4
|
-
|
|
4
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
5
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
5
6
|
//# sourceMappingURL=CopyableText.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyableText.d.ts","sourceRoot":"","sources":["../../src/components/CopyableText.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY;
|
|
1
|
+
{"version":3,"file":"CopyableText.d.ts","sourceRoot":"","sources":["../../src/components/CopyableText.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,OAAO;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;CAChC,4CA4EA,CAAA"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export interface CycleTimerProps {
|
|
2
2
|
/**
|
|
3
3
|
* Callback that receives the timer control functions:
|
|
4
|
-
* - `startNewCycle(maxTimeSeconds
|
|
4
|
+
* - `startNewCycle(maxTimeSeconds?, elapsedSeconds?)` - Start a new timer cycle (if maxTimeSeconds is omitted, runs as count-up timer)
|
|
5
5
|
* - `pause()` - Pause the countdown while preserving remaining time
|
|
6
6
|
* - `resume()` - Resume countdown from where it was paused
|
|
7
7
|
* - `isPaused()` - Check current pause state
|
|
8
8
|
*/
|
|
9
9
|
onCycleComplete: (controls: {
|
|
10
|
-
startNewCycle: (maxTimeSeconds
|
|
10
|
+
startNewCycle: (maxTimeSeconds?: number, elapsedSeconds?: number) => void;
|
|
11
11
|
pause: () => void;
|
|
12
12
|
resume: () => void;
|
|
13
13
|
isPaused: () => boolean;
|
|
@@ -22,17 +22,22 @@ export interface CycleTimerProps {
|
|
|
22
22
|
compact?: boolean;
|
|
23
23
|
/** Additional CSS classes */
|
|
24
24
|
className?: string;
|
|
25
|
+
/** Whether the timer is in an error state (pauses timer and shows error styling) */
|
|
26
|
+
hasError?: boolean;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
|
-
* A circular gauge timer component that shows the remaining time of a cycle
|
|
29
|
+
* A circular gauge timer component that shows the remaining time of a cycle or counts up
|
|
28
30
|
*
|
|
29
31
|
* Features:
|
|
30
32
|
* - Circular gauge with 264px diameter and 40px thickness
|
|
31
|
-
* -
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
33
|
+
* - Two modes: count-down (with max time) or count-up (without max time)
|
|
34
|
+
* - Count-down mode: shows remaining time prominently, counts down to zero
|
|
35
|
+
* - Count-up mode: shows elapsed time, gauge progresses in minute steps
|
|
36
|
+
* - Displays appropriate labels based on mode
|
|
37
|
+
* - Automatically counts down/up and triggers callback when reaching zero (count-down only)
|
|
34
38
|
* - Full timer control: start, pause, resume functionality
|
|
35
39
|
* - Support for starting with elapsed time (resume mid-cycle)
|
|
40
|
+
* - Error state support: pauses timer and shows error styling (red color)
|
|
36
41
|
* - Smooth spring-based progress animations for all state transitions
|
|
37
42
|
* - Fully localized with i18next
|
|
38
43
|
* - Material-UI theming integration
|
|
@@ -44,37 +49,49 @@ export interface CycleTimerProps {
|
|
|
44
49
|
* @param variant - Visual variant: "default" (large gauge) or "small" (animated icon with text)
|
|
45
50
|
* @param compact - For small variant: whether to hide remaining time details
|
|
46
51
|
* @param className - Additional CSS classes
|
|
52
|
+
* @param hasError - Whether the timer is in an error state (pauses timer and shows error styling)
|
|
47
53
|
*
|
|
48
54
|
* Usage:
|
|
49
55
|
* ```tsx
|
|
56
|
+
* // Count-down timer (with max time)
|
|
50
57
|
* <CycleTimer
|
|
51
58
|
* onCycleComplete={(controls) => {
|
|
52
|
-
* // Start a 5-minute cycle
|
|
59
|
+
* // Start a 5-minute countdown cycle
|
|
53
60
|
* controls.startNewCycle(300)
|
|
54
61
|
*
|
|
55
62
|
* // Or start a 5-minute cycle with 2 minutes already elapsed
|
|
56
63
|
* controls.startNewCycle(300, 120)
|
|
64
|
+
* }}
|
|
65
|
+
* onCycleEnd={() => console.log('Cycle completed!')}
|
|
66
|
+
* />
|
|
57
67
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
68
|
+
* // Count-up timer (no max time)
|
|
69
|
+
* <CycleTimer
|
|
70
|
+
* onCycleComplete={(controls) => {
|
|
71
|
+
* // Start count-up timer
|
|
72
|
+
* controls.startNewCycle()
|
|
60
73
|
*
|
|
61
|
-
* //
|
|
62
|
-
* controls.
|
|
74
|
+
* // Or start count-up timer with some elapsed time
|
|
75
|
+
* controls.startNewCycle(undefined, 120)
|
|
76
|
+
* }}
|
|
77
|
+
* />
|
|
63
78
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
79
|
+
* // Timer with error state
|
|
80
|
+
* <CycleTimer
|
|
81
|
+
* hasError={errorCondition}
|
|
82
|
+
* onCycleComplete={(controls) => {
|
|
83
|
+
* controls.startNewCycle(300)
|
|
66
84
|
* }}
|
|
67
|
-
* onCycleEnd={() => console.log('Cycle completed!')}
|
|
68
85
|
* />
|
|
69
86
|
* ```
|
|
70
87
|
*
|
|
71
88
|
* Control Functions:
|
|
72
|
-
* - `startNewCycle(maxTimeSeconds
|
|
89
|
+
* - `startNewCycle(maxTimeSeconds?, elapsedSeconds?)` - Start a new timer cycle (omit maxTimeSeconds for count-up mode)
|
|
73
90
|
* - `pause()` - Pause the countdown while preserving remaining time
|
|
74
91
|
* - `resume()` - Resume countdown from where it was paused
|
|
75
92
|
* - `isPaused()` - Check current pause state
|
|
76
93
|
*/
|
|
77
|
-
export declare const CycleTimer: (({ onCycleComplete, onCycleEnd, autoStart, variant, compact, className, }: CycleTimerProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
94
|
+
export declare const CycleTimer: (({ onCycleComplete, onCycleEnd, autoStart, variant, compact, className, hasError, }: CycleTimerProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
78
95
|
displayName: string;
|
|
79
96
|
};
|
|
80
97
|
//# sourceMappingURL=CycleTimer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CycleTimer.d.ts","sourceRoot":"","sources":["../../src/components/CycleTimer.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE;QAC1B,aAAa,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"CycleTimer.d.ts","sourceRoot":"","sources":["../../src/components/CycleTimer.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,eAAe,EAAE,CAAC,QAAQ,EAAE;QAC1B,aAAa,EAAE,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;QACzE,KAAK,EAAE,MAAM,IAAI,CAAA;QACjB,MAAM,EAAE,MAAM,IAAI,CAAA;QAClB,QAAQ,EAAE,MAAM,OAAO,CAAA;KACxB,KAAK,IAAI,CAAA;IACV,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,uEAAuE;IACvE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kCAAkC;IAClC,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiEG;AACH,eAAO,MAAM,UAAU,wFAUhB,eAAe;;CA0lBrB,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Box } from "@mui/material";
|
|
2
|
+
import { type DataGridProps, type GridColDef, type GridRowParams } from "@mui/x-data-grid";
|
|
3
|
+
export interface WandelbotsDataGridProps<T = Record<string, unknown>> {
|
|
4
|
+
/**
|
|
5
|
+
* Array of data items to display in the grid
|
|
6
|
+
*/
|
|
7
|
+
data: T[];
|
|
8
|
+
/**
|
|
9
|
+
* Column definitions for the DataGrid
|
|
10
|
+
*/
|
|
11
|
+
columns: GridColDef[];
|
|
12
|
+
/**
|
|
13
|
+
* Function to transform data items into DataGrid rows
|
|
14
|
+
* Should return an object with an 'id' field and other fields matching column definitions
|
|
15
|
+
*/
|
|
16
|
+
getRowData: (item: T) => Record<string, unknown> & {
|
|
17
|
+
id: string | number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Callback when a row is clicked
|
|
21
|
+
*/
|
|
22
|
+
onRowClick?: (item: T, params: GridRowParams) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Currently selected item (for highlighting)
|
|
25
|
+
*/
|
|
26
|
+
selectedItem?: T | null;
|
|
27
|
+
/**
|
|
28
|
+
* Function to get the ID of an item (used for selection highlighting)
|
|
29
|
+
*/
|
|
30
|
+
getItemId?: (item: T) => string | number;
|
|
31
|
+
/**
|
|
32
|
+
* Title displayed in the toolbar
|
|
33
|
+
*/
|
|
34
|
+
title?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Show item count in title
|
|
37
|
+
* @default true
|
|
38
|
+
*/
|
|
39
|
+
showCount?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Placeholder text for the search input
|
|
42
|
+
* @default "Search programs"
|
|
43
|
+
*/
|
|
44
|
+
searchPlaceholder?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Additional DataGrid props to pass through
|
|
47
|
+
*/
|
|
48
|
+
dataGridProps?: Partial<DataGridProps>;
|
|
49
|
+
/**
|
|
50
|
+
* Custom toolbar component to replace the default one
|
|
51
|
+
*/
|
|
52
|
+
CustomToolbar?: React.ComponentType;
|
|
53
|
+
/**
|
|
54
|
+
* Select the first item by default
|
|
55
|
+
* @default false
|
|
56
|
+
*/
|
|
57
|
+
selectFirstByDefault?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Custom sx styles for the root container
|
|
60
|
+
*/
|
|
61
|
+
sx?: React.ComponentProps<typeof Box>["sx"];
|
|
62
|
+
}
|
|
63
|
+
export declare const WandelbotsDataGrid: (<T>({ data, columns, getRowData, onRowClick, selectedItem, getItemId, title, showCount, searchPlaceholder, dataGridProps, CustomToolbar, selectFirstByDefault, sx, }: WandelbotsDataGridProps<T>) => import("react/jsx-runtime").JSX.Element) & {
|
|
64
|
+
displayName: string;
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=DataGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataGrid.d.ts","sourceRoot":"","sources":["../../src/components/DataGrid.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,GAAG,EAAiC,MAAM,eAAe,CAAA;AAClE,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,UAAU,EACf,KAAK,aAAa,EAQnB,MAAM,kBAAkB,CAAA;AAKzB,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAClE;;OAEG;IACH,IAAI,EAAE,CAAC,EAAE,CAAA;IAET;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAA;IAErB;;;OAGG;IACH,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;IAE1E;;OAEG;IACH,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAA;IAErD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,IAAI,CAAA;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,CAAA;IAExC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;IAEtC;;OAEG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAA;IAEnC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;OAEG;IACH,EAAE,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;CAC5C;AAED,eAAO,MAAM,kBAAkB,IAE1B,CAAC,oKAcC,uBAAuB,CAAC,CAAC,CAAC;;CAmiBhC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SxProps } from "@mui/material";
|
|
2
|
+
import { LogStore } from "./LogStore";
|
|
3
|
+
export type LogPanelProps = {
|
|
4
|
+
/** Log store instance to use, or create one automatically if not provided */
|
|
5
|
+
store?: LogStore;
|
|
6
|
+
/** Height of the component */
|
|
7
|
+
height?: string | number;
|
|
8
|
+
/** Additional styles */
|
|
9
|
+
sx?: SxProps;
|
|
10
|
+
/** Ref to the log store for external access */
|
|
11
|
+
onStoreReady?: (store: LogStore) => void;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A complete log panel component with built-in state management.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function MyComponent() {
|
|
19
|
+
* const [logStore, setLogStore] = useState<LogStore>()
|
|
20
|
+
*
|
|
21
|
+
* return (
|
|
22
|
+
* <LogPanel
|
|
23
|
+
* height={400}
|
|
24
|
+
* onStoreReady={setLogStore}
|
|
25
|
+
* />
|
|
26
|
+
* )
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* // Then use the store to add messages
|
|
30
|
+
* logStore?.addInfo("Operation completed successfully")
|
|
31
|
+
* logStore?.addError("Something went wrong")
|
|
32
|
+
* logStore?.addWarning("Warning message")
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const LogPanel: ((props: LogPanelProps) => import("react/jsx-runtime").JSX.Element) & {
|
|
36
|
+
displayName: string;
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=LogPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogPanel.d.ts","sourceRoot":"","sources":["../../src/components/LogPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAI5C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGrC,MAAM,MAAM,aAAa,GAAG;IAC1B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,wBAAwB;IACxB,EAAE,CAAC,EAAE,OAAO,CAAA;IACZ,+CAA+C;IAC/C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;CACzC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,QAAQ,WACF,aAAa;;CA2B/B,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LogLevel, LogMessage } from "./LogViewer";
|
|
2
|
+
export declare class LogStore {
|
|
3
|
+
messages: LogMessage[];
|
|
4
|
+
constructor();
|
|
5
|
+
addMessage: (message: string, level?: LogLevel) => void;
|
|
6
|
+
clearMessages: () => void;
|
|
7
|
+
addInfo: (message: string) => void;
|
|
8
|
+
addWarning: (message: string) => void;
|
|
9
|
+
addError: (message: string) => void;
|
|
10
|
+
addDebug: (message: string) => void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=LogStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogStore.d.ts","sourceRoot":"","sources":["../../src/components/LogStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEvD,qBAAa,QAAQ;IACnB,QAAQ,EAAE,UAAU,EAAE,CAAK;;IAU3B,UAAU,GAAI,SAAS,MAAM,EAAE,QAAO,QAAiB,UAQtD;IAED,aAAa,aAEZ;IAED,OAAO,GAAI,SAAS,MAAM,UAEzB;IAED,UAAU,GAAI,SAAS,MAAM,UAE5B;IAED,QAAQ,GAAI,SAAS,MAAM,UAE1B;IAED,QAAQ,GAAI,SAAS,MAAM,UAE1B;CACF"}
|