cjm-transcript-segmentation 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.
@@ -0,0 +1 @@
1
+ __version__ = "0.0.1"
@@ -0,0 +1,150 @@
1
+ # Autogenerated by nbdev
2
+
3
+ d = { 'settings': { 'branch': 'main',
4
+ 'doc_baseurl': '/cjm-transcript-segmentation',
5
+ 'doc_host': 'https://cj-mills.github.io',
6
+ 'git_url': 'https://github.com/cj-mills/cjm-transcript-segmentation',
7
+ 'lib_path': 'cjm_transcript_segmentation'},
8
+ 'syms': { 'cjm_transcript_segmentation.components.callbacks': { 'cjm_transcript_segmentation.components.callbacks._generate_focus_change_script': ( 'components/callbacks.html#_generate_focus_change_script',
9
+ 'cjm_transcript_segmentation/components/callbacks.py'),
10
+ 'cjm_transcript_segmentation.components.callbacks.generate_seg_callbacks_script': ( 'components/callbacks.html#generate_seg_callbacks_script',
11
+ 'cjm_transcript_segmentation/components/callbacks.py')},
12
+ 'cjm_transcript_segmentation.components.card_stack_config': {},
13
+ 'cjm_transcript_segmentation.components.helpers': { 'cjm_transcript_segmentation.components.helpers._get_card_width': ( 'components/helpers.html#_get_card_width',
14
+ 'cjm_transcript_segmentation/components/helpers.py'),
15
+ 'cjm_transcript_segmentation.components.helpers._get_focused_index': ( 'components/helpers.html#_get_focused_index',
16
+ 'cjm_transcript_segmentation/components/helpers.py'),
17
+ 'cjm_transcript_segmentation.components.helpers._get_history': ( 'components/helpers.html#_get_history',
18
+ 'cjm_transcript_segmentation/components/helpers.py'),
19
+ 'cjm_transcript_segmentation.components.helpers._get_is_auto_mode': ( 'components/helpers.html#_get_is_auto_mode',
20
+ 'cjm_transcript_segmentation/components/helpers.py'),
21
+ 'cjm_transcript_segmentation.components.helpers._get_segmentation_state': ( 'components/helpers.html#_get_segmentation_state',
22
+ 'cjm_transcript_segmentation/components/helpers.py'),
23
+ 'cjm_transcript_segmentation.components.helpers._get_segments': ( 'components/helpers.html#_get_segments',
24
+ 'cjm_transcript_segmentation/components/helpers.py'),
25
+ 'cjm_transcript_segmentation.components.helpers._get_visible_count': ( 'components/helpers.html#_get_visible_count',
26
+ 'cjm_transcript_segmentation/components/helpers.py'),
27
+ 'cjm_transcript_segmentation.components.helpers._is_initialized': ( 'components/helpers.html#_is_initialized',
28
+ 'cjm_transcript_segmentation/components/helpers.py')},
29
+ 'cjm_transcript_segmentation.components.keyboard_config': { 'cjm_transcript_segmentation.components.keyboard_config.create_seg_kb_parts': ( 'components/keyboard_config.html#create_seg_kb_parts',
30
+ 'cjm_transcript_segmentation/components/keyboard_config.py')},
31
+ 'cjm_transcript_segmentation.components.segment_card': { 'cjm_transcript_segmentation.components.segment_card._render_card_actions': ( 'components/segment_card.html#_render_card_actions',
32
+ 'cjm_transcript_segmentation/components/segment_card.py'),
33
+ 'cjm_transcript_segmentation.components.segment_card._render_card_metadata': ( 'components/segment_card.html#_render_card_metadata',
34
+ 'cjm_transcript_segmentation/components/segment_card.py'),
35
+ 'cjm_transcript_segmentation.components.segment_card._render_split_mode_content': ( 'components/segment_card.html#_render_split_mode_content',
36
+ 'cjm_transcript_segmentation/components/segment_card.py'),
37
+ 'cjm_transcript_segmentation.components.segment_card._render_view_mode_content': ( 'components/segment_card.html#_render_view_mode_content',
38
+ 'cjm_transcript_segmentation/components/segment_card.py'),
39
+ 'cjm_transcript_segmentation.components.segment_card.create_segment_card_renderer': ( 'components/segment_card.html#create_segment_card_renderer',
40
+ 'cjm_transcript_segmentation/components/segment_card.py'),
41
+ 'cjm_transcript_segmentation.components.segment_card.render_segment_card': ( 'components/segment_card.html#render_segment_card',
42
+ 'cjm_transcript_segmentation/components/segment_card.py')},
43
+ 'cjm_transcript_segmentation.components.step_renderer': { 'cjm_transcript_segmentation.components.step_renderer.render_seg_column_body': ( 'components/step_renderer.html#render_seg_column_body',
44
+ 'cjm_transcript_segmentation/components/step_renderer.py'),
45
+ 'cjm_transcript_segmentation.components.step_renderer.render_seg_footer_content': ( 'components/step_renderer.html#render_seg_footer_content',
46
+ 'cjm_transcript_segmentation/components/step_renderer.py'),
47
+ 'cjm_transcript_segmentation.components.step_renderer.render_seg_mini_stats_text': ( 'components/step_renderer.html#render_seg_mini_stats_text',
48
+ 'cjm_transcript_segmentation/components/step_renderer.py'),
49
+ 'cjm_transcript_segmentation.components.step_renderer.render_seg_stats': ( 'components/step_renderer.html#render_seg_stats',
50
+ 'cjm_transcript_segmentation/components/step_renderer.py'),
51
+ 'cjm_transcript_segmentation.components.step_renderer.render_toolbar': ( 'components/step_renderer.html#render_toolbar',
52
+ 'cjm_transcript_segmentation/components/step_renderer.py')},
53
+ 'cjm_transcript_segmentation.html_ids': { 'cjm_transcript_segmentation.html_ids.SegmentationHtmlIds': ( 'html_ids.html#segmentationhtmlids',
54
+ 'cjm_transcript_segmentation/html_ids.py'),
55
+ 'cjm_transcript_segmentation.html_ids.SegmentationHtmlIds.as_selector': ( 'html_ids.html#segmentationhtmlids.as_selector',
56
+ 'cjm_transcript_segmentation/html_ids.py'),
57
+ 'cjm_transcript_segmentation.html_ids.SegmentationHtmlIds.segment_card': ( 'html_ids.html#segmentationhtmlids.segment_card',
58
+ 'cjm_transcript_segmentation/html_ids.py')},
59
+ 'cjm_transcript_segmentation.models': { 'cjm_transcript_segmentation.models.SegmentationStepState': ( 'models.html#segmentationstepstate',
60
+ 'cjm_transcript_segmentation/models.py'),
61
+ 'cjm_transcript_segmentation.models.SegmentationUrls': ( 'models.html#segmentationurls',
62
+ 'cjm_transcript_segmentation/models.py'),
63
+ 'cjm_transcript_segmentation.models.TextSegment': ( 'models.html#textsegment',
64
+ 'cjm_transcript_segmentation/models.py'),
65
+ 'cjm_transcript_segmentation.models.TextSegment.from_dict': ( 'models.html#textsegment.from_dict',
66
+ 'cjm_transcript_segmentation/models.py'),
67
+ 'cjm_transcript_segmentation.models.TextSegment.to_dict': ( 'models.html#textsegment.to_dict',
68
+ 'cjm_transcript_segmentation/models.py')},
69
+ 'cjm_transcript_segmentation.routes.card_stack': { 'cjm_transcript_segmentation.routes.card_stack._build_nav_response': ( 'routes/card_stack.html#_build_nav_response',
70
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
71
+ 'cjm_transcript_segmentation.routes.card_stack._build_slots_oob': ( 'routes/card_stack.html#_build_slots_oob',
72
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
73
+ 'cjm_transcript_segmentation.routes.card_stack._handle_seg_enter_split_mode': ( 'routes/card_stack.html#_handle_seg_enter_split_mode',
74
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
75
+ 'cjm_transcript_segmentation.routes.card_stack._handle_seg_exit_split_mode': ( 'routes/card_stack.html#_handle_seg_exit_split_mode',
76
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
77
+ 'cjm_transcript_segmentation.routes.card_stack._handle_seg_navigate': ( 'routes/card_stack.html#_handle_seg_navigate',
78
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
79
+ 'cjm_transcript_segmentation.routes.card_stack._handle_seg_save_width': ( 'routes/card_stack.html#_handle_seg_save_width',
80
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
81
+ 'cjm_transcript_segmentation.routes.card_stack._handle_seg_update_viewport': ( 'routes/card_stack.html#_handle_seg_update_viewport',
82
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
83
+ 'cjm_transcript_segmentation.routes.card_stack._make_renderer': ( 'routes/card_stack.html#_make_renderer',
84
+ 'cjm_transcript_segmentation/routes/card_stack.py'),
85
+ 'cjm_transcript_segmentation.routes.card_stack.init_card_stack_router': ( 'routes/card_stack.html#init_card_stack_router',
86
+ 'cjm_transcript_segmentation/routes/card_stack.py')},
87
+ 'cjm_transcript_segmentation.routes.core': { 'cjm_transcript_segmentation.routes.core.SegContext': ( 'routes/core.html#segcontext',
88
+ 'cjm_transcript_segmentation/routes/core.py'),
89
+ 'cjm_transcript_segmentation.routes.core._build_card_stack_state': ( 'routes/core.html#_build_card_stack_state',
90
+ 'cjm_transcript_segmentation/routes/core.py'),
91
+ 'cjm_transcript_segmentation.routes.core._get_seg_state': ( 'routes/core.html#_get_seg_state',
92
+ 'cjm_transcript_segmentation/routes/core.py'),
93
+ 'cjm_transcript_segmentation.routes.core._get_selection_state': ( 'routes/core.html#_get_selection_state',
94
+ 'cjm_transcript_segmentation/routes/core.py'),
95
+ 'cjm_transcript_segmentation.routes.core._load_seg_context': ( 'routes/core.html#_load_seg_context',
96
+ 'cjm_transcript_segmentation/routes/core.py'),
97
+ 'cjm_transcript_segmentation.routes.core._push_history': ( 'routes/core.html#_push_history',
98
+ 'cjm_transcript_segmentation/routes/core.py'),
99
+ 'cjm_transcript_segmentation.routes.core._to_segments': ( 'routes/core.html#_to_segments',
100
+ 'cjm_transcript_segmentation/routes/core.py'),
101
+ 'cjm_transcript_segmentation.routes.core._update_seg_state': ( 'routes/core.html#_update_seg_state',
102
+ 'cjm_transcript_segmentation/routes/core.py')},
103
+ 'cjm_transcript_segmentation.routes.handlers': { 'cjm_transcript_segmentation.routes.handlers.SegInitResult': ( 'routes/handlers.html#seginitresult',
104
+ 'cjm_transcript_segmentation/routes/handlers.py'),
105
+ 'cjm_transcript_segmentation.routes.handlers._build_mutation_response': ( 'routes/handlers.html#_build_mutation_response',
106
+ 'cjm_transcript_segmentation/routes/handlers.py'),
107
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_ai_split': ( 'routes/handlers.html#_handle_seg_ai_split',
108
+ 'cjm_transcript_segmentation/routes/handlers.py'),
109
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_init': ( 'routes/handlers.html#_handle_seg_init',
110
+ 'cjm_transcript_segmentation/routes/handlers.py'),
111
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_merge': ( 'routes/handlers.html#_handle_seg_merge',
112
+ 'cjm_transcript_segmentation/routes/handlers.py'),
113
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_reset': ( 'routes/handlers.html#_handle_seg_reset',
114
+ 'cjm_transcript_segmentation/routes/handlers.py'),
115
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_split': ( 'routes/handlers.html#_handle_seg_split',
116
+ 'cjm_transcript_segmentation/routes/handlers.py'),
117
+ 'cjm_transcript_segmentation.routes.handlers._handle_seg_undo': ( 'routes/handlers.html#_handle_seg_undo',
118
+ 'cjm_transcript_segmentation/routes/handlers.py'),
119
+ 'cjm_transcript_segmentation.routes.handlers.init_workflow_router': ( 'routes/handlers.html#init_workflow_router',
120
+ 'cjm_transcript_segmentation/routes/handlers.py')},
121
+ 'cjm_transcript_segmentation.routes.init': { 'cjm_transcript_segmentation.routes.init.init_segmentation_routers': ( 'routes/init.html#init_segmentation_routers',
122
+ 'cjm_transcript_segmentation/routes/init.py')},
123
+ 'cjm_transcript_segmentation.services.segmentation': { 'cjm_transcript_segmentation.services.segmentation.SegmentationService': ( 'services/segmentation.html#segmentationservice',
124
+ 'cjm_transcript_segmentation/services/segmentation.py'),
125
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.__init__': ( 'services/segmentation.html#segmentationservice.__init__',
126
+ 'cjm_transcript_segmentation/services/segmentation.py'),
127
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.ensure_loaded': ( 'services/segmentation.html#segmentationservice.ensure_loaded',
128
+ 'cjm_transcript_segmentation/services/segmentation.py'),
129
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.is_available': ( 'services/segmentation.html#segmentationservice.is_available',
130
+ 'cjm_transcript_segmentation/services/segmentation.py'),
131
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.split_combined_sources_async': ( 'services/segmentation.html#segmentationservice.split_combined_sources_async',
132
+ 'cjm_transcript_segmentation/services/segmentation.py'),
133
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.split_sentences': ( 'services/segmentation.html#segmentationservice.split_sentences',
134
+ 'cjm_transcript_segmentation/services/segmentation.py'),
135
+ 'cjm_transcript_segmentation.services.segmentation.SegmentationService.split_sentences_async': ( 'services/segmentation.html#segmentationservice.split_sentences_async',
136
+ 'cjm_transcript_segmentation/services/segmentation.py'),
137
+ 'cjm_transcript_segmentation.services.segmentation.merge_text_segments': ( 'services/segmentation.html#merge_text_segments',
138
+ 'cjm_transcript_segmentation/services/segmentation.py'),
139
+ 'cjm_transcript_segmentation.services.segmentation.reconstruct_source_blocks': ( 'services/segmentation.html#reconstruct_source_blocks',
140
+ 'cjm_transcript_segmentation/services/segmentation.py'),
141
+ 'cjm_transcript_segmentation.services.segmentation.reindex_segments': ( 'services/segmentation.html#reindex_segments',
142
+ 'cjm_transcript_segmentation/services/segmentation.py'),
143
+ 'cjm_transcript_segmentation.services.segmentation.split_segment_at_position': ( 'services/segmentation.html#split_segment_at_position',
144
+ 'cjm_transcript_segmentation/services/segmentation.py')},
145
+ 'cjm_transcript_segmentation.utils': { 'cjm_transcript_segmentation.utils.calculate_segment_stats': ( 'utils.html#calculate_segment_stats',
146
+ 'cjm_transcript_segmentation/utils.py'),
147
+ 'cjm_transcript_segmentation.utils.count_words': ( 'utils.html#count_words',
148
+ 'cjm_transcript_segmentation/utils.py'),
149
+ 'cjm_transcript_segmentation.utils.word_index_to_char_position': ( 'utils.html#word_index_to_char_position',
150
+ 'cjm_transcript_segmentation/utils.py')}}}
File without changes
@@ -0,0 +1,56 @@
1
+ """JavaScript callback generators for Phase 2 segmentation keyboard interaction"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/callbacks.ipynb.
4
+
5
+ # %% auto #0
6
+ __all__ = ['generate_seg_callbacks_script']
7
+
8
+ # %% ../../nbs/components/callbacks.ipynb #9c3ae2f7
9
+ from cjm_fasthtml_card_stack.core.config import CardStackConfig
10
+ from cjm_fasthtml_card_stack.core.html_ids import CardStackHtmlIds
11
+ from cjm_fasthtml_card_stack.core.button_ids import CardStackButtonIds
12
+ from cjm_fasthtml_card_stack.core.models import CardStackUrls
13
+ from cjm_fasthtml_card_stack.js.core import generate_card_stack_js
14
+
15
+ # %% ../../nbs/components/callbacks.ipynb #eee98aa2
16
+ def _generate_focus_change_script(
17
+ focus_input_id: str, # ID of hidden input for focused segment index
18
+ ) -> str: # JavaScript code for focus change callback
19
+ """Generate JavaScript for card focus change handling."""
20
+ return f"""
21
+ // Called when card focus changes (from keyboard navigation library)
22
+ window.onCardFocusChange = function(item, index, zoneId) {{
23
+ // Update hidden input with focused segment index
24
+ const input = document.getElementById('{focus_input_id}');
25
+ if (input && item) {{
26
+ input.value = item.dataset.segmentIndex || index;
27
+ }}
28
+ }};
29
+ """
30
+
31
+ # %% ../../nbs/components/callbacks.ipynb #328ed0e1
32
+ def generate_seg_callbacks_script(
33
+ ids:CardStackHtmlIds, # Card stack HTML IDs
34
+ button_ids:CardStackButtonIds, # Card stack button IDs
35
+ config:CardStackConfig, # Card stack configuration
36
+ urls:CardStackUrls, # Card stack URL bundle
37
+ container_id:str, # ID of the segmentation container (parent of card stack)
38
+ focus_input_id:str, # ID of hidden input for focused segment index
39
+ ) -> any: # Script element with all JavaScript callbacks
40
+ """Generate JavaScript for segmentation keyboard interaction.
41
+
42
+ Delegates card-stack-generic JS to the library and injects the
43
+ focus change callback via extra_scripts.
44
+ """
45
+ seg_scripts = (
46
+ _generate_focus_change_script(focus_input_id),
47
+ )
48
+
49
+ return generate_card_stack_js(
50
+ ids=ids,
51
+ button_ids=button_ids,
52
+ config=config,
53
+ urls=urls,
54
+ container_id=container_id,
55
+ extra_scripts=seg_scripts
56
+ )
@@ -0,0 +1,36 @@
1
+ """Card stack configuration constants for the Phase 2 segmentation UI"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/card_stack_config.ipynb.
4
+
5
+ # %% auto #0
6
+ __all__ = ['SEG_CS_CONFIG', 'SEG_CS_IDS', 'SEG_CS_BTN_IDS', 'SEG_TS_CONFIG', 'SEG_TS_IDS']
7
+
8
+ # %% ../../nbs/components/card_stack_config.ipynb #cs-cfg-constants
9
+ from cjm_fasthtml_card_stack.core.config import CardStackConfig, CardStackStyleConfig
10
+ from cjm_fasthtml_card_stack.core.html_ids import CardStackHtmlIds
11
+ from cjm_fasthtml_card_stack.core.button_ids import CardStackButtonIds
12
+
13
+ from cjm_fasthtml_token_selector.core.config import TokenSelectorConfig
14
+ from cjm_fasthtml_token_selector.core.html_ids import TokenSelectorHtmlIds
15
+
16
+ SEG_CS_CONFIG = CardStackConfig(
17
+ prefix="sd-seg",
18
+ disable_scroll_in_modes=("split",),
19
+ style=CardStackStyleConfig(
20
+ viewport_padding_x='0.0rem',
21
+ viewport_padding_y='0.0rem'
22
+ )
23
+ )
24
+
25
+ SEG_CS_IDS = CardStackHtmlIds(prefix=SEG_CS_CONFIG.prefix)
26
+ SEG_CS_BTN_IDS = CardStackButtonIds(prefix=SEG_CS_CONFIG.prefix)
27
+
28
+ SEG_TS_CONFIG = TokenSelectorConfig(
29
+ prefix="sd-seg-ts",
30
+ selection_mode="gap",
31
+ initial_delay=200,
32
+ repeat_interval=90,
33
+ throttle_floor=50,
34
+ )
35
+
36
+ SEG_TS_IDS = TokenSelectorHtmlIds(prefix=SEG_TS_CONFIG.prefix)
@@ -0,0 +1,83 @@
1
+ """Shared helper functions for the segmentation module"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/helpers.ipynb.
4
+
5
+ # %% auto #0
6
+ __all__ = []
7
+
8
+ # %% ../../nbs/components/helpers.ipynb #c3d4e5f6
9
+ from typing import Any, Dict, List
10
+
11
+ from cjm_fasthtml_interactions.core.context import InteractionContext
12
+
13
+ from cjm_transcript_segmentation.models import (
14
+ TextSegment, SegmentationStepState
15
+ )
16
+
17
+ # %% ../../nbs/components/helpers.ipynb #e5f6a7b8
18
+ def _get_segmentation_state(
19
+ ctx: InteractionContext # Interaction context with state
20
+ ) -> SegmentationStepState: # Typed segmentation step state
21
+ """Get the full segmentation step state from context."""
22
+ step_states = ctx.state.get("step_states", {})
23
+ return step_states.get("segmentation", {})
24
+
25
+ # %% ../../nbs/components/helpers.ipynb #rvxle78vfj
26
+ def _get_segments(
27
+ ctx: InteractionContext # Interaction context with state
28
+ ) -> List[TextSegment]: # List of TextSegment objects
29
+ """Get the list of segments from step state as TextSegment objects."""
30
+ state = _get_segmentation_state(ctx)
31
+ segment_dicts = state.get("segments", [])
32
+ return [TextSegment.from_dict(s) for s in segment_dicts]
33
+
34
+ # %% ../../nbs/components/helpers.ipynb #2dliq35ph
35
+ def _is_initialized(
36
+ ctx: InteractionContext # Interaction context with state
37
+ ) -> bool: # True if segments have been initialized
38
+ """Check if segments have been initialized."""
39
+ state = _get_segmentation_state(ctx)
40
+ return state.get("is_initialized", False)
41
+
42
+ # %% ../../nbs/components/helpers.ipynb #1zg9dsfg9za
43
+ def _get_visible_count(
44
+ ctx: InteractionContext, # Interaction context with state
45
+ default: int = 3, # Default visible card count
46
+ ) -> int: # Number of visible cards in viewport
47
+ """Get the stored visible card count."""
48
+ state = _get_segmentation_state(ctx)
49
+ return state.get("visible_count", default)
50
+
51
+ # %% ../../nbs/components/helpers.ipynb #ev9120vz98m
52
+ def _get_card_width(
53
+ ctx: InteractionContext, # Interaction context with state
54
+ default: int = 80, # Default card width in rem
55
+ ) -> int: # Card stack width in rem
56
+ """Get the stored card stack width."""
57
+ state = _get_segmentation_state(ctx)
58
+ return state.get("card_width", default)
59
+
60
+
61
+ #| export
62
+ def _get_is_auto_mode(
63
+ ctx: InteractionContext, # Interaction context with state
64
+ ) -> bool: # Whether card count is in auto-adjust mode
65
+ """Get whether the card count is in auto-adjust mode."""
66
+ state = _get_segmentation_state(ctx)
67
+ return state.get("is_auto_mode", False)
68
+
69
+ # %% ../../nbs/components/helpers.ipynb #5qlapc1birw
70
+ def _get_history(
71
+ ctx: InteractionContext # Interaction context with state
72
+ ) -> List[List[Dict[str, Any]]]: # Stack of segment snapshots
73
+ """Get the undo history stack."""
74
+ state = _get_segmentation_state(ctx)
75
+ return state.get("history", [])
76
+
77
+ # %% ../../nbs/components/helpers.ipynb #nnrf1g1wu5h
78
+ def _get_focused_index(
79
+ ctx: InteractionContext # Interaction context with state
80
+ ) -> int: # Currently focused segment index
81
+ """Get the currently focused segment index."""
82
+ state = _get_segmentation_state(ctx)
83
+ return state.get("focused_index", 0)
@@ -0,0 +1,165 @@
1
+ """Segmentation-specific keyboard actions, modes, and zone configuration"""
2
+
3
+ # AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/components/keyboard_config.ipynb.
4
+
5
+ # %% auto #0
6
+ __all__ = ['SD_SEG_ENTER_SPLIT_BTN', 'SD_SEG_EXIT_SPLIT_BTN', 'SD_SEG_SPLIT_BTN', 'SD_SEG_MERGE_BTN', 'SD_SEG_UNDO_BTN',
7
+ 'create_seg_kb_parts']
8
+
9
+ # %% ../../nbs/components/keyboard_config.ipynb #c3d4e5f6
10
+ from typing import Tuple
11
+
12
+ # Keyboard navigation library
13
+ from cjm_fasthtml_keyboard_navigation.core.actions import KeyAction
14
+ from cjm_fasthtml_keyboard_navigation.core.focus_zone import FocusZone
15
+
16
+ # Card stack library
17
+ from cjm_fasthtml_card_stack.core.config import CardStackConfig
18
+ from cjm_fasthtml_card_stack.core.html_ids import CardStackHtmlIds
19
+ from cjm_fasthtml_card_stack.core.button_ids import CardStackButtonIds
20
+ from cjm_fasthtml_card_stack.keyboard.actions import (
21
+ create_card_stack_focus_zone, create_card_stack_nav_actions,
22
+ )
23
+
24
+ # Token selector library
25
+ from cjm_fasthtml_token_selector.keyboard.actions import (
26
+ create_token_selector_mode, create_token_nav_actions,
27
+ )
28
+ from cjm_transcript_segmentation.components.card_stack_config import (
29
+ SEG_TS_CONFIG,
30
+ )
31
+
32
+ # %% ../../nbs/components/keyboard_config.ipynb #e5f6a7b8
33
+ # Button IDs for keyboard actions — segmentation operations (workflow-specific)
34
+ SD_SEG_ENTER_SPLIT_BTN = "sd-seg-enter-split-btn"
35
+ SD_SEG_EXIT_SPLIT_BTN = "sd-seg-exit-split-btn"
36
+ SD_SEG_SPLIT_BTN = "sd-seg-split-btn"
37
+ SD_SEG_MERGE_BTN = "sd-seg-merge-btn"
38
+ SD_SEG_UNDO_BTN = "sd-seg-undo-btn"
39
+
40
+ # %% ../../nbs/components/keyboard_config.ipynb #a7b8c9d0
41
+ def create_seg_kb_parts(
42
+ ids:CardStackHtmlIds, # Card stack HTML IDs
43
+ button_ids:CardStackButtonIds, # Card stack button IDs for navigation
44
+ config:CardStackConfig, # Card stack configuration
45
+ ) -> Tuple[FocusZone, tuple, tuple]: # (zone, actions, modes)
46
+ """Create segmentation-specific keyboard building blocks.
47
+
48
+ Returns a zone, actions tuple, and modes tuple for assembly into a shared
49
+ ZoneManager by the combined-level keyboard config.
50
+ """
51
+ # Card stack zone from library — no data_attributes needed since
52
+ # onCardFocusChange callback updates the card stack's hidden input directly
53
+ card_zone = create_card_stack_focus_zone(
54
+ ids=ids,
55
+ on_focus_change="onCardFocusChange",
56
+ )
57
+ zone_id = card_zone.id
58
+
59
+ # Card stack navigation actions from library (arrows, page jump, first/last, width)
60
+ nav_actions = create_card_stack_nav_actions(
61
+ zone_id=zone_id,
62
+ button_ids=button_ids,
63
+ config=config,
64
+ disable_in_modes=("split",),
65
+ )
66
+
67
+ # --- Token selector: split mode definition (library factory) ---
68
+ split_mode = create_token_selector_mode(
69
+ SEG_TS_CONFIG,
70
+ mode_name="split",
71
+ indicator_text="Split Mode",
72
+ exit_key="",
73
+ exit_on_zone_change=False,
74
+ )
75
+
76
+ # --- Token selector: Home/End navigation in split mode ---
77
+ token_nav_actions = create_token_nav_actions(
78
+ SEG_TS_CONFIG,
79
+ zone_id=zone_id,
80
+ mode_name="split",
81
+ )
82
+
83
+ # --- Consumer-specific: segmentation operation actions ---
84
+ # All seg actions are zone-restricted to prevent firing when alignment zone is active
85
+ seg_zone_ids = (zone_id,)
86
+
87
+ seg_actions = (
88
+ # Enter split mode (Enter or Space when NOT in split mode)
89
+ KeyAction(
90
+ key="Enter",
91
+ htmx_trigger=SD_SEG_ENTER_SPLIT_BTN,
92
+ zone_ids=seg_zone_ids,
93
+ mode_enter="split",
94
+ not_modes=("split",),
95
+ description="Enter split mode",
96
+ hint_group="Segmentation",
97
+ ),
98
+ KeyAction(
99
+ key=" ",
100
+ htmx_trigger=SD_SEG_ENTER_SPLIT_BTN,
101
+ zone_ids=seg_zone_ids,
102
+ mode_enter="split",
103
+ not_modes=("split",),
104
+ description="Enter split mode",
105
+ hint_group="Segmentation",
106
+ show_in_hints=False,
107
+ ),
108
+
109
+ # Execute split (Enter or Space when IN split mode)
110
+ KeyAction(
111
+ key="Enter",
112
+ htmx_trigger=SD_SEG_SPLIT_BTN,
113
+ zone_ids=seg_zone_ids,
114
+ mode_exit=True,
115
+ mode_names=("split",),
116
+ description="Split at caret",
117
+ hint_group="Split Mode",
118
+ ),
119
+ KeyAction(
120
+ key=" ",
121
+ htmx_trigger=SD_SEG_SPLIT_BTN,
122
+ zone_ids=seg_zone_ids,
123
+ mode_exit=True,
124
+ mode_names=("split",),
125
+ description="Split at caret",
126
+ hint_group="Split Mode",
127
+ show_in_hints=False,
128
+ ),
129
+
130
+ # Exit split mode (Escape when IN split mode)
131
+ KeyAction(
132
+ key="Escape",
133
+ htmx_trigger=SD_SEG_EXIT_SPLIT_BTN,
134
+ zone_ids=seg_zone_ids,
135
+ mode_exit=True,
136
+ mode_names=("split",),
137
+ description="Exit split mode",
138
+ hint_group="Split Mode",
139
+ ),
140
+
141
+ # Merge with previous (Backspace when NOT in split mode)
142
+ KeyAction(
143
+ key="Backspace",
144
+ htmx_trigger=SD_SEG_MERGE_BTN,
145
+ zone_ids=seg_zone_ids,
146
+ not_modes=("split",),
147
+ description="Merge with previous",
148
+ hint_group="Segmentation",
149
+ ),
150
+
151
+ # Undo (Ctrl+Z in any mode, but zone-restricted)
152
+ KeyAction(
153
+ key="z",
154
+ modifiers=frozenset({"ctrl"}),
155
+ htmx_trigger=SD_SEG_UNDO_BTN,
156
+ zone_ids=seg_zone_ids,
157
+ description="Undo",
158
+ hint_group="General",
159
+ ),
160
+ )
161
+
162
+ actions = (*nav_actions, *seg_actions, *token_nav_actions)
163
+ modes = (split_mode,)
164
+
165
+ return card_zone, actions, modes