@trustquery/browser 0.1.0 → 0.2.1
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 +13 -1
- package/dist/trustquery.js +158 -16
- package/dist/trustquery.js.map +1 -1
- package/package.json +1 -1
- package/src/CommandScanner.js +5 -3
- package/src/DropdownManager.js +15 -5
- package/src/InteractionHandler.js +10 -4
- package/src/OverlayRenderer.js +7 -2
- package/src/TrustQuery.js +16 -2
- package/src/ValidationStateManager.js +105 -0
package/README.md
CHANGED
|
@@ -73,7 +73,19 @@ ui: {
|
|
|
73
73
|
```javascript
|
|
74
74
|
events: {
|
|
75
75
|
onWordHover: (matchData) => { /* ... */ },
|
|
76
|
-
onWordClick: (matchData) => { /* ... */ }
|
|
76
|
+
onWordClick: (matchData) => { /* ... */ },
|
|
77
|
+
onValidationChange: (validationState) => {
|
|
78
|
+
// Fires when validation state changes
|
|
79
|
+
// validationState: {
|
|
80
|
+
// hasBlockingError: boolean,
|
|
81
|
+
// errors: Array, // matches with message-state: 'error'
|
|
82
|
+
// warnings: Array, // matches with message-state: 'warning'
|
|
83
|
+
// info: Array // matches with message-state: 'info'
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// Example: Disable submit button on blocking errors
|
|
87
|
+
submitButton.disabled = validationState.hasBlockingError;
|
|
88
|
+
}
|
|
77
89
|
}
|
|
78
90
|
```
|
|
79
91
|
|
package/dist/trustquery.js
CHANGED
|
@@ -12,10 +12,13 @@ class OverlayRenderer {
|
|
|
12
12
|
this.options = {
|
|
13
13
|
theme: options.theme || 'light',
|
|
14
14
|
commandHandlers: options.commandHandlers || null,
|
|
15
|
+
debug: options.debug || false,
|
|
15
16
|
...options
|
|
16
17
|
};
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
if (this.options.debug) {
|
|
20
|
+
console.log('[OverlayRenderer] Initialized');
|
|
21
|
+
}
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -35,7 +38,9 @@ class OverlayRenderer {
|
|
|
35
38
|
// Update overlay
|
|
36
39
|
this.overlay.innerHTML = linesHTML;
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
if (this.options.debug) {
|
|
42
|
+
console.log('[OverlayRenderer] Rendered', lines.length, 'lines with', matches.length, 'matches');
|
|
43
|
+
}
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
/**
|
|
@@ -345,8 +350,6 @@ class CommandScanner {
|
|
|
345
350
|
// Sort by length (longest first) to match longer patterns first
|
|
346
351
|
commands.sort((a, b) => b.match.length - a.match.length);
|
|
347
352
|
|
|
348
|
-
console.log('[CommandScanner] Parsed commands:', commands.length, commands);
|
|
349
|
-
|
|
350
353
|
return commands;
|
|
351
354
|
}
|
|
352
355
|
|
|
@@ -369,7 +372,11 @@ class CommandScanner {
|
|
|
369
372
|
matches.push(...lineMatches);
|
|
370
373
|
});
|
|
371
374
|
|
|
372
|
-
|
|
375
|
+
// Only log when matches are found
|
|
376
|
+
if (matches.length > 0) {
|
|
377
|
+
console.log(`[CommandScanner] Found ${matches.length} matches`);
|
|
378
|
+
}
|
|
379
|
+
|
|
373
380
|
return matches;
|
|
374
381
|
}
|
|
375
382
|
|
|
@@ -769,7 +776,9 @@ class DropdownManager {
|
|
|
769
776
|
this.selectedDropdownIndex = 0;
|
|
770
777
|
this.keyboardHandler = null;
|
|
771
778
|
|
|
772
|
-
|
|
779
|
+
if (this.options.debug) {
|
|
780
|
+
console.log('[DropdownManager] Initialized with offset:', this.options.dropdownOffset);
|
|
781
|
+
}
|
|
773
782
|
}
|
|
774
783
|
|
|
775
784
|
/**
|
|
@@ -850,7 +859,9 @@ class DropdownManager {
|
|
|
850
859
|
document.addEventListener('click', this.closeDropdownHandler);
|
|
851
860
|
}, 0);
|
|
852
861
|
|
|
853
|
-
|
|
862
|
+
if (this.options.debug) {
|
|
863
|
+
console.log('[DropdownManager] Dropdown shown with', options.length, 'options');
|
|
864
|
+
}
|
|
854
865
|
}
|
|
855
866
|
|
|
856
867
|
/**
|
|
@@ -1284,7 +1295,9 @@ class DropdownManager {
|
|
|
1284
1295
|
* @param {Object} matchData - Match data
|
|
1285
1296
|
*/
|
|
1286
1297
|
handleDropdownSelect(option, matchData) {
|
|
1287
|
-
|
|
1298
|
+
if (this.options.debug) {
|
|
1299
|
+
console.log('[DropdownManager] Dropdown option selected:', option, 'for:', matchData.text);
|
|
1300
|
+
}
|
|
1288
1301
|
|
|
1289
1302
|
// Check if option has on-select.display
|
|
1290
1303
|
if (option['on-select'] && option['on-select'].display && this.options.textarea) {
|
|
@@ -1310,7 +1323,9 @@ class DropdownManager {
|
|
|
1310
1323
|
const inputEvent = new Event('input', { bubbles: true });
|
|
1311
1324
|
textarea.dispatchEvent(inputEvent);
|
|
1312
1325
|
|
|
1313
|
-
|
|
1326
|
+
if (this.options.debug) {
|
|
1327
|
+
console.log('[DropdownManager] Appended to', matchData.text, '→', newText);
|
|
1328
|
+
}
|
|
1314
1329
|
}
|
|
1315
1330
|
}
|
|
1316
1331
|
|
|
@@ -1335,7 +1350,9 @@ class DropdownManager {
|
|
|
1335
1350
|
*/
|
|
1336
1351
|
destroy() {
|
|
1337
1352
|
this.cleanup();
|
|
1338
|
-
|
|
1353
|
+
if (this.options.debug) {
|
|
1354
|
+
console.log('[DropdownManager] Destroyed');
|
|
1355
|
+
}
|
|
1339
1356
|
}
|
|
1340
1357
|
}
|
|
1341
1358
|
|
|
@@ -1367,17 +1384,21 @@ class InteractionHandler {
|
|
|
1367
1384
|
this.bubbleManager = new BubbleManager({
|
|
1368
1385
|
bubbleDelay: this.options.bubbleDelay,
|
|
1369
1386
|
styleManager: this.options.styleManager,
|
|
1370
|
-
commandHandlers: this.options.commandHandlers
|
|
1387
|
+
commandHandlers: this.options.commandHandlers,
|
|
1388
|
+
debug: this.options.debug
|
|
1371
1389
|
});
|
|
1372
1390
|
|
|
1373
1391
|
this.dropdownManager = new DropdownManager({
|
|
1374
1392
|
styleManager: this.options.styleManager,
|
|
1375
1393
|
textarea: this.options.textarea,
|
|
1376
1394
|
onWordClick: this.options.onWordClick,
|
|
1377
|
-
dropdownOffset: this.options.dropdownOffset
|
|
1395
|
+
dropdownOffset: this.options.dropdownOffset,
|
|
1396
|
+
debug: this.options.debug
|
|
1378
1397
|
});
|
|
1379
1398
|
|
|
1380
|
-
|
|
1399
|
+
if (this.options.debug) {
|
|
1400
|
+
console.log('[InteractionHandler] Initialized');
|
|
1401
|
+
}
|
|
1381
1402
|
}
|
|
1382
1403
|
|
|
1383
1404
|
/**
|
|
@@ -1415,7 +1436,9 @@ class InteractionHandler {
|
|
|
1415
1436
|
}
|
|
1416
1437
|
});
|
|
1417
1438
|
|
|
1418
|
-
|
|
1439
|
+
if (this.options.debug) {
|
|
1440
|
+
console.log('[InteractionHandler] Updated with', matches.length, 'interactive elements');
|
|
1441
|
+
}
|
|
1419
1442
|
}
|
|
1420
1443
|
|
|
1421
1444
|
/**
|
|
@@ -2503,6 +2526,112 @@ class AutoGrow {
|
|
|
2503
2526
|
}
|
|
2504
2527
|
}
|
|
2505
2528
|
|
|
2529
|
+
// ValidationStateManager - Tracks validation state and triggers callbacks
|
|
2530
|
+
|
|
2531
|
+
class ValidationStateManager {
|
|
2532
|
+
/**
|
|
2533
|
+
* Create validation state manager
|
|
2534
|
+
* @param {Object} options - Configuration
|
|
2535
|
+
*/
|
|
2536
|
+
constructor(options = {}) {
|
|
2537
|
+
this.options = {
|
|
2538
|
+
onValidationChange: options.onValidationChange || null,
|
|
2539
|
+
...options
|
|
2540
|
+
};
|
|
2541
|
+
|
|
2542
|
+
this.state = {
|
|
2543
|
+
hasBlockingError: false,
|
|
2544
|
+
errors: [], // matches with message-state: 'error'
|
|
2545
|
+
warnings: [], // matches with message-state: 'warning'
|
|
2546
|
+
info: [] // matches with message-state: 'info'
|
|
2547
|
+
};
|
|
2548
|
+
|
|
2549
|
+
console.log('[ValidationStateManager] Initialized');
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
/**
|
|
2553
|
+
* Update validation state based on current matches
|
|
2554
|
+
* @param {Array} matches - Current matches from scanner
|
|
2555
|
+
*/
|
|
2556
|
+
update(matches) {
|
|
2557
|
+
// Reset state
|
|
2558
|
+
const newState = {
|
|
2559
|
+
hasBlockingError: false,
|
|
2560
|
+
errors: [],
|
|
2561
|
+
warnings: [],
|
|
2562
|
+
info: []
|
|
2563
|
+
};
|
|
2564
|
+
|
|
2565
|
+
// Categorize current matches
|
|
2566
|
+
matches.forEach(match => {
|
|
2567
|
+
const messageState = match.intent?.handler?.['message-state'];
|
|
2568
|
+
const blockSubmit = match.intent?.handler?.['block-submit'] === true;
|
|
2569
|
+
|
|
2570
|
+
if (blockSubmit) {
|
|
2571
|
+
newState.hasBlockingError = true;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
switch (messageState) {
|
|
2575
|
+
case 'error':
|
|
2576
|
+
newState.errors.push(match);
|
|
2577
|
+
break;
|
|
2578
|
+
case 'warning':
|
|
2579
|
+
newState.warnings.push(match);
|
|
2580
|
+
break;
|
|
2581
|
+
case 'info':
|
|
2582
|
+
newState.info.push(match);
|
|
2583
|
+
break;
|
|
2584
|
+
}
|
|
2585
|
+
});
|
|
2586
|
+
|
|
2587
|
+
// Check if state changed
|
|
2588
|
+
const stateChanged =
|
|
2589
|
+
this.state.hasBlockingError !== newState.hasBlockingError ||
|
|
2590
|
+
this.state.errors.length !== newState.errors.length ||
|
|
2591
|
+
this.state.warnings.length !== newState.warnings.length ||
|
|
2592
|
+
this.state.info.length !== newState.info.length;
|
|
2593
|
+
|
|
2594
|
+
if (stateChanged) {
|
|
2595
|
+
this.state = newState;
|
|
2596
|
+
|
|
2597
|
+
// Trigger callback
|
|
2598
|
+
if (this.options.onValidationChange) {
|
|
2599
|
+
this.options.onValidationChange(this.state);
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
console.log('[ValidationStateManager] State changed:', {
|
|
2603
|
+
hasBlockingError: newState.hasBlockingError,
|
|
2604
|
+
errors: newState.errors.length,
|
|
2605
|
+
warnings: newState.warnings.length,
|
|
2606
|
+
info: newState.info.length
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
/**
|
|
2612
|
+
* Get current validation state
|
|
2613
|
+
* @returns {Object} Current validation state
|
|
2614
|
+
*/
|
|
2615
|
+
getState() {
|
|
2616
|
+
return { ...this.state };
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
/**
|
|
2620
|
+
* Reset validation state to empty
|
|
2621
|
+
*/
|
|
2622
|
+
reset() {
|
|
2623
|
+
this.update([]);
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
/**
|
|
2627
|
+
* Check if there are blocking errors
|
|
2628
|
+
* @returns {boolean} True if there are blocking errors
|
|
2629
|
+
*/
|
|
2630
|
+
hasBlockingErrors() {
|
|
2631
|
+
return this.state.hasBlockingError;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
|
|
2506
2635
|
// TrustQuery - Lightweight library to make textareas interactive
|
|
2507
2636
|
// Turns matching words into interactive elements with hover bubbles and click actions
|
|
2508
2637
|
|
|
@@ -2607,6 +2736,7 @@ class TrustQuery {
|
|
|
2607
2736
|
// Events (callbacks)
|
|
2608
2737
|
onWordClick: events.onWordClick || options.onWordClick || null,
|
|
2609
2738
|
onWordHover: events.onWordHover || options.onWordHover || null,
|
|
2739
|
+
onValidationChange: events.onValidationChange || options.onValidationChange || null,
|
|
2610
2740
|
|
|
2611
2741
|
// Theme/style options (passed to StyleManager)
|
|
2612
2742
|
backgroundColor: ui.backgroundColor || options.backgroundColor,
|
|
@@ -2643,7 +2773,8 @@ class TrustQuery {
|
|
|
2643
2773
|
// Initialize renderer
|
|
2644
2774
|
this.renderer = new OverlayRenderer(this.overlay, {
|
|
2645
2775
|
theme: this.options.theme,
|
|
2646
|
-
commandHandlers: this.commandHandlers // Pass handlers for styling
|
|
2776
|
+
commandHandlers: this.commandHandlers, // Pass handlers for styling
|
|
2777
|
+
debug: this.options.debug // Pass debug flag
|
|
2647
2778
|
});
|
|
2648
2779
|
|
|
2649
2780
|
// Initialize scanner (will be configured when command map loads)
|
|
@@ -2657,7 +2788,13 @@ class TrustQuery {
|
|
|
2657
2788
|
onWordHover: this.options.onWordHover,
|
|
2658
2789
|
styleManager: this.styleManager, // Pass style manager for bubbles/dropdowns
|
|
2659
2790
|
commandHandlers: this.commandHandlers, // Pass handlers for bubble content
|
|
2660
|
-
textarea: this.textarea // Pass textarea for on-select display updates
|
|
2791
|
+
textarea: this.textarea, // Pass textarea for on-select display updates
|
|
2792
|
+
debug: this.options.debug // Pass debug flag
|
|
2793
|
+
});
|
|
2794
|
+
|
|
2795
|
+
// Initialize validation state manager
|
|
2796
|
+
this.validationStateManager = new ValidationStateManager({
|
|
2797
|
+
onValidationChange: this.options.onValidationChange
|
|
2661
2798
|
});
|
|
2662
2799
|
|
|
2663
2800
|
// Initialize features
|
|
@@ -2856,6 +2993,11 @@ class TrustQuery {
|
|
|
2856
2993
|
|
|
2857
2994
|
// Update interaction handler with new elements
|
|
2858
2995
|
this.interactionHandler.update();
|
|
2996
|
+
|
|
2997
|
+
// Update validation state
|
|
2998
|
+
if (this.validationStateManager) {
|
|
2999
|
+
this.validationStateManager.update(matches);
|
|
3000
|
+
}
|
|
2859
3001
|
}
|
|
2860
3002
|
|
|
2861
3003
|
/**
|