@umituz/web-design-system 6.15.0 → 6.16.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.
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/__tests__/condition-pips.test.tsx +31 -0
- package/src/__tests__/theme-provider.test.tsx +12 -0
- package/src/domain/types/theme.types.ts +1 -0
- package/src/index.ts +2 -0
- package/src/infrastructure/themes/apply-theme.ts +18 -6
- package/src/infrastructure/themes/field.theme.ts +230 -0
- package/src/infrastructure/themes/index.ts +1 -0
- package/src/infrastructure/themes/registry.ts +2 -0
- package/src/presentation/molecules/ConditionPips.tsx +37 -0
- package/src/presentation/molecules/index.ts +3 -0
- package/src/styles/console.css +616 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/web-design-system",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.16.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Web Design System - Tailwind v4 authored, precompiled CSS shipped. Atomic Design components (Atoms, Molecules, Organisms, Templates) for React applications.",
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import { ConditionPips } from '../presentation/molecules/ConditionPips';
|
|
4
|
+
|
|
5
|
+
describe('ConditionPips', () => {
|
|
6
|
+
it('renders score pips with default max of 5', () => {
|
|
7
|
+
const { container } = render(<ConditionPips score={3} />);
|
|
8
|
+
const root = container.querySelector('.cond-pips');
|
|
9
|
+
expect(root).toBeDefined();
|
|
10
|
+
expect(root?.getAttribute('aria-label')).toBe('3/5');
|
|
11
|
+
|
|
12
|
+
const pips = container.querySelectorAll('.pip');
|
|
13
|
+
expect(pips.length).toBe(5);
|
|
14
|
+
|
|
15
|
+
const onPips = container.querySelectorAll('.pip.on');
|
|
16
|
+
expect(onPips.length).toBe(3);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('handles custom max and zero or null scores', () => {
|
|
20
|
+
const { container: c1 } = render(<ConditionPips score={null} max={4} />);
|
|
21
|
+
const root1 = c1.querySelector('.cond-pips');
|
|
22
|
+
expect(root1?.getAttribute('aria-label')).toBe('0/4');
|
|
23
|
+
expect(c1.querySelectorAll('.pip').length).toBe(4);
|
|
24
|
+
expect(c1.querySelectorAll('.pip.on').length).toBe(0);
|
|
25
|
+
|
|
26
|
+
const { container: c2 } = render(<ConditionPips score={7} max={5} ariaLabel="Excellent (5/5)" />);
|
|
27
|
+
const root2 = c2.querySelector('.cond-pips');
|
|
28
|
+
expect(root2?.getAttribute('aria-label')).toBe('Excellent (5/5)');
|
|
29
|
+
expect(c2.querySelectorAll('.pip.on').length).toBe(5);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
oceanTheme,
|
|
16
16
|
defaultTheme,
|
|
17
17
|
forestTheme,
|
|
18
|
+
fieldTheme,
|
|
18
19
|
} from '../infrastructure/themes';
|
|
19
20
|
import type { ThemeConfig } from '../domain/types';
|
|
20
21
|
|
|
@@ -32,6 +33,7 @@ describe('Theme System and Provider', () => {
|
|
|
32
33
|
expect(getTheme('editorial').name).toBe('editorial');
|
|
33
34
|
expect(getTheme('ocean').name).toBe('ocean');
|
|
34
35
|
expect(getTheme('forest').name).toBe('forest');
|
|
36
|
+
expect(getTheme('field').name).toBe('field');
|
|
35
37
|
expect(getTheme('default').name).toBe('default');
|
|
36
38
|
expect(getTheme('non-existent').name).toBe('default');
|
|
37
39
|
});
|
|
@@ -171,4 +173,14 @@ describe('Theme System and Provider', () => {
|
|
|
171
173
|
expect(screen.getByTestId('theme-mode').textContent).toBe('dark');
|
|
172
174
|
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
|
173
175
|
});
|
|
176
|
+
|
|
177
|
+
it('generates field theme CSS custom variables and dark mode overrides', () => {
|
|
178
|
+
const css = themeToCssVariables(fieldTheme);
|
|
179
|
+
expect(css).toContain('--paper: #f4f3ee;');
|
|
180
|
+
expect(css).toContain('--primary-500: #357344;');
|
|
181
|
+
expect(css).toContain('--font-display: \'Fraunces\', Georgia, serif;');
|
|
182
|
+
expect(css).toContain('.dark, [data-theme="dark"]');
|
|
183
|
+
expect(css).toContain('--paper: #10140f;');
|
|
184
|
+
expect(css).toContain('--primary-500: #6aa878;');
|
|
185
|
+
});
|
|
174
186
|
});
|
package/src/index.ts
CHANGED
|
@@ -151,4 +151,6 @@ export { EntityRow } from './presentation/molecules/EntityRow';
|
|
|
151
151
|
export type { EntityRowProps } from './presentation/molecules/EntityRow';
|
|
152
152
|
export { PlaceholderPanel } from './presentation/molecules/PlaceholderPanel';
|
|
153
153
|
export type { PlaceholderPanelProps } from './presentation/molecules/PlaceholderPanel';
|
|
154
|
+
export { ConditionPips } from './presentation/molecules/ConditionPips';
|
|
155
|
+
export type { ConditionPipsProps } from './presentation/molecules/ConditionPips';
|
|
154
156
|
|
|
@@ -108,12 +108,24 @@ export function themeToCssVariables(theme: ThemeConfig): string {
|
|
|
108
108
|
|
|
109
109
|
let css = `:root {\n ${rootLines.join('\n ')}\n}\n`;
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
111
|
+
const hasDarkColors = Boolean(theme.darkColors && Object.keys(theme.darkColors).length > 0);
|
|
112
|
+
const hasDarkVars = Boolean(theme.darkCustomVars && Object.keys(theme.darkCustomVars).length > 0);
|
|
113
|
+
|
|
114
|
+
if (hasDarkColors || hasDarkVars) {
|
|
115
|
+
const darkLines: string[] = [];
|
|
116
|
+
if (hasDarkColors) {
|
|
117
|
+
const darkMerged: ThemeColors = {
|
|
118
|
+
...theme.colors,
|
|
119
|
+
...theme.darkColors,
|
|
120
|
+
};
|
|
121
|
+
darkLines.push(colorPropsToCss(darkMerged));
|
|
122
|
+
}
|
|
123
|
+
if (hasDarkVars && theme.darkCustomVars) {
|
|
124
|
+
for (const [k, v] of Object.entries(theme.darkCustomVars)) {
|
|
125
|
+
darkLines.push(`--${k}: ${v};`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
css += `\n.dark, [data-theme="dark"] {\n ${darkLines.join('\n ')}\n}\n`;
|
|
117
129
|
}
|
|
118
130
|
|
|
119
131
|
return css;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { ThemeConfig } from '../../domain/types';
|
|
2
|
+
|
|
3
|
+
export const fieldTheme: ThemeConfig = {
|
|
4
|
+
name: 'field',
|
|
5
|
+
mode: 'light',
|
|
6
|
+
colors: {
|
|
7
|
+
background: '#f4f3ee',
|
|
8
|
+
foreground: '#1a231c',
|
|
9
|
+
card: '#ffffff',
|
|
10
|
+
cardForeground: '#212c23',
|
|
11
|
+
popover: '#ffffff',
|
|
12
|
+
popoverForeground: '#212c23',
|
|
13
|
+
primary: '#357344',
|
|
14
|
+
primaryForeground: '#ffffff',
|
|
15
|
+
primarySoft: '#dcead9',
|
|
16
|
+
secondary: '#f1f4ef',
|
|
17
|
+
secondaryForeground: '#2b382d',
|
|
18
|
+
muted: '#edebe3',
|
|
19
|
+
mutedForeground: '#5a655b',
|
|
20
|
+
accent: '#f5e8d3',
|
|
21
|
+
accentForeground: '#c9862f',
|
|
22
|
+
border: '#e2dfd3',
|
|
23
|
+
input: '#cfcaba',
|
|
24
|
+
destructive: '#a53f2a',
|
|
25
|
+
destructiveForeground: '#ffffff',
|
|
26
|
+
ring: 'rgba(53, 115, 68, 0.45)',
|
|
27
|
+
success: '#2f6b40',
|
|
28
|
+
successForeground: '#ffffff',
|
|
29
|
+
warning: '#96690f',
|
|
30
|
+
warningForeground: '#ffffff',
|
|
31
|
+
info: '#3e5f80',
|
|
32
|
+
infoForeground: '#ffffff',
|
|
33
|
+
},
|
|
34
|
+
darkColors: {
|
|
35
|
+
background: '#10140f',
|
|
36
|
+
foreground: '#edf0e7',
|
|
37
|
+
card: '#191f18',
|
|
38
|
+
cardForeground: '#dce1d2',
|
|
39
|
+
popover: '#191f18',
|
|
40
|
+
popoverForeground: '#dce1d2',
|
|
41
|
+
primary: '#6aa878',
|
|
42
|
+
primaryForeground: '#10140f',
|
|
43
|
+
secondary: '#1f261e',
|
|
44
|
+
secondaryForeground: '#c3c9b6',
|
|
45
|
+
muted: '#151a14',
|
|
46
|
+
mutedForeground: '#828b79',
|
|
47
|
+
accent: 'rgba(217, 165, 79, 0.15)',
|
|
48
|
+
accentForeground: '#cf9a48',
|
|
49
|
+
border: '#262e24',
|
|
50
|
+
input: '#333d30',
|
|
51
|
+
destructive: '#d07a63',
|
|
52
|
+
destructiveForeground: '#10140f',
|
|
53
|
+
ring: 'rgba(122, 183, 136, 0.45)',
|
|
54
|
+
success: '#7cb989',
|
|
55
|
+
successForeground: '#10140f',
|
|
56
|
+
warning: '#d3a04e',
|
|
57
|
+
warningForeground: '#10140f',
|
|
58
|
+
info: '#8fb0d4',
|
|
59
|
+
infoForeground: '#10140f',
|
|
60
|
+
},
|
|
61
|
+
typography: {
|
|
62
|
+
fontSans: "'Archivo', 'Segoe UI', system-ui, sans-serif",
|
|
63
|
+
fontDisplay: "'Fraunces', Georgia, serif",
|
|
64
|
+
fontMono: "'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace",
|
|
65
|
+
},
|
|
66
|
+
radii: {
|
|
67
|
+
xs: '2px',
|
|
68
|
+
sm: '4px',
|
|
69
|
+
md: '6px',
|
|
70
|
+
lg: '9px',
|
|
71
|
+
xl: '999px',
|
|
72
|
+
},
|
|
73
|
+
customVars: {
|
|
74
|
+
paper: '#f4f3ee',
|
|
75
|
+
'paper-deep': '#edebe3',
|
|
76
|
+
surface: '#ffffff',
|
|
77
|
+
'surface-sunken': '#faf9f5',
|
|
78
|
+
'surface-tint': '#f1f4ef',
|
|
79
|
+
'ink-900': '#1a231c',
|
|
80
|
+
'ink-800': '#212c23',
|
|
81
|
+
'ink-700': '#2b382d',
|
|
82
|
+
'ink-600': '#414d42',
|
|
83
|
+
'ink-500': '#5a655b',
|
|
84
|
+
'ink-400': '#79827a',
|
|
85
|
+
'ink-300': '#9aa29a',
|
|
86
|
+
'ink-200': '#c3c8bd',
|
|
87
|
+
'ink-100': '#dfe2d8',
|
|
88
|
+
'chrome-900': '#131f17',
|
|
89
|
+
'chrome-800': '#16251b',
|
|
90
|
+
'chrome-700': '#1c2e21',
|
|
91
|
+
'chrome-600': '#233a2a',
|
|
92
|
+
'chrome-500': '#2c4734',
|
|
93
|
+
'chrome-line': '#2a3f30',
|
|
94
|
+
'chrome-text': '#c5cfc4',
|
|
95
|
+
'chrome-text-dim': '#7f9484',
|
|
96
|
+
'chrome-active': '#d8e6d4',
|
|
97
|
+
'primary-700': '#24502f',
|
|
98
|
+
'primary-600': '#2c6139',
|
|
99
|
+
'primary-500': '#357344',
|
|
100
|
+
'primary-100': '#dcead9',
|
|
101
|
+
'primary-050': '#edf4ea',
|
|
102
|
+
'accent-600': '#b06e22',
|
|
103
|
+
'accent-500': '#c9862f',
|
|
104
|
+
'accent-100': '#f5e8d3',
|
|
105
|
+
'status-success': '#2f6b40',
|
|
106
|
+
'status-success-bg': '#e2efdf',
|
|
107
|
+
'status-warning': '#96690f',
|
|
108
|
+
'status-warning-bg': '#f6ecd4',
|
|
109
|
+
'status-danger': '#a53f2a',
|
|
110
|
+
'status-danger-bg': '#f7e2db',
|
|
111
|
+
'status-info': '#3e5f80',
|
|
112
|
+
'status-info-bg': '#e0eaf2',
|
|
113
|
+
'status-neutral': '#55605a',
|
|
114
|
+
'status-neutral-bg': '#e8eae4',
|
|
115
|
+
'status-critical': '#8f1f14',
|
|
116
|
+
'danger-600': '#a53f2a',
|
|
117
|
+
'warning-600': '#96690f',
|
|
118
|
+
line: '#e2dfd3',
|
|
119
|
+
'line-strong': '#cfcaba',
|
|
120
|
+
'line-chrome': '#2a3f30',
|
|
121
|
+
'font-ui': "'Archivo', 'Segoe UI', system-ui, sans-serif",
|
|
122
|
+
'font-display': "'Fraunces', Georgia, serif",
|
|
123
|
+
'font-mono': "'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace",
|
|
124
|
+
'text-xs': '11px',
|
|
125
|
+
'text-sm': '12.5px',
|
|
126
|
+
'text-base': '13.5px',
|
|
127
|
+
'text-md': '15px',
|
|
128
|
+
'text-lg': '17px',
|
|
129
|
+
'text-xl': '21px',
|
|
130
|
+
'text-2xl': '26px',
|
|
131
|
+
'sp-1': '4px',
|
|
132
|
+
'sp-2': '8px',
|
|
133
|
+
'sp-3': '12px',
|
|
134
|
+
'sp-4': '16px',
|
|
135
|
+
'sp-5': '20px',
|
|
136
|
+
'sp-6': '24px',
|
|
137
|
+
'sp-7': '32px',
|
|
138
|
+
'sp-8': '40px',
|
|
139
|
+
'sp-9': '56px',
|
|
140
|
+
'r-sm': '4px',
|
|
141
|
+
'r-md': '6px',
|
|
142
|
+
'r-lg': '9px',
|
|
143
|
+
'r-pill': '999px',
|
|
144
|
+
'shadow-1': '0 1px 2px rgba(26, 35, 28, 0.05)',
|
|
145
|
+
'shadow-2': '0 2px 6px rgba(26, 35, 28, 0.07), 0 1px 2px rgba(26, 35, 28, 0.05)',
|
|
146
|
+
'shadow-3': '0 12px 32px -8px rgba(26, 35, 28, 0.18), 0 2px 6px rgba(26, 35, 28, 0.06)',
|
|
147
|
+
'shadow-overlay': '0 24px 64px -16px rgba(19, 31, 23, 0.35)',
|
|
148
|
+
'sidebar-w': '244px',
|
|
149
|
+
'sidebar-w-collapsed': '64px',
|
|
150
|
+
'topbar-h': '54px',
|
|
151
|
+
'page-max': '1560px',
|
|
152
|
+
'chart-1': '#357344',
|
|
153
|
+
'chart-2': '#b06e22',
|
|
154
|
+
'chart-3': '#3e5f80',
|
|
155
|
+
'chart-4': '#7a6ba8',
|
|
156
|
+
'chart-5': '#8a5a3b',
|
|
157
|
+
'chart-6': '#5e7d5a',
|
|
158
|
+
'chart-faint': '#e5e9df',
|
|
159
|
+
'tint-hover': 'rgba(26, 35, 28, 0.06)',
|
|
160
|
+
'tint-press': 'rgba(26, 35, 28, 0.09)',
|
|
161
|
+
'topbar-glass': 'rgba(244, 243, 238, 0.86)',
|
|
162
|
+
'dur-1': '110ms',
|
|
163
|
+
'dur-2': '180ms',
|
|
164
|
+
'dur-3': '280ms',
|
|
165
|
+
ease: 'cubic-bezier(0.32, 0.72, 0, 1)',
|
|
166
|
+
},
|
|
167
|
+
darkCustomVars: {
|
|
168
|
+
paper: '#10140f',
|
|
169
|
+
'paper-deep': '#151a14',
|
|
170
|
+
surface: '#191f18',
|
|
171
|
+
'surface-sunken': '#141a13',
|
|
172
|
+
'surface-tint': '#1f261e',
|
|
173
|
+
'ink-900': '#edf0e7',
|
|
174
|
+
'ink-800': '#dce1d2',
|
|
175
|
+
'ink-700': '#c3c9b6',
|
|
176
|
+
'ink-600': '#a2aa96',
|
|
177
|
+
'ink-500': '#828b79',
|
|
178
|
+
'ink-400': '#646d5d',
|
|
179
|
+
'ink-300': '#4b5346',
|
|
180
|
+
'ink-200': '#333c30',
|
|
181
|
+
'ink-100': '#232b21',
|
|
182
|
+
'chrome-900': '#0c130d',
|
|
183
|
+
'chrome-800': '#0f1810',
|
|
184
|
+
'chrome-700': '#132016',
|
|
185
|
+
'chrome-600': '#182718',
|
|
186
|
+
'chrome-500': '#1d2f1e',
|
|
187
|
+
'chrome-line': '#1c2a1d',
|
|
188
|
+
'chrome-text': '#b9c6b6',
|
|
189
|
+
'chrome-text-dim': '#71836f',
|
|
190
|
+
'chrome-active': '#cfe2ca',
|
|
191
|
+
'primary-700': '#8fc79c',
|
|
192
|
+
'primary-600': '#79b788',
|
|
193
|
+
'primary-500': '#6aa878',
|
|
194
|
+
'primary-100': 'rgba(121, 183, 136, 0.16)',
|
|
195
|
+
'primary-050': 'rgba(121, 183, 136, 0.09)',
|
|
196
|
+
'accent-600': '#d9a54f',
|
|
197
|
+
'accent-500': '#cf9a48',
|
|
198
|
+
'accent-100': 'rgba(217, 165, 79, 0.15)',
|
|
199
|
+
'status-success': '#7cb989',
|
|
200
|
+
'status-success-bg': 'rgba(124, 185, 137, 0.14)',
|
|
201
|
+
'status-warning': '#d3a04e',
|
|
202
|
+
'status-warning-bg': 'rgba(211, 160, 78, 0.14)',
|
|
203
|
+
'status-danger': '#d07a63',
|
|
204
|
+
'status-danger-bg': 'rgba(208, 122, 99, 0.15)',
|
|
205
|
+
'status-info': '#8fb0d4',
|
|
206
|
+
'status-info-bg': 'rgba(143, 176, 212, 0.14)',
|
|
207
|
+
'status-neutral': '#a3a898',
|
|
208
|
+
'status-neutral-bg': 'rgba(163, 168, 152, 0.13)',
|
|
209
|
+
'status-critical': '#e08a73',
|
|
210
|
+
'danger-600': '#d07a63',
|
|
211
|
+
'warning-600': '#d3a04e',
|
|
212
|
+
line: '#262e24',
|
|
213
|
+
'line-strong': '#333d30',
|
|
214
|
+
'line-chrome': '#1c2a1d',
|
|
215
|
+
'shadow-1': '0 1px 2px rgba(0, 0, 0, 0.35)',
|
|
216
|
+
'shadow-2': '0 2px 6px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3)',
|
|
217
|
+
'shadow-3': '0 12px 32px -8px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.35)',
|
|
218
|
+
'shadow-overlay': '0 24px 64px -16px rgba(0, 0, 0, 0.7)',
|
|
219
|
+
'chart-1': '#79b788',
|
|
220
|
+
'chart-2': '#d9a54f',
|
|
221
|
+
'chart-3': '#8fb0d4',
|
|
222
|
+
'chart-4': '#a79bd4',
|
|
223
|
+
'chart-5': '#c78e6b',
|
|
224
|
+
'chart-6': '#93b389',
|
|
225
|
+
'chart-faint': '#232b21',
|
|
226
|
+
'tint-hover': 'rgba(237, 240, 231, 0.06)',
|
|
227
|
+
'tint-press': 'rgba(237, 240, 231, 0.09)',
|
|
228
|
+
'topbar-glass': 'rgba(16, 20, 15, 0.86)',
|
|
229
|
+
},
|
|
230
|
+
};
|
|
@@ -3,6 +3,7 @@ export { oceanTheme } from './ocean.theme';
|
|
|
3
3
|
export { midnightTheme } from './midnight.theme';
|
|
4
4
|
export { editorialTheme } from './editorial.theme';
|
|
5
5
|
export { forestTheme } from './forest.theme';
|
|
6
|
+
export { fieldTheme } from './field.theme';
|
|
6
7
|
export { createTheme } from './create-theme';
|
|
7
8
|
export type { ThemeOverrides } from './create-theme';
|
|
8
9
|
export { registerTheme, getTheme, hasTheme, listThemes } from './registry';
|
|
@@ -4,6 +4,7 @@ import { oceanTheme } from './ocean.theme';
|
|
|
4
4
|
import { midnightTheme } from './midnight.theme';
|
|
5
5
|
import { editorialTheme } from './editorial.theme';
|
|
6
6
|
import { forestTheme } from './forest.theme';
|
|
7
|
+
import { fieldTheme } from './field.theme';
|
|
7
8
|
|
|
8
9
|
const themeRegistry = new Map<string, ThemeConfig>([
|
|
9
10
|
['default', defaultTheme],
|
|
@@ -11,6 +12,7 @@ const themeRegistry = new Map<string, ThemeConfig>([
|
|
|
11
12
|
['midnight', midnightTheme],
|
|
12
13
|
['editorial', editorialTheme],
|
|
13
14
|
['forest', forestTheme],
|
|
15
|
+
['field', fieldTheme],
|
|
14
16
|
]);
|
|
15
17
|
|
|
16
18
|
export function registerTheme(theme: ThemeConfig): void {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
import { cn } from '../../infrastructure/utils';
|
|
3
|
+
|
|
4
|
+
export interface ConditionPipsProps extends HTMLAttributes<HTMLSpanElement> {
|
|
5
|
+
score: number | null | undefined;
|
|
6
|
+
max?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
ariaLabel?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ConditionPips({
|
|
12
|
+
score,
|
|
13
|
+
max = 5,
|
|
14
|
+
className,
|
|
15
|
+
ariaLabel,
|
|
16
|
+
...props
|
|
17
|
+
}: ConditionPipsProps) {
|
|
18
|
+
const value = Math.max(0, Math.min(score ?? 0, max));
|
|
19
|
+
const label = ariaLabel ?? `${value}/${max}`;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<span
|
|
23
|
+
className={cn('cond-pips', className)}
|
|
24
|
+
role="img"
|
|
25
|
+
aria-label={label}
|
|
26
|
+
{...props}
|
|
27
|
+
>
|
|
28
|
+
{Array.from({ length: max }, (_, i) => (
|
|
29
|
+
<span
|
|
30
|
+
key={i}
|
|
31
|
+
className={cn('pip', i < value && 'on')}
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
/>
|
|
34
|
+
))}
|
|
35
|
+
</span>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -99,3 +99,6 @@ export type { EntityRowProps } from './EntityRow';
|
|
|
99
99
|
|
|
100
100
|
export { PlaceholderPanel } from './PlaceholderPanel';
|
|
101
101
|
export type { PlaceholderPanelProps } from './PlaceholderPanel';
|
|
102
|
+
|
|
103
|
+
export { ConditionPips } from './ConditionPips';
|
|
104
|
+
export type { ConditionPipsProps } from './ConditionPips';
|