courthive-components 0.9.6 → 0.9.8

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 CHANGED
@@ -1,3 +1,415 @@
1
1
  # courthive-components
2
2
 
3
- shared components for competition projects
3
+ Vanilla JavaScript UI components for tennis tournament management and competition displays.
4
+
5
+ [![Storybook](https://img.shields.io/badge/Storybook-Documentation-ff4785?logo=storybook)](https://courthive.github.io/courthive-components/)
6
+ [![npm version](https://img.shields.io/npm/v/courthive-components.svg)](https://www.npmjs.com/package/courthive-components)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ ## Overview
10
+
11
+ This library provides a comprehensive set of UI components for building tournament management applications. Components are framework-agnostic (vanilla JavaScript) and designed to work seamlessly with the [Competition Factory](https://github.com/CourtHive/tods-competition-factory) engine.
12
+
13
+ **Used by:**
14
+
15
+ - **TMX** (Tournament Management eXperience) - Production tournament management application
16
+ - **Competition Factory Documentation** - Interactive examples and demonstrations
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install courthive-components
22
+ # or
23
+ yarn add courthive-components
24
+ # or
25
+ pnpm add courthive-components
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```javascript
31
+ import { renderMatchUp, scoringModal, compositions } from 'courthive-components';
32
+
33
+ // Render a match display
34
+ const matchUpElement = renderMatchUp({
35
+ matchUp: myMatchUpData,
36
+ composition: compositions.Australian
37
+ });
38
+ document.getElementById('container').appendChild(matchUpElement);
39
+
40
+ // Open scoring modal
41
+ scoringModal({
42
+ matchUp: myMatchUpData,
43
+ callback: (outcome) => {
44
+ console.log('Score submitted:', outcome);
45
+ }
46
+ });
47
+ ```
48
+
49
+ ## Components
50
+
51
+ ### Display Components
52
+
53
+ #### **renderMatchUp**
54
+
55
+ Display a single match with scores, participants, and status indicators.
56
+
57
+ ```javascript
58
+ import { renderMatchUp, compositions } from 'courthive-components';
59
+
60
+ const element = renderMatchUp({
61
+ matchUp: matchUpData,
62
+ composition: compositions.Wimbledon,
63
+ isLucky: false
64
+ });
65
+ ```
66
+
67
+ #### **renderStructure**
68
+
69
+ Display a complete draw structure (bracket, round robin, etc.).
70
+
71
+ ```javascript
72
+ import { renderStructure } from 'courthive-components';
73
+
74
+ const element = renderStructure({
75
+ structure: drawStructure,
76
+ config: { showSeeds: true }
77
+ });
78
+ ```
79
+
80
+ #### **renderRound**
81
+
82
+ Display a single round of matches within a structure.
83
+
84
+ ```javascript
85
+ import { renderRound } from 'courthive-components';
86
+
87
+ const element = renderRound({
88
+ round: roundData,
89
+ roundNumber: 1
90
+ });
91
+ ```
92
+
93
+ #### **renderParticipant**
94
+
95
+ Display participant information (name, rating, country, etc.).
96
+
97
+ ```javascript
98
+ import { renderParticipant } from 'courthive-components';
99
+
100
+ const element = renderParticipant({
101
+ participant: participantData,
102
+ showRating: true
103
+ });
104
+ ```
105
+
106
+ #### **renderRoundHeader**
107
+
108
+ Display round headers for draw structures.
109
+
110
+ ```javascript
111
+ import { renderRoundHeader } from 'courthive-components';
112
+
113
+ const element = renderRoundHeader({
114
+ roundName: 'Quarterfinals',
115
+ roundNumber: 3
116
+ });
117
+ ```
118
+
119
+ #### **renderContainer**
120
+
121
+ Wrapper component for draw containers with scrolling and layout.
122
+
123
+ ### Input Components
124
+
125
+ #### **renderParticipantInput**
126
+
127
+ Autocomplete input for participant selection.
128
+
129
+ ```javascript
130
+ import { renderParticipantInput } from 'courthive-components';
131
+
132
+ const input = renderParticipantInput({
133
+ participants: participantsList,
134
+ onSelect: (participant) => console.log('Selected:', participant)
135
+ });
136
+ ```
137
+
138
+ ### Modal Components
139
+
140
+ #### **cModal**
141
+
142
+ Base modal system with flexible configuration.
143
+
144
+ ```javascript
145
+ import { cModal } from 'courthive-components';
146
+
147
+ cModal.open({
148
+ title: 'Confirm Action',
149
+ content: 'Are you sure?',
150
+ buttons: [
151
+ { label: 'Cancel', close: true },
152
+ { label: 'Confirm', onClick: handleConfirm, close: true }
153
+ ]
154
+ });
155
+ ```
156
+
157
+ #### **scoringModal**
158
+
159
+ Interactive score entry with multiple input approaches.
160
+
161
+ ```javascript
162
+ import { scoringModal, setScoringConfig } from 'courthive-components';
163
+
164
+ // Configure scoring behavior
165
+ setScoringConfig({
166
+ scoringApproach: 'dynamicSets', // 'dynamicSets' | 'freeScore' | 'dialPad'
167
+ smartComplements: true,
168
+ composition: 'Australian'
169
+ });
170
+
171
+ // Open scoring modal
172
+ scoringModal({
173
+ matchUp: matchUpData,
174
+ callback: (outcome) => {
175
+ // outcome: { isValid, sets, winningSide, matchUpStatus }
176
+ }
177
+ });
178
+ ```
179
+
180
+ **Scoring Approaches:**
181
+
182
+ - **dynamicSets** - Set-by-set entry with real-time validation
183
+ - **freeScore** - Flexible text-based entry (e.g., "6-4 6-3")
184
+ - **dialPad** - Touch-friendly numeric keypad
185
+
186
+ #### **getMatchUpFormatModal**
187
+
188
+ Interactive modal for selecting/editing match formats.
189
+
190
+ ```javascript
191
+ import { getMatchUpFormatModal } from 'courthive-components';
192
+
193
+ getMatchUpFormatModal({
194
+ existingMatchUpFormat: 'SET3-S:6/TB7',
195
+ callback: (newFormat) => {
196
+ console.log('Format:', newFormat);
197
+ }
198
+ });
199
+ ```
200
+
201
+ ### Form Components
202
+
203
+ #### **renderForm**
204
+
205
+ Render dynamic forms from configuration.
206
+
207
+ ```javascript
208
+ import { renderForm } from 'courthive-components';
209
+
210
+ const inputs = renderForm(container, [
211
+ { field: 'name', label: 'Name', type: 'text' },
212
+ { field: 'age', label: 'Age', type: 'number' }
213
+ ]);
214
+ ```
215
+
216
+ #### **renderField**
217
+
218
+ Render individual form fields.
219
+
220
+ #### **renderButtons**
221
+
222
+ Render button groups with consistent styling.
223
+
224
+ #### **renderMenu**
225
+
226
+ Render dropdown/context menus.
227
+
228
+ #### **validator**
229
+
230
+ Form validation utilities.
231
+
232
+ ### UI Components
233
+
234
+ #### **drawer**
235
+
236
+ Slide-out drawer component for side panels.
237
+
238
+ ```javascript
239
+ import { drawer, initDrawer } from 'courthive-components';
240
+
241
+ initDrawer(); // Initialize once
242
+
243
+ drawer.open({
244
+ title: 'Details',
245
+ content: myContent,
246
+ side: 'right' // 'left' | 'right'
247
+ });
248
+ ```
249
+
250
+ #### **tipster**
251
+
252
+ Tooltip/popover system using Tippy.js.
253
+
254
+ ```javascript
255
+ import { tipster } from 'courthive-components';
256
+
257
+ tipster({
258
+ target: buttonElement,
259
+ content: 'Click to edit',
260
+ placement: 'top'
261
+ });
262
+ ```
263
+
264
+ ### Compositions
265
+
266
+ Pre-configured visual themes matching Grand Slam tournaments:
267
+
268
+ ```javascript
269
+ import { compositions } from 'courthive-components';
270
+
271
+ // Available compositions:
272
+ compositions.Australian; // Australian Open colors
273
+ compositions.French; // Roland Garros colors
274
+ compositions.Wimbledon; // Wimbledon colors
275
+ compositions.US; // US Open colors
276
+ ```
277
+
278
+ ### Constants
279
+
280
+ #### **MATCH_FORMATS**
281
+
282
+ Pre-defined match format codes.
283
+
284
+ ```javascript
285
+ import { MATCH_FORMATS } from 'courthive-components';
286
+
287
+ console.log(MATCH_FORMATS.BEST_OF_3_TB7);
288
+ // 'SET3-S:6/TB7'
289
+ ```
290
+
291
+ ### Utilities
292
+
293
+ #### **courthiveComponentsVersion**
294
+
295
+ Get the current package version.
296
+
297
+ ```javascript
298
+ import { courthiveComponentsVersion } from 'courthive-components';
299
+
300
+ console.log(courthiveComponentsVersion());
301
+ ```
302
+
303
+ ## Documentation
304
+
305
+ 📚 **Interactive Documentation:** [Storybook](https://courthive.github.io/courthive-components/)
306
+
307
+ The Storybook includes:
308
+
309
+ - Live component demos
310
+ - Interactive examples
311
+ - Configuration options
312
+ - Usage patterns
313
+ - Integration guides
314
+
315
+ ## Styling
316
+
317
+ Components use Bulma CSS framework. Include Bulma in your project:
318
+
319
+ ```html
320
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css" />
321
+ ```
322
+
323
+ Or import the bundled CSS:
324
+
325
+ ```javascript
326
+ import 'courthive-components/dist/courthive-components.css';
327
+ ```
328
+
329
+ ## TypeScript Support
330
+
331
+ The package includes TypeScript definitions:
332
+
333
+ ```typescript
334
+ import { renderMatchUp, ScoringModalParams, ScoreOutcome } from 'courthive-components';
335
+
336
+ const params: ScoringModalParams = {
337
+ matchUp: myMatchUp,
338
+ callback: (outcome: ScoreOutcome) => {
339
+ if (outcome.isValid) {
340
+ console.log('Winner:', outcome.winningSide);
341
+ }
342
+ }
343
+ };
344
+ ```
345
+
346
+ ## Integration with Competition Factory
347
+
348
+ Components are designed to work with TODS (Tennis Open Data Standards) data structures from [tods-competition-factory](https://www.npmjs.com/package/tods-competition-factory):
349
+
350
+ ```javascript
351
+ import { tournamentEngine } from 'tods-competition-factory';
352
+ import { renderMatchUp, scoringModal } from 'courthive-components';
353
+
354
+ // Get match data from factory
355
+ const { matchUp } = tournamentEngine.findMatchUp({ matchUpId });
356
+
357
+ // Render with components
358
+ const display = renderMatchUp({ matchUp });
359
+
360
+ // Score with modal
361
+ scoringModal({
362
+ matchUp,
363
+ callback: (outcome) => {
364
+ // Update tournament using factory
365
+ tournamentEngine.setMatchUpStatus({
366
+ matchUpId,
367
+ outcome: {
368
+ score: { sets: outcome.sets },
369
+ winningSide: outcome.winningSide,
370
+ matchUpStatus: outcome.matchUpStatus
371
+ }
372
+ });
373
+ }
374
+ });
375
+ ```
376
+
377
+ ## Development
378
+
379
+ ```bash
380
+ # Install dependencies
381
+ pnpm install
382
+
383
+ # Start Storybook
384
+ pnpm storybook
385
+
386
+ # Build library
387
+ pnpm build
388
+
389
+ # Run tests
390
+ pnpm test
391
+
392
+ # Build Storybook for deployment
393
+ pnpm build-storybook
394
+ ```
395
+
396
+ ## Contributing
397
+
398
+ Contributions are welcome! This library is actively used in production tournament management applications.
399
+
400
+ ### Guidelines
401
+
402
+ - Maintain framework-agnostic vanilla JavaScript
403
+ - Follow existing component patterns
404
+ - Add Storybook stories for new components
405
+ - Include TypeScript types
406
+ - Test with Competition Factory integration
407
+
408
+ ## License
409
+
410
+ MIT © Charles Allen
411
+
412
+ ## Links
413
+
414
+ - **Competition Factory:** <https://github.com/CourtHive/tods-competition-factory>
415
+ - **TMX:** <https://github.com/CourtHive/tmx>