cjm-transcript-segment-align 0.0.1__py3-none-any.whl
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.
- cjm_transcript_segment_align/__init__.py +1 -0
- cjm_transcript_segment_align/_modidx.py +101 -0
- cjm_transcript_segment_align/components/__init__.py +0 -0
- cjm_transcript_segment_align/components/handlers.py +331 -0
- cjm_transcript_segment_align/components/helpers.py +85 -0
- cjm_transcript_segment_align/components/keyboard_config.py +323 -0
- cjm_transcript_segment_align/components/step_renderer.py +624 -0
- cjm_transcript_segment_align/html_ids.py +44 -0
- cjm_transcript_segment_align/routes/__init__.py +0 -0
- cjm_transcript_segment_align/routes/chrome.py +169 -0
- cjm_transcript_segment_align/routes/forced_alignment.py +396 -0
- cjm_transcript_segment_align/services/__init__.py +0 -0
- cjm_transcript_segment_align/services/forced_alignment.py +301 -0
- cjm_transcript_segment_align-0.0.1.dist-info/LICENSE +201 -0
- cjm_transcript_segment_align-0.0.1.dist-info/METADATA +777 -0
- cjm_transcript_segment_align-0.0.1.dist-info/RECORD +19 -0
- cjm_transcript_segment_align-0.0.1.dist-info/WHEEL +5 -0
- cjm_transcript_segment_align-0.0.1.dist-info/entry_points.txt +2 -0
- cjm_transcript_segment_align-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""Shared keyboard navigation configuration for the combined Phase 2 step"""
|
|
2
|
+
|
|
3
|
+
# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/keyboard_config.ipynb.
|
|
4
|
+
|
|
5
|
+
# %% auto #0
|
|
6
|
+
__all__ = ['DEBUG_KB_SYSTEM', 'ZONE_CHANGE_CALLBACK', 'SWITCH_CHROME_BTN_ID', 'render_keyboard_hints_collapsible',
|
|
7
|
+
'build_combined_kb_system', 'generate_zone_change_js']
|
|
8
|
+
|
|
9
|
+
# %% ../../nbs/components/keyboard_config.ipynb #kb-imports
|
|
10
|
+
from typing import Any, Tuple, Optional
|
|
11
|
+
|
|
12
|
+
from fasthtml.common import Details, Summary, Div, Script
|
|
13
|
+
|
|
14
|
+
# DaisyUI components
|
|
15
|
+
from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
|
|
16
|
+
from cjm_fasthtml_daisyui.components.data_display.collapse import (
|
|
17
|
+
collapse, collapse_title, collapse_content, collapse_modifiers
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Tailwind utilities
|
|
21
|
+
from cjm_fasthtml_tailwind.utilities.typography import font_size, font_weight
|
|
22
|
+
from cjm_fasthtml_tailwind.core.base import combine_classes
|
|
23
|
+
|
|
24
|
+
# Keyboard navigation library
|
|
25
|
+
from cjm_fasthtml_keyboard_navigation.core.manager import ZoneManager
|
|
26
|
+
from cjm_fasthtml_keyboard_navigation.components.hints import render_keyboard_hints
|
|
27
|
+
from cjm_fasthtml_keyboard_navigation.components.system import render_keyboard_system
|
|
28
|
+
|
|
29
|
+
# Card stack library
|
|
30
|
+
from cjm_fasthtml_card_stack.keyboard.actions import build_card_stack_url_map
|
|
31
|
+
|
|
32
|
+
# Local HTML IDs
|
|
33
|
+
from ..html_ids import CombinedHtmlIds
|
|
34
|
+
|
|
35
|
+
# Segmentation-specific keyboard config (building blocks)
|
|
36
|
+
from cjm_transcript_segmentation.components.keyboard_config import (
|
|
37
|
+
SD_SEG_ENTER_SPLIT_BTN, SD_SEG_EXIT_SPLIT_BTN,
|
|
38
|
+
SD_SEG_SPLIT_BTN, SD_SEG_MERGE_BTN, SD_SEG_UNDO_BTN,
|
|
39
|
+
create_seg_kb_parts,
|
|
40
|
+
)
|
|
41
|
+
from cjm_transcript_segmentation.components.card_stack_config import (
|
|
42
|
+
SEG_CS_CONFIG, SEG_CS_IDS, SEG_CS_BTN_IDS,
|
|
43
|
+
SEG_TS_IDS,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Alignment-specific keyboard config (building blocks)
|
|
47
|
+
from cjm_transcript_vad_align.components.keyboard_config import (
|
|
48
|
+
create_align_kb_parts,
|
|
49
|
+
)
|
|
50
|
+
from cjm_transcript_vad_align.components.card_stack_config import (
|
|
51
|
+
ALIGN_CS_CONFIG, ALIGN_CS_IDS, ALIGN_CS_BTN_IDS,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# URL bundles
|
|
55
|
+
from cjm_transcript_segmentation.models import SegmentationUrls
|
|
56
|
+
from cjm_transcript_vad_align.models import AlignmentUrls
|
|
57
|
+
|
|
58
|
+
# Debug flag for keyboard system tracing (set False in production)
|
|
59
|
+
DEBUG_KB_SYSTEM = True
|
|
60
|
+
|
|
61
|
+
# %% ../../nbs/components/keyboard_config.ipynb #kb-hints
|
|
62
|
+
def render_keyboard_hints_collapsible(
|
|
63
|
+
manager:ZoneManager, # Keyboard zone manager with actions configured
|
|
64
|
+
container_id:str="sd-keyboard-hints", # HTML ID for the hints container
|
|
65
|
+
include_zone_switch:bool=False, # Whether to include zone switch hints
|
|
66
|
+
) -> Any: # Collapsible keyboard hints component
|
|
67
|
+
"""Render keyboard shortcut hints in a collapsible DaisyUI collapse."""
|
|
68
|
+
hints = render_keyboard_hints(
|
|
69
|
+
manager,
|
|
70
|
+
include_navigation=True,
|
|
71
|
+
include_zone_switch=include_zone_switch,
|
|
72
|
+
badge_style="outline",
|
|
73
|
+
container_id=container_id,
|
|
74
|
+
use_icons=False
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return Details(
|
|
78
|
+
Summary(
|
|
79
|
+
"Keyboard Shortcuts",
|
|
80
|
+
cls=combine_classes(collapse_title, font_size.sm, font_weight.medium)
|
|
81
|
+
),
|
|
82
|
+
Div(
|
|
83
|
+
hints,
|
|
84
|
+
cls=collapse_content
|
|
85
|
+
),
|
|
86
|
+
cls=combine_classes(collapse, collapse_modifiers.arrow, bg_dui.base_200)
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# %% ../../nbs/components/keyboard_config.ipynb #q9f5gd0d0s
|
|
90
|
+
# Zone change callback name — global JS function called when zone switches
|
|
91
|
+
ZONE_CHANGE_CALLBACK = "onCombinedZoneChange"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def build_combined_kb_system(
|
|
95
|
+
seg_urls:SegmentationUrls, # URL bundle for segmentation routes
|
|
96
|
+
align_urls:AlignmentUrls, # URL bundle for alignment routes
|
|
97
|
+
) -> Tuple[ZoneManager, Any]: # (keyboard manager, rendered keyboard system)
|
|
98
|
+
"""Build combined keyboard system with segmentation and alignment zones."""
|
|
99
|
+
if DEBUG_KB_SYSTEM:
|
|
100
|
+
print("[KB_SYSTEM] build_combined_kb_system called")
|
|
101
|
+
|
|
102
|
+
# Get segmentation-specific building blocks
|
|
103
|
+
seg_zone, seg_actions, seg_modes = create_seg_kb_parts(
|
|
104
|
+
ids=SEG_CS_IDS,
|
|
105
|
+
button_ids=SEG_CS_BTN_IDS,
|
|
106
|
+
config=SEG_CS_CONFIG,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Get alignment-specific building blocks
|
|
110
|
+
align_zone, align_actions, align_modes = create_align_kb_parts(
|
|
111
|
+
ids=ALIGN_CS_IDS,
|
|
112
|
+
button_ids=ALIGN_CS_BTN_IDS,
|
|
113
|
+
config=ALIGN_CS_CONFIG,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if DEBUG_KB_SYSTEM:
|
|
117
|
+
print(f"[KB_SYSTEM] seg_zone.id: {seg_zone.id}")
|
|
118
|
+
print(f"[KB_SYSTEM] align_zone.id: {align_zone.id}")
|
|
119
|
+
print(f"[KB_SYSTEM] seg_actions count: {len(seg_actions)}")
|
|
120
|
+
print(f"[KB_SYSTEM] align_actions count: {len(align_actions)}")
|
|
121
|
+
|
|
122
|
+
# Combine modes (only segmentation has split mode)
|
|
123
|
+
all_modes = (*seg_modes, *align_modes)
|
|
124
|
+
|
|
125
|
+
# Combine actions from both zones
|
|
126
|
+
all_actions = (*seg_actions, *align_actions)
|
|
127
|
+
|
|
128
|
+
# Assemble into ZoneManager with zone switching enabled
|
|
129
|
+
kb_manager = ZoneManager(
|
|
130
|
+
zones=(seg_zone, align_zone),
|
|
131
|
+
actions=all_actions,
|
|
132
|
+
modes=all_modes,
|
|
133
|
+
initial_zone_id=seg_zone.id,
|
|
134
|
+
prev_zone_key="ArrowLeft",
|
|
135
|
+
next_zone_key="ArrowRight",
|
|
136
|
+
on_zone_change=ZONE_CHANGE_CALLBACK,
|
|
137
|
+
state_hidden_inputs=True,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Build URL maps for both stacks
|
|
141
|
+
seg_include_selector = (
|
|
142
|
+
f"#{SEG_CS_IDS.focused_index_input}, "
|
|
143
|
+
f"#{SEG_TS_IDS.anchor_input}"
|
|
144
|
+
)
|
|
145
|
+
align_include_selector = f"#{ALIGN_CS_IDS.focused_index_input}"
|
|
146
|
+
|
|
147
|
+
# Segmentation URL mappings
|
|
148
|
+
seg_url_map = {
|
|
149
|
+
**build_card_stack_url_map(SEG_CS_BTN_IDS, seg_urls.card_stack),
|
|
150
|
+
SD_SEG_ENTER_SPLIT_BTN: seg_urls.enter_split,
|
|
151
|
+
SD_SEG_EXIT_SPLIT_BTN: seg_urls.exit_split,
|
|
152
|
+
SD_SEG_SPLIT_BTN: seg_urls.split,
|
|
153
|
+
SD_SEG_MERGE_BTN: seg_urls.merge,
|
|
154
|
+
SD_SEG_UNDO_BTN: seg_urls.undo,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# Alignment URL mappings (navigation only — no undo for alignment)
|
|
158
|
+
align_url_map = {
|
|
159
|
+
**build_card_stack_url_map(ALIGN_CS_BTN_IDS, align_urls.card_stack),
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# Combined URL map
|
|
163
|
+
url_map = {**seg_url_map, **align_url_map}
|
|
164
|
+
|
|
165
|
+
# Target maps (each stack targets its own card_stack element)
|
|
166
|
+
seg_target = f"#{SEG_CS_IDS.card_stack}"
|
|
167
|
+
align_target = f"#{ALIGN_CS_IDS.card_stack}"
|
|
168
|
+
target_map = {
|
|
169
|
+
**{btn_id: seg_target for btn_id in seg_url_map},
|
|
170
|
+
**{btn_id: align_target for btn_id in align_url_map},
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# Include maps (each stack includes its own focused_index input)
|
|
174
|
+
include_map = {
|
|
175
|
+
**{btn_id: seg_include_selector for btn_id in seg_url_map},
|
|
176
|
+
**{btn_id: align_include_selector for btn_id in align_url_map},
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Swap map (none for all — OOB swaps handle updates)
|
|
180
|
+
swap_map = {btn_id: "none" for btn_id in url_map}
|
|
181
|
+
|
|
182
|
+
kb_system = render_keyboard_system(
|
|
183
|
+
kb_manager,
|
|
184
|
+
url_map=url_map,
|
|
185
|
+
target_map=target_map,
|
|
186
|
+
include_map=include_map,
|
|
187
|
+
swap_map=swap_map,
|
|
188
|
+
show_hints=False,
|
|
189
|
+
include_state_inputs=True,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if DEBUG_KB_SYSTEM:
|
|
193
|
+
print(f"[KB_SYSTEM] combined kb_system built successfully")
|
|
194
|
+
|
|
195
|
+
return kb_manager, kb_system
|
|
196
|
+
|
|
197
|
+
# %% ../../nbs/components/keyboard_config.ipynb #0rck8zsx5u8m
|
|
198
|
+
# Hidden button ID for chrome swap HTMX trigger
|
|
199
|
+
SWITCH_CHROME_BTN_ID = "sd-switch-chrome-btn"
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def generate_zone_change_js(
|
|
203
|
+
switch_chrome_url:str="", # URL for chrome swap handler (empty = no swap)
|
|
204
|
+
) -> Script: # Script element with zone change callback and click handlers
|
|
205
|
+
"""Generate JavaScript for zone change handling and column click handlers."""
|
|
206
|
+
# Zone IDs from card stack configs
|
|
207
|
+
seg_zone_id = SEG_CS_IDS.card_stack
|
|
208
|
+
align_zone_id = ALIGN_CS_IDS.card_stack
|
|
209
|
+
|
|
210
|
+
# Card stack prefixes for syncCountDropdown calls
|
|
211
|
+
seg_prefix = SEG_CS_CONFIG.prefix
|
|
212
|
+
align_prefix = ALIGN_CS_CONFIG.prefix
|
|
213
|
+
|
|
214
|
+
# Column container IDs
|
|
215
|
+
seg_col_id = CombinedHtmlIds.SEG_COLUMN
|
|
216
|
+
align_col_id = CombinedHtmlIds.ALIGNMENT_COLUMN
|
|
217
|
+
active_input_id = CombinedHtmlIds.ACTIVE_COLUMN_INPUT
|
|
218
|
+
|
|
219
|
+
# Chrome swap trigger with dropdown sync (optional)
|
|
220
|
+
chrome_swap_js = ""
|
|
221
|
+
if switch_chrome_url:
|
|
222
|
+
chrome_swap_js = f"""
|
|
223
|
+
// Trigger chrome swap via hidden HTMX button
|
|
224
|
+
const chromeSwitchBtn = document.getElementById('{SWITCH_CHROME_BTN_ID}');
|
|
225
|
+
if (chromeSwitchBtn) {{
|
|
226
|
+
// Add one-time listener to sync dropdown after chrome swap settles
|
|
227
|
+
function onChromeSettle(evt) {{
|
|
228
|
+
// Sync the active card stack's dropdown from localStorage
|
|
229
|
+
const activePrefix = (newZoneId === seg_zone_id) ? '{seg_prefix}' : '{align_prefix}';
|
|
230
|
+
if (window.cardStacks?.[activePrefix]?.syncCountDropdown) {{
|
|
231
|
+
window.cardStacks[activePrefix].syncCountDropdown();
|
|
232
|
+
}}
|
|
233
|
+
document.body.removeEventListener('htmx:afterSettle', onChromeSettle);
|
|
234
|
+
}}
|
|
235
|
+
document.body.addEventListener('htmx:afterSettle', onChromeSettle);
|
|
236
|
+
chromeSwitchBtn.click();
|
|
237
|
+
}}
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
js_code = f"""
|
|
241
|
+
(function() {{
|
|
242
|
+
const seg_zone_id = '{seg_zone_id}';
|
|
243
|
+
const align_zone_id = '{align_zone_id}';
|
|
244
|
+
const seg_col_id = '{seg_col_id}';
|
|
245
|
+
const align_col_id = '{align_col_id}';
|
|
246
|
+
const active_input_id = '{active_input_id}';
|
|
247
|
+
|
|
248
|
+
function updateColumnStyles(activeZoneId) {{
|
|
249
|
+
const segCol = document.getElementById(seg_col_id);
|
|
250
|
+
const alignCol = document.getElementById(align_col_id);
|
|
251
|
+
const activeInput = document.getElementById(active_input_id);
|
|
252
|
+
|
|
253
|
+
if (!segCol || !alignCol) return;
|
|
254
|
+
|
|
255
|
+
const isSegActive = activeZoneId === seg_zone_id;
|
|
256
|
+
|
|
257
|
+
// Ring classes for active indicator
|
|
258
|
+
segCol.classList.toggle('ring-1', isSegActive);
|
|
259
|
+
segCol.classList.toggle('ring-primary', isSegActive);
|
|
260
|
+
alignCol.classList.toggle('ring-1', !isSegActive);
|
|
261
|
+
alignCol.classList.toggle('ring-secondary', !isSegActive);
|
|
262
|
+
|
|
263
|
+
// Opacity for inactive column
|
|
264
|
+
segCol.classList.toggle('opacity-70', !isSegActive);
|
|
265
|
+
alignCol.classList.toggle('opacity-70', isSegActive);
|
|
266
|
+
|
|
267
|
+
// Update hidden input
|
|
268
|
+
if (activeInput) {{
|
|
269
|
+
activeInput.value = isSegActive ? 'seg' : 'align';
|
|
270
|
+
}}
|
|
271
|
+
}}
|
|
272
|
+
|
|
273
|
+
// Global callback for ZoneManager (called on keyboard zone switch)
|
|
274
|
+
window.{ZONE_CHANGE_CALLBACK} = function(newZoneId, prevZoneId) {{
|
|
275
|
+
if (window.DEBUG_KB_SYSTEM) {{
|
|
276
|
+
console.log('[KB_SYSTEM] Zone change:', prevZoneId, '->', newZoneId);
|
|
277
|
+
}}
|
|
278
|
+
updateColumnStyles(newZoneId);
|
|
279
|
+
{chrome_swap_js}
|
|
280
|
+
}};
|
|
281
|
+
|
|
282
|
+
// Click handler for column focus switching
|
|
283
|
+
function handleColumnClick(targetZoneId) {{
|
|
284
|
+
// Skip if already active
|
|
285
|
+
const state = window.kbNav?.getState?.();
|
|
286
|
+
if (state && state.activeZoneId === targetZoneId) return;
|
|
287
|
+
|
|
288
|
+
// Skip if in split mode (don't allow accidental zone switch)
|
|
289
|
+
if (state && state.currentMode === 'split') return;
|
|
290
|
+
|
|
291
|
+
// Switch zone using keyboard navigation library API
|
|
292
|
+
if (window.kbNav?.setActiveZone) {{
|
|
293
|
+
window.kbNav.setActiveZone(targetZoneId);
|
|
294
|
+
}}
|
|
295
|
+
}}
|
|
296
|
+
|
|
297
|
+
// Set up click handlers on columns
|
|
298
|
+
function setupClickHandlers() {{
|
|
299
|
+
const segCol = document.getElementById(seg_col_id);
|
|
300
|
+
const alignCol = document.getElementById(align_col_id);
|
|
301
|
+
|
|
302
|
+
if (segCol) {{
|
|
303
|
+
segCol.addEventListener('mousedown', function(e) {{
|
|
304
|
+
handleColumnClick(seg_zone_id);
|
|
305
|
+
}});
|
|
306
|
+
}}
|
|
307
|
+
|
|
308
|
+
if (alignCol) {{
|
|
309
|
+
alignCol.addEventListener('mousedown', function(e) {{
|
|
310
|
+
handleColumnClick(align_zone_id);
|
|
311
|
+
}});
|
|
312
|
+
}}
|
|
313
|
+
}}
|
|
314
|
+
|
|
315
|
+
// Initial update (segmentation zone is active by default)
|
|
316
|
+
updateColumnStyles(seg_zone_id);
|
|
317
|
+
|
|
318
|
+
// Set up click handlers
|
|
319
|
+
setupClickHandlers();
|
|
320
|
+
}})();
|
|
321
|
+
"""
|
|
322
|
+
|
|
323
|
+
return Script(js_code)
|