rte-utils 1.2.29 → 1.2.30
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 +101 -88
- package/dist/components/Avatar.d.ts +2 -2
- package/dist/components/Avatar.stories.d.ts +2 -2
- package/dist/components/Chip.d.ts +3 -3
- package/dist/components/Chip.stories.d.ts +2 -2
- package/dist/components/Histogram.d.ts +2 -2
- package/dist/components/Histogram.stories.d.ts +2 -2
- package/dist/components/Histogramme.d.ts +22 -0
- package/dist/components/Input.d.ts +2 -2
- package/dist/components/InputNumber.d.ts +2 -2
- package/dist/components/InputNumber.stories.d.ts +2 -2
- package/dist/components/MwhCost.d.ts +2 -2
- package/dist/components/ProductionUnit.d.ts +1 -1
- package/dist/components/ProductionUnit.stories.d.ts +2 -2
- package/dist/components/ProductionUnitContainer.d.ts +1 -1
- package/dist/components/ProductionUnitContainer.stories.d.ts +2 -2
- package/dist/components/Switch.d.ts +2 -2
- package/dist/components/Switch.stories.d.ts +2 -2
- package/dist/components/Timer.d.ts +43 -0
- package/dist/components/Timer.stories.d.ts +17 -0
- package/dist/components/index.d.ts +10 -8
- package/dist/index.css +1 -1
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -15,23 +15,23 @@ npm install rte-utils
|
|
|
15
15
|
You need to import both the component and its CSS styles:
|
|
16
16
|
|
|
17
17
|
```tsx
|
|
18
|
-
import { Histogram, Chip } from
|
|
19
|
-
import
|
|
18
|
+
import { Histogram, Chip } from 'rte-utils';
|
|
19
|
+
import 'rte-utils/dist/index.css'; // Import the CSS styles
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
### Basic Example
|
|
23
23
|
|
|
24
24
|
```tsx
|
|
25
|
-
import React from
|
|
26
|
-
import { Histogram } from
|
|
27
|
-
import
|
|
25
|
+
import React from 'react';
|
|
26
|
+
import { Histogram } from 'rte-utils';
|
|
27
|
+
import 'rte-utils/dist/index.css';
|
|
28
28
|
|
|
29
29
|
function App() {
|
|
30
30
|
return (
|
|
31
31
|
<div>
|
|
32
32
|
<Histogram
|
|
33
|
-
max={{ value: 100, color:
|
|
34
|
-
relative={{ value: 56, color:
|
|
33
|
+
max={{ value: 100, color: '#D3D64E' }}
|
|
34
|
+
relative={{ value: 56, color: '#C0C402' }}
|
|
35
35
|
barWidth={32}
|
|
36
36
|
>
|
|
37
37
|
<div className="histogram-value-container">
|
|
@@ -52,18 +52,18 @@ export default App;
|
|
|
52
52
|
### Advanced Example with Animation
|
|
53
53
|
|
|
54
54
|
```tsx
|
|
55
|
-
import React, { useState } from
|
|
56
|
-
import { Histogram } from
|
|
57
|
-
import
|
|
55
|
+
import React, { useState } from 'react';
|
|
56
|
+
import { Histogram } from 'rte-utils';
|
|
57
|
+
import 'rte-utils/dist/index.css';
|
|
58
58
|
|
|
59
59
|
function EnergyDashboard() {
|
|
60
60
|
const [currentValue, setCurrentValue] = useState(45);
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
|
-
<div style={{ display:
|
|
63
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
64
64
|
<Histogram
|
|
65
|
-
max={{ value: 100, color:
|
|
66
|
-
relative={{ value: currentValue, color:
|
|
65
|
+
max={{ value: 100, color: '#D3D64E' }}
|
|
66
|
+
relative={{ value: currentValue, color: '#C0C402' }}
|
|
67
67
|
barHeight={120}
|
|
68
68
|
barWidth={40}
|
|
69
69
|
>
|
|
@@ -76,9 +76,7 @@ function EnergyDashboard() {
|
|
|
76
76
|
</div>
|
|
77
77
|
</Histogram>
|
|
78
78
|
|
|
79
|
-
<button onClick={() => setCurrentValue((prev) => prev + 10)}>
|
|
80
|
-
Increase (+10)
|
|
81
|
-
</button>
|
|
79
|
+
<button onClick={() => setCurrentValue((prev) => prev + 10)}>Increase (+10)</button>
|
|
82
80
|
</div>
|
|
83
81
|
);
|
|
84
82
|
}
|
|
@@ -87,16 +85,16 @@ function EnergyDashboard() {
|
|
|
87
85
|
### Horizontal Orientation Example
|
|
88
86
|
|
|
89
87
|
```tsx
|
|
90
|
-
import React from
|
|
91
|
-
import { Histogram } from
|
|
92
|
-
import
|
|
88
|
+
import React from 'react';
|
|
89
|
+
import { Histogram } from 'rte-utils';
|
|
90
|
+
import 'rte-utils/dist/index.css';
|
|
93
91
|
|
|
94
92
|
function HorizontalChart() {
|
|
95
93
|
return (
|
|
96
|
-
<div style={{ display:
|
|
94
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
97
95
|
<Histogram
|
|
98
|
-
max={{ value: 100, color:
|
|
99
|
-
relative={{ value: 75, color:
|
|
96
|
+
max={{ value: 100, color: '#D3D64E' }}
|
|
97
|
+
relative={{ value: 75, color: '#C0C402' }}
|
|
100
98
|
barWidth={200} // This becomes height in horizontal mode
|
|
101
99
|
barHeight={24} // This becomes width in horizontal mode
|
|
102
100
|
orientation="horizontal"
|
|
@@ -117,17 +115,17 @@ function HorizontalChart() {
|
|
|
117
115
|
### Custom Corner Radius Example
|
|
118
116
|
|
|
119
117
|
```tsx
|
|
120
|
-
import React from
|
|
121
|
-
import { Histogram } from
|
|
122
|
-
import
|
|
118
|
+
import React from 'react';
|
|
119
|
+
import { Histogram } from 'rte-utils';
|
|
120
|
+
import 'rte-utils/dist/index.css';
|
|
123
121
|
|
|
124
122
|
function CustomCornerChart() {
|
|
125
123
|
return (
|
|
126
|
-
<div style={{ display:
|
|
124
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
127
125
|
{/* Rounded top corners only */}
|
|
128
126
|
<Histogram
|
|
129
|
-
max={{ value: 100, color:
|
|
130
|
-
relative={{ value: 60, color:
|
|
127
|
+
max={{ value: 100, color: '#E0E0E0' }}
|
|
128
|
+
relative={{ value: 60, color: '#4CAF50' }}
|
|
131
129
|
barWidth={32}
|
|
132
130
|
barHeight={120}
|
|
133
131
|
cornerRadius={{
|
|
@@ -140,8 +138,8 @@ function CustomCornerChart() {
|
|
|
140
138
|
|
|
141
139
|
{/* Fully rounded corners */}
|
|
142
140
|
<Histogram
|
|
143
|
-
max={{ value: 100, color:
|
|
144
|
-
relative={{ value: 80, color:
|
|
141
|
+
max={{ value: 100, color: '#F0F0F0', opacity: 0.5 }}
|
|
142
|
+
relative={{ value: 80, color: '#2196F3' }}
|
|
145
143
|
barWidth={32}
|
|
146
144
|
barHeight={120}
|
|
147
145
|
cornerRadius={{
|
|
@@ -154,8 +152,8 @@ function CustomCornerChart() {
|
|
|
154
152
|
|
|
155
153
|
{/* Asymmetric corners */}
|
|
156
154
|
<Histogram
|
|
157
|
-
max={{ value: 100, color:
|
|
158
|
-
relative={{ value: 45, color:
|
|
155
|
+
max={{ value: 100, color: '#FFECB3' }}
|
|
156
|
+
relative={{ value: 45, color: '#FF9800' }}
|
|
159
157
|
barWidth={32}
|
|
160
158
|
barHeight={120}
|
|
161
159
|
cornerRadius={{
|
|
@@ -173,15 +171,15 @@ function CustomCornerChart() {
|
|
|
173
171
|
### Opacity and Advanced Styling Example
|
|
174
172
|
|
|
175
173
|
```tsx
|
|
176
|
-
import React from
|
|
177
|
-
import { Histogram } from
|
|
178
|
-
import
|
|
174
|
+
import React from 'react';
|
|
175
|
+
import { Histogram } from 'rte-utils';
|
|
176
|
+
import 'rte-utils/dist/index.css';
|
|
179
177
|
|
|
180
178
|
function AdvancedStylingChart() {
|
|
181
179
|
return (
|
|
182
180
|
<Histogram
|
|
183
|
-
max={{ value: 100, color:
|
|
184
|
-
relative={{ value: 65, color:
|
|
181
|
+
max={{ value: 100, color: '#000000', opacity: 0.1 }}
|
|
182
|
+
relative={{ value: 65, color: '#E91E63' }}
|
|
185
183
|
barWidth={40}
|
|
186
184
|
barHeight={150}
|
|
187
185
|
orientation="vertical"
|
|
@@ -235,9 +233,26 @@ A histogram component with smooth animations for energy data visualization.
|
|
|
235
233
|
The component uses external CSS classes for styling. Make sure to import the CSS file:
|
|
236
234
|
|
|
237
235
|
```tsx
|
|
238
|
-
import
|
|
236
|
+
import 'rte-utils/dist/index.css';
|
|
239
237
|
```
|
|
240
238
|
|
|
239
|
+
## Scripts
|
|
240
|
+
|
|
241
|
+
Development & quality commands:
|
|
242
|
+
|
|
243
|
+
- `npm run build` – build the library (Rollup)
|
|
244
|
+
- `npm run dev` – watch mode build
|
|
245
|
+
- `npm run test` – run tests
|
|
246
|
+
- `npm run lint` – run ESLint (no fixes)
|
|
247
|
+
- `npm run lint:fix` – run ESLint with auto fixes
|
|
248
|
+
- `npm run format` – apply Prettier formatting
|
|
249
|
+
- `npm run format:check` – check formatting (CI)
|
|
250
|
+
- `npm run typecheck` – TypeScript diagnostics (no emit)
|
|
251
|
+
- `npm run storybook` – start Storybook
|
|
252
|
+
- `npm run build-storybook` – build static Storybook
|
|
253
|
+
|
|
254
|
+
Prettier is integrated with ESLint (plugin:prettier/recommended). Formatting issues will surface as ESLint errors.
|
|
255
|
+
|
|
241
256
|
You can override the default styles by targeting the CSS classes:
|
|
242
257
|
|
|
243
258
|
- `.histogram-container` - Main container
|
|
@@ -259,35 +274,35 @@ A comprehensive production unit component that combines an image display, status
|
|
|
259
274
|
|
|
260
275
|
#### Props
|
|
261
276
|
|
|
262
|
-
| Prop | Type
|
|
263
|
-
| ---------------- |
|
|
264
|
-
| `onChangeInput` | `(value: number) => void`
|
|
265
|
-
| `onChangeSwitch` | `(checked: boolean) => void` | ❌
|
|
266
|
-
| `defaultValue` | `number`
|
|
267
|
-
| `defaultChecked` | `boolean`
|
|
268
|
-
| `unitName` | `string`
|
|
269
|
-
| `energyCost` | `number`
|
|
270
|
-
| `checkedImage` | `React.ReactNode`
|
|
271
|
-
| `uncheckedImage` | `React.ReactNode`
|
|
277
|
+
| Prop | Type | Required | Default | Description |
|
|
278
|
+
| ---------------- | ---------------------------- | -------- | ------------------- | --------------------------------------------------- |
|
|
279
|
+
| `onChangeInput` | `(value: number) => void` | ❌ | - | Callback triggered when input value changes |
|
|
280
|
+
| `onChangeSwitch` | `(checked: boolean) => void` | ❌ | - | Callback triggered when switch state changes |
|
|
281
|
+
| `defaultValue` | `number` | ❌ | - | Initial value for the input field |
|
|
282
|
+
| `defaultChecked` | `boolean` | ❌ | `false` | Initial state for the switch |
|
|
283
|
+
| `unitName` | `string` | ❌ | `"Production Unit"` | Display name for the production unit |
|
|
284
|
+
| `energyCost` | `number` | ❌ | `0` | Energy cost value displayed in the chip (MW) |
|
|
285
|
+
| `checkedImage` | `React.ReactNode` | ❌ | - | Custom image/component displayed when switch is ON |
|
|
286
|
+
| `uncheckedImage` | `React.ReactNode` | ❌ | - | Custom image/component displayed when switch is OFF |
|
|
272
287
|
|
|
273
288
|
#### Example Usage
|
|
274
289
|
|
|
275
290
|
```tsx
|
|
276
|
-
import React from
|
|
277
|
-
import { ProductionUnit } from
|
|
278
|
-
import
|
|
291
|
+
import React from 'react';
|
|
292
|
+
import { ProductionUnit } from 'rte-utils';
|
|
293
|
+
import 'rte-utils/dist/index.css';
|
|
279
294
|
|
|
280
295
|
function ProductionUnitExample() {
|
|
281
296
|
const handleInputChange = (value: number) => {
|
|
282
|
-
console.log(
|
|
297
|
+
console.log('Production value changed:', value);
|
|
283
298
|
};
|
|
284
299
|
|
|
285
300
|
const handleSwitchChange = (checked: boolean) => {
|
|
286
|
-
console.log(
|
|
301
|
+
console.log('Production unit is now:', checked ? 'ON' : 'OFF');
|
|
287
302
|
};
|
|
288
303
|
|
|
289
304
|
return (
|
|
290
|
-
<div style={{ display:
|
|
305
|
+
<div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
|
|
291
306
|
{/* Basic usage */}
|
|
292
307
|
<ProductionUnit
|
|
293
308
|
unitName="Solar Panel"
|
|
@@ -305,16 +320,10 @@ function ProductionUnitExample() {
|
|
|
305
320
|
defaultChecked={false}
|
|
306
321
|
defaultValue={75}
|
|
307
322
|
checkedImage={
|
|
308
|
-
<img
|
|
309
|
-
src="https://placehold.co/60x60/4CAF50/FFFFFF/png?text=ON"
|
|
310
|
-
alt="Wind Turbine On"
|
|
311
|
-
/>
|
|
323
|
+
<img src="https://placehold.co/60x60/4CAF50/FFFFFF/png?text=ON" alt="Wind Turbine On" />
|
|
312
324
|
}
|
|
313
325
|
uncheckedImage={
|
|
314
|
-
<img
|
|
315
|
-
src="https://placehold.co/60x60/F44336/FFFFFF/png?text=OFF"
|
|
316
|
-
alt="Wind Turbine Off"
|
|
317
|
-
/>
|
|
326
|
+
<img src="https://placehold.co/60x60/F44336/FFFFFF/png?text=OFF" alt="Wind Turbine Off" />
|
|
318
327
|
}
|
|
319
328
|
onChangeInput={handleInputChange}
|
|
320
329
|
onChangeSwitch={handleSwitchChange}
|
|
@@ -326,32 +335,36 @@ function ProductionUnitExample() {
|
|
|
326
335
|
energyCost={1000}
|
|
327
336
|
defaultChecked={true}
|
|
328
337
|
checkedImage={
|
|
329
|
-
<div
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
<div
|
|
339
|
+
style={{
|
|
340
|
+
width: 60,
|
|
341
|
+
height: 60,
|
|
342
|
+
borderRadius: '50%',
|
|
343
|
+
backgroundColor: '#4CAF50',
|
|
344
|
+
display: 'flex',
|
|
345
|
+
alignItems: 'center',
|
|
346
|
+
justifyContent: 'center',
|
|
347
|
+
color: 'white',
|
|
348
|
+
fontWeight: 'bold',
|
|
349
|
+
}}
|
|
350
|
+
>
|
|
340
351
|
⚡
|
|
341
352
|
</div>
|
|
342
353
|
}
|
|
343
354
|
uncheckedImage={
|
|
344
|
-
<div
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
+
<div
|
|
356
|
+
style={{
|
|
357
|
+
width: 60,
|
|
358
|
+
height: 60,
|
|
359
|
+
borderRadius: '50%',
|
|
360
|
+
backgroundColor: '#F44336',
|
|
361
|
+
display: 'flex',
|
|
362
|
+
alignItems: 'center',
|
|
363
|
+
justifyContent: 'center',
|
|
364
|
+
color: 'white',
|
|
365
|
+
fontWeight: 'bold',
|
|
366
|
+
}}
|
|
367
|
+
>
|
|
355
368
|
⚠️
|
|
356
369
|
</div>
|
|
357
370
|
}
|
|
@@ -393,13 +406,13 @@ A customizable chip component for displaying labels, tags, or status indicators.
|
|
|
393
406
|
#### Example Usage
|
|
394
407
|
|
|
395
408
|
```tsx
|
|
396
|
-
import React from
|
|
397
|
-
import { Chip } from
|
|
398
|
-
import
|
|
409
|
+
import React from 'react';
|
|
410
|
+
import { Chip } from 'rte-utils';
|
|
411
|
+
import 'rte-utils/dist/index.css';
|
|
399
412
|
|
|
400
413
|
function ChipExample() {
|
|
401
414
|
return (
|
|
402
|
-
<div style={{ display:
|
|
415
|
+
<div style={{ display: 'flex', gap: '0.5rem' }}>
|
|
403
416
|
{/* Default chip */}
|
|
404
417
|
<Chip label="Default" />
|
|
405
418
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { Avatar } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Avatar } from './Avatar';
|
|
3
3
|
declare const meta: Meta<typeof Avatar>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Chip.css';
|
|
3
3
|
interface ChipProps {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
bgColor?: string;
|
|
6
|
-
width?:
|
|
6
|
+
width?: 'fit-content' | 'full-width';
|
|
7
7
|
}
|
|
8
8
|
export declare const Chip: React.FC<ChipProps>;
|
|
9
9
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { Chip } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Chip } from './Chip';
|
|
3
3
|
declare const meta: Meta<typeof Chip>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { Histogram } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Histogram } from './Histogram';
|
|
3
3
|
declare const meta: Meta<typeof Histogram>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import "./Histogramme.css";
|
|
3
|
+
interface HistogramProps {
|
|
4
|
+
/** Maximum value configuration with value and color */
|
|
5
|
+
max: {
|
|
6
|
+
value: number;
|
|
7
|
+
color: string;
|
|
8
|
+
};
|
|
9
|
+
/** Relative/current value configuration with value and color */
|
|
10
|
+
relative: {
|
|
11
|
+
value: number;
|
|
12
|
+
color: string;
|
|
13
|
+
};
|
|
14
|
+
/** Height of the histogram bar in pixels */
|
|
15
|
+
barHeight?: number;
|
|
16
|
+
/** Width of the histogram bar in pixels */
|
|
17
|
+
barWidth?: number;
|
|
18
|
+
/** Child components (typically text content) */
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
}
|
|
21
|
+
export declare const Histogram: React.FC<HistogramProps>;
|
|
22
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { InputNumber } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { InputNumber } from './InputNumber';
|
|
3
3
|
declare const meta: Meta<typeof InputNumber>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { ProductionUnit } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ProductionUnit } from './ProductionUnit';
|
|
3
3
|
declare const meta: Meta<typeof ProductionUnit>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { ProductionUnitContainer } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ProductionUnitContainer } from './ProductionUnitContainer';
|
|
3
3
|
declare const meta: Meta<typeof ProductionUnitContainer>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { Switch } from
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Switch } from './Switch';
|
|
3
3
|
declare const meta: Meta<typeof Switch>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof meta>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Timer.css';
|
|
3
|
+
export interface TimerProps {
|
|
4
|
+
phases: {
|
|
5
|
+
duration: number;
|
|
6
|
+
title?: string;
|
|
7
|
+
}[];
|
|
8
|
+
onComplete?: () => void;
|
|
9
|
+
onPhaseComplete?: (phaseIndex: number, phaseDuration: number) => void;
|
|
10
|
+
onTick?: (currentTime: number, phaseIndex: number) => void;
|
|
11
|
+
onStart?: () => void;
|
|
12
|
+
onPause?: () => void;
|
|
13
|
+
onFreeze?: (frozen: boolean) => void;
|
|
14
|
+
onAnonymiseToggle?: (anonymised: boolean) => void;
|
|
15
|
+
onStop?: () => void;
|
|
16
|
+
onReset?: () => void;
|
|
17
|
+
onPrevious?: () => void;
|
|
18
|
+
onNext?: () => void;
|
|
19
|
+
onPhaseClick?: (phaseIndex: number) => void;
|
|
20
|
+
autoStart?: boolean;
|
|
21
|
+
className?: string;
|
|
22
|
+
gameActions?: {
|
|
23
|
+
[phaseIndex: number]: string;
|
|
24
|
+
};
|
|
25
|
+
user?: 'actor' | 'admin';
|
|
26
|
+
}
|
|
27
|
+
export interface TimerRef {
|
|
28
|
+
start: () => void;
|
|
29
|
+
pause: () => void;
|
|
30
|
+
freeze: (force?: boolean) => void;
|
|
31
|
+
toggleAnonymise: (force?: boolean) => void;
|
|
32
|
+
stop: () => void;
|
|
33
|
+
reset: () => void;
|
|
34
|
+
setPhases: (phases: {
|
|
35
|
+
duration: number;
|
|
36
|
+
title?: string;
|
|
37
|
+
}[]) => void;
|
|
38
|
+
getCurrentTime: () => number;
|
|
39
|
+
getCurrentPhase: () => number;
|
|
40
|
+
isRunning: () => boolean;
|
|
41
|
+
isPaused: () => boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare const Timer: React.ForwardRefExoticComponent<TimerProps & React.RefAttributes<TimerRef>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Timer } from './Timer';
|
|
3
|
+
declare const meta: Meta<typeof Timer>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const GameTimer: Story;
|
|
8
|
+
export declare const SinglePhase: Story;
|
|
9
|
+
export declare const MinimalTimer: Story;
|
|
10
|
+
export declare const ProgressOnly: Story;
|
|
11
|
+
export declare const WithPhaseTitles: Story;
|
|
12
|
+
export declare const WithCallbacks: Story;
|
|
13
|
+
export declare const ControlledTimer: Story;
|
|
14
|
+
export declare const FreezeDemo: Story;
|
|
15
|
+
export declare const AdminUser: Story;
|
|
16
|
+
export declare const ActorUser: Story;
|
|
17
|
+
export declare const UserComparison: Story;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export { ProductionUnit } from
|
|
2
|
-
export { ProductionUnitContainer } from
|
|
3
|
-
export { Histogram } from
|
|
4
|
-
export { Chip } from
|
|
5
|
-
export { Switch } from
|
|
6
|
-
export { InputNumber } from
|
|
7
|
-
export { Avatar } from
|
|
8
|
-
export { MwhCost } from
|
|
1
|
+
export { ProductionUnit } from './ProductionUnit';
|
|
2
|
+
export { ProductionUnitContainer } from './ProductionUnitContainer';
|
|
3
|
+
export { Histogram } from './Histogram';
|
|
4
|
+
export { Chip } from './Chip';
|
|
5
|
+
export { Switch } from './Switch';
|
|
6
|
+
export { InputNumber } from './InputNumber';
|
|
7
|
+
export { Avatar } from './Avatar';
|
|
8
|
+
export { MwhCost } from './MwhCost';
|
|
9
|
+
export { Timer } from './Timer';
|
|
10
|
+
export type { TimerProps, TimerRef } from './Timer';
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.input-container,.input-field{position:relative;width:100%}.input-element{background-color:#fff;border:2px solid #e0e0e0;border-radius:4px;box-sizing:border-box;font-size:16px;outline:none;padding:8px 0 8px 12px;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.input-element:focus{border-color:#009cdf;box-shadow:0 0 0 2px rgba(0,156,223,.1)}.input-label{background-color:#fff;color:#999;font-size:16px;left:12px;padding:0 4px;pointer-events:none;position:absolute;top:50%;transform:translateY(-50%);transition:all .2s ease;white-space:nowrap}.input-required{color:#e74c3c;margin-left:2px}.input-container--floating .input-label,.input-container--focused .input-label{font-size:12px;font-weight:500;top:0;transform:translateY(-50%)}.input-container--focused .input-element{border-color:#009cdf;box-shadow:0 0 0 2px rgba(0,156,223,.1)}.input-container--focused .input-label{color:#009cdf}.input-container--error .input-element{border-color:#e74c3c}.input-container--error .input-element:focus{border-color:#e74c3c;box-shadow:0 0 0 2px rgba(231,76,60,.1)}.input-container--error .input-label,.input-error{color:#e74c3c}.input-error{font-size:12px;margin-top:4px;padding-left:12px}.input-container--disabled .input-element{background-color:#f5f5f5;border-color:#d0d0d0;color:#999;cursor:not-allowed}.input-container--disabled .input-label{color:#999}.input-element:not(:disabled):hover{border-color:#009cdf}.input-container--error .input-element:not(:disabled):hover{border-color:#e74c3c}.input-element:-webkit-autofill{-webkit-text-fill-color:inherit!important}.input-element:-webkit-autofill,.input-element:-webkit-autofill:focus{-webkit-box-shadow:inset 0 0 0 30px #fff!important}.input-container--small .input-element{font-size:14px;padding:12px 8px 6px}.input-container--small .input-label{font-size:14px;left:8px}.input-container--small.input-container--floating .input-label,.input-container--small.input-container--focused .input-label{font-size:10px}.input-container--large .input-element{font-size:18px;padding:20px 16px 10px}.input-container--large .input-label{font-size:18px;left:16px}.input-container--large.input-container--floating .input-label,.input-container--large.input-container--focused .input-label{font-size:14px}.input-constraints{align-items:center;display:flex;gap:8px;justify-content:space-between}.input-max,.input-min{color:#999;font-size:12px;text-align:center}.input-container--focused .input-max,.input-container--focused .input-min{color:#009cdf;font-weight:500}.input-element[type=number]::-webkit-inner-spin-button,.input-element[type=number]::-webkit-outer-spin-button{-webkit-appearance:auto;cursor:pointer;margin:0;opacity:1}.input-element[type=number]{-moz-appearance:textfield}.input-element[type=number]:hover::-webkit-inner-spin-button,.input-element[type=number]:hover::-webkit-outer-spin-button{opacity:1}.switch-container{align-items:center;display:flex;gap:8px}.switch-wrapper{align-items:center;display:flex;flex-direction:column;gap:4px}.switch-icon{height:16px;width:16px}.switch-icon,.switch-label{align-items:center;display:flex;justify-content:center}.switch-label{color:#666;font-size:12px;font-weight:500;min-height:16px;padding:0 2px}.switch-power-icon{height:100%;object-fit:contain;width:100%}.switch{background:none;border:none;cursor:pointer;outline:none;padding:0;transition:all .2s ease}.switch:focus-visible{outline:2px solid #009cdf;outline-offset:2px}.switch--disabled{cursor:not-allowed;opacity:.5}.switch-track{background-color:#999fa1;border-radius:60px;display:block;position:relative;transition:background-color .2s ease}.switch--checked .switch-track{background-color:#82d4f6}.switch-wrapper--checked .switch-label{color:#82d4f6}.switch-thumb{align-items:center;background-color:#fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2);display:flex;justify-content:center;left:0;position:absolute;top:-3px;transition:transform .2s ease}.switch-thumb-icon{height:100%;object-fit:contain;width:100%}.switch-track{height:10px;width:32px}.switch-thumb{height:16px;width:16px}.switch--checked .switch-thumb{transform:translateX(16px)}.switch:not(.switch--disabled):hover .switch-track{filter:brightness(1.1)}.switch:not(.switch--disabled):active .switch-thumb{transform:scale(1.1)}.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(16px) scale(1.1)}.switch--small.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(12px) scale(1.1)}.switch--large.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(20px) scale(1.1)}.production-unit-container{align-items:center;display:flex;height:64px;justify-content:space-between;padding-right:24px}.production-unit-content{align-items:center;display:flex;gap:16px}.production-unit-chip{display:flex;flex-direction:column;flex-shrink:0}.production-unit-chip-name{word-wrap:break-word;color:#11161a;font-size:16px;font-weight:600;line-height:24px}.production-unit-switch-container{width:156px}.chip-container{align-items:center;background-color:var(--chip-bg-color,#e0e0e0);border-radius:60px;color:var(--chip-text-color,#000);display:inline-flex;min-width:84px;padding:4px 8px}.chip-container--fit-content{width:fit-content}.chip-container--full-width{width:100%}.chip-content{align-items:center;display:flex;flex-grow:1;gap:.5rem;justify-content:center}.chip-label{font-size:14px;font-weight:600;margin:0}.production-unit-container-box{border-radius:64px;box-shadow:0 2px 16px 0 rgba(0,0,0,.16);box-sizing:border-box;width:100%}@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap");*{font-family:Open Sans,sans-serif}.histogram-container{height:auto;max-width:54px;position:relative}.histogram-container--horizontal{max-width:none;width:auto}.histogram-content{align-items:center;display:flex;flex-direction:column;gap:8px;width:100%}.histogram-content--horizontal{align-items:center;flex-direction:row;height:100%}.histogram-bar{position:relative}.histogram-svg{display:block}.histogram-text-container{align-items:center;display:flex;flex-direction:column;gap:0;justify-content:center;width:100%}.histogram-text-container--horizontal{align-items:flex-start;margin-left:8px}.histogram-value-container{text-align:center;width:40px}.histogram-value{font-size:16px;line-height:14px}.histogram-unit,.histogram-value{color:#000;display:block;font-weight:600;margin:0}.histogram-unit{font-size:12px}.histogram-label{color:#6f6f6f;font-size:12px;font-style:normal;font-weight:400;line-height:18px;margin:0;text-align:left;white-space:nowrap}.avatar-container{align-items:center;border:1px solid #f5f3ed;border-radius:50%;color:#333;display:inline-flex;font-size:20px;font-weight:500;height:64px;justify-content:center;overflow:hidden;position:relative;user-select:none;width:64px}.avatar-container--clickable{cursor:pointer;transition:transform .2s ease,box-shadow .2s ease}.avatar-container--clickable:hover{box-shadow:0 2px 8px rgba(0,0,0,.15);transform:scale(1.05)}.avatar-container--clickable:active{transform:scale(.95)}.avatar-content{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.avatar-content img{height:100%;object-fit:cover;width:100%}.avatar-content{line-height:1;text-transform:uppercase}.cost-text-container{align-items:baseline;display:flex;gap:3px}.cost-number{font-size:16px;font-weight:semibold}.cost-unit{font-size:16px;line-height:24px}.cost-unit-per{font-size:12px;font-weight:400;letter-spacing:0;line-height:18px;text-transform:uppercase}
|
|
1
|
+
.input-container,.input-field{position:relative;width:100%}.input-element{background-color:#fff;border:2px solid #e0e0e0;border-radius:4px;box-sizing:border-box;font-size:16px;outline:none;padding:8px 0 8px 12px;transition:border-color .2s ease,box-shadow .2s ease;width:100%}.input-element:focus{border-color:#009cdf;box-shadow:0 0 0 2px rgba(0,156,223,.1)}.input-label{background-color:#fff;color:#999;font-size:16px;left:12px;padding:0 4px;pointer-events:none;position:absolute;top:50%;transform:translateY(-50%);transition:all .2s ease;white-space:nowrap}.input-required{color:#e74c3c;margin-left:2px}.input-container--floating .input-label,.input-container--focused .input-label{font-size:12px;font-weight:500;top:0;transform:translateY(-50%)}.input-container--focused .input-element{border-color:#009cdf;box-shadow:0 0 0 2px rgba(0,156,223,.1)}.input-container--focused .input-label{color:#009cdf}.input-container--error .input-element{border-color:#e74c3c}.input-container--error .input-element:focus{border-color:#e74c3c;box-shadow:0 0 0 2px rgba(231,76,60,.1)}.input-container--error .input-label,.input-error{color:#e74c3c}.input-error{font-size:12px;margin-top:4px;padding-left:12px}.input-container--disabled .input-element{background-color:#f5f5f5;border-color:#d0d0d0;color:#999;cursor:not-allowed}.input-container--disabled .input-label{color:#999}.input-element:not(:disabled):hover{border-color:#009cdf}.input-container--error .input-element:not(:disabled):hover{border-color:#e74c3c}.input-element:-webkit-autofill{-webkit-text-fill-color:inherit!important}.input-element:-webkit-autofill,.input-element:-webkit-autofill:focus{-webkit-box-shadow:inset 0 0 0 30px #fff!important}.input-container--small .input-element{font-size:14px;padding:12px 8px 6px}.input-container--small .input-label{font-size:14px;left:8px}.input-container--small.input-container--floating .input-label,.input-container--small.input-container--focused .input-label{font-size:10px}.input-container--large .input-element{font-size:18px;padding:20px 16px 10px}.input-container--large .input-label{font-size:18px;left:16px}.input-container--large.input-container--floating .input-label,.input-container--large.input-container--focused .input-label{font-size:14px}.input-constraints{align-items:center;display:flex;gap:8px;justify-content:space-between}.input-max,.input-min{color:#999;font-size:12px;text-align:center}.input-container--focused .input-max,.input-container--focused .input-min{color:#009cdf;font-weight:500}.input-element[type=number]::-webkit-inner-spin-button,.input-element[type=number]::-webkit-outer-spin-button{-webkit-appearance:auto;cursor:pointer;margin:0;opacity:1}.input-element[type=number]{-moz-appearance:textfield}.input-element[type=number]:hover::-webkit-inner-spin-button,.input-element[type=number]:hover::-webkit-outer-spin-button{opacity:1}.switch-container{align-items:center;display:flex;gap:8px}.switch-wrapper{align-items:center;display:flex;flex-direction:column;gap:4px}.switch-icon{height:16px;width:16px}.switch-icon,.switch-label{align-items:center;display:flex;justify-content:center}.switch-label{color:#666;font-size:12px;font-weight:500;min-height:16px;padding:0 2px}.switch-power-icon{height:100%;object-fit:contain;width:100%}.switch{background:none;border:none;cursor:pointer;outline:none;padding:0;transition:all .2s ease}.switch:focus-visible{outline:2px solid #009cdf;outline-offset:2px}.switch--disabled{cursor:not-allowed;opacity:.5}.switch-track{background-color:#999fa1;border-radius:60px;display:block;position:relative;transition:background-color .2s ease}.switch--checked .switch-track{background-color:#82d4f6}.switch-wrapper--checked .switch-label{color:#82d4f6}.switch-thumb{align-items:center;background-color:#fff;border-radius:50%;box-shadow:0 2px 4px rgba(0,0,0,.2);display:flex;justify-content:center;left:0;position:absolute;top:-3px;transition:transform .2s ease}.switch-thumb-icon{height:100%;object-fit:contain;width:100%}.switch-track{height:10px;width:32px}.switch-thumb{height:16px;width:16px}.switch--checked .switch-thumb{transform:translateX(16px)}.switch:not(.switch--disabled):hover .switch-track{filter:brightness(1.1)}.switch:not(.switch--disabled):active .switch-thumb{transform:scale(1.1)}.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(16px) scale(1.1)}.switch--small.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(12px) scale(1.1)}.switch--large.switch--checked:not(.switch--disabled):active .switch-thumb{transform:translateX(20px) scale(1.1)}.production-unit-container{align-items:center;display:flex;height:64px;justify-content:space-between;padding-right:24px}.production-unit-content{align-items:center;display:flex;gap:16px}.production-unit-chip{display:flex;flex-direction:column;flex-shrink:0}.production-unit-chip-name{word-wrap:break-word;color:#11161a;font-size:16px;font-weight:600;line-height:24px}.production-unit-switch-container{width:156px}.chip-container{align-items:center;background-color:var(--chip-bg-color,#e0e0e0);border-radius:60px;color:var(--chip-text-color,#000);display:inline-flex;min-width:84px;padding:4px 8px}.chip-container--fit-content{width:fit-content}.chip-container--full-width{width:100%}.chip-content{align-items:center;display:flex;flex-grow:1;gap:.5rem;justify-content:center}.chip-label{font-size:14px;font-weight:600;margin:0}.production-unit-container-box{border-radius:64px;box-shadow:0 2px 16px 0 rgba(0,0,0,.16);box-sizing:border-box;width:100%}@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap");*{font-family:Open Sans,sans-serif}.histogram-container{height:auto;max-width:54px;position:relative}.histogram-container--horizontal{max-width:none;width:auto}.histogram-content{align-items:center;display:flex;flex-direction:column;gap:8px;width:100%}.histogram-content--horizontal{align-items:center;flex-direction:row;height:100%}.histogram-bar{position:relative}.histogram-svg{display:block}.histogram-text-container{align-items:center;display:flex;flex-direction:column;gap:0;justify-content:center;width:100%}.histogram-text-container--horizontal{align-items:flex-start;margin-left:8px}.histogram-value-container{text-align:center;width:40px}.histogram-value{font-size:16px;line-height:14px}.histogram-unit,.histogram-value{color:#000;display:block;font-weight:600;margin:0}.histogram-unit{font-size:12px}.histogram-label{color:#6f6f6f;font-size:12px;font-style:normal;font-weight:400;line-height:18px;margin:0;text-align:left;white-space:nowrap}.avatar-container{align-items:center;border:1px solid #f5f3ed;border-radius:50%;color:#333;display:inline-flex;font-size:20px;font-weight:500;height:64px;justify-content:center;overflow:hidden;position:relative;user-select:none;width:64px}.avatar-container--clickable{cursor:pointer;transition:transform .2s ease,box-shadow .2s ease}.avatar-container--clickable:hover{box-shadow:0 2px 8px rgba(0,0,0,.15);transform:scale(1.05)}.avatar-container--clickable:active{transform:scale(.95)}.avatar-content{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.avatar-content img{height:100%;object-fit:cover;width:100%}.avatar-content{line-height:1;text-transform:uppercase}.cost-text-container{align-items:baseline;display:flex;gap:3px}.cost-number{font-size:16px;font-weight:semibold}.cost-unit{font-size:16px;line-height:24px}.cost-unit-per{font-size:12px;font-weight:400;letter-spacing:0;line-height:18px;text-transform:uppercase}.timer-header-control{border:1px solid red;box-sizing:border-box;display:flex;font-family:Open Sans,sans-serif;width:100%}.timer-section{background-color:#fff;border-bottom-left-radius:16px;border-top-left-radius:16px;display:flex;flex-shrink:0;padding:10px 0 10px 16px}.timer-content{align-items:center;display:flex;gap:8px;padding-right:8px}.timer-display-area{display:flex;flex-direction:column;flex-shrink:0;gap:10px}.timer-header{align-items:baseline;color:#11161a;display:flex;justify-content:space-between;width:124px}.timer-title{flex-shrink:0;font-size:12px;font-weight:700;line-height:12px;min-width:64px;text-align:left;text-transform:uppercase}.timer-time,.timer-title{font-family:Open Sans,sans-serif}.timer-time{font-size:20px;font-weight:600;line-height:14px;text-align:right;white-space:nowrap;width:61px}.timer-progress-bar{background:#000;border-radius:4px;height:8px;overflow:hidden;position:relative;width:124px}.timer-progress-fill{background:#009cdf;border-radius:4px;height:100%;transition:width .3s ease}.step-indicators{align-items:center;display:flex;gap:4px}.step-indicator{align-items:center;border-radius:50%;color:#fff;display:flex;flex-shrink:0;font-family:Open Sans,sans-serif;font-size:12px;font-weight:600;height:16px;justify-content:center;line-height:18px;width:16px}.step-indicator--active{background-color:#009cdf}.step-indicator--active.step-indicator--actor{height:40px;margin-right:4px;width:40px}.step-indicator--active.step-indicator--admin{height:16px;width:16px}.step-indicator--completed{background-color:#005896}.step-indicator--upcoming{background-color:#b7bec2}.step-expand{align-items:center;background-color:#292e33;border-radius:50%;color:#fff;display:flex;justify-content:center;margin-left:4px;transform:rotate(90deg)}.timer-controls-section{align-items:center;align-self:stretch;background-color:#fff;display:flex;flex-shrink:0;gap:10px;padding:10px 16px 10px 10px}.control-button{align-items:center;background:none;background:#d9d9d9;border:none;cursor:pointer;display:flex;height:24px;justify-content:center;padding:0;position:relative;width:24px}.control-button,.control-button:before{border-radius:50%;height:32px;width:32px}.control-button:before{background:radial-gradient(circle,rgba(0,0,0,.1) 0,transparent 70%);content:"";left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:-1}.control-button:hover:before{background:radial-gradient(circle,rgba(0,0,0,.15) 0,transparent 70%)}.control-button svg{color:#000;height:16px;width:16px}.timer--running .step-indicator--active{animation:pulse 1s ease-in-out infinite alternate}.timer--frozen .timer-progress-fill{background:#7aa6b9}.control-button--anonymise-active{background-color:#444;color:#fff}.control-button--freeze-active{background:#7aa6b9}.control-button--freeze-active svg path{fill:#000}@keyframes pulse{0%{background-color:#009cdf}to{background-color:#0081b8}}.step-indicator--placeholder{background-color:#e9ecef;color:#6c757d;position:relative}.step-indicator--placeholder:after{content:attr(data-step);font-size:10px;font-weight:700;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%)}.step-expand.step-expand--end{background-color:#1a7f37;transform:none}.timer-header--block{display:flex;flex-direction:column;gap:10px;margin-right:10px}@media (max-width:480px){.timer-header-control{flex-direction:column}.timer-section{border-radius:16px 16px 0 0}.timer-controls-section{border-radius:0 0 16px 16px;justify-content:center}}.step-indicator--clickable{cursor:pointer;position:relative;transition:background-color .2s ease,box-shadow .2s ease,transform .1s ease}.step-indicator--clickable:focus-visible{box-shadow:0 0 0 2px #11161a;outline:2px solid #fff;outline-offset:2px}.step-indicator--clickable:hover{filter:brightness(1.1)}.step-indicator--clickable:active{transform:scale(.9)}.step-indicator--selected{box-shadow:0 0 0 2px #fff,0 0 0 4px #ffb100}
|