collavre 0.21.0 → 0.23.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.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/app/assets/stylesheets/collavre/actiontext.css +251 -90
- data/app/assets/stylesheets/collavre/code_highlight.css +7 -201
- data/app/assets/stylesheets/collavre/comments_popup.css +169 -64
- data/app/assets/stylesheets/collavre/creatives.css +11 -2
- data/app/assets/stylesheets/collavre/modal_dialog.css +32 -0
- data/app/assets/stylesheets/collavre/popup.css +148 -0
- data/app/assets/stylesheets/collavre/tables.css +91 -0
- data/app/channels/collavre/agent_channel.rb +205 -0
- data/app/channels/collavre/inbox_badge_channel.rb +30 -0
- data/app/controllers/collavre/admin/integrations_controller.rb +16 -5
- data/app/controllers/collavre/api/v1/agents_controller.rb +777 -0
- data/app/controllers/collavre/api/v1/base_controller.rb +46 -0
- data/app/controllers/collavre/api/v1/mobile/agent_events_controller.rb +224 -0
- data/app/controllers/collavre/api/v1/mobile/base_controller.rb +95 -0
- data/app/controllers/collavre/api/v1/mobile/devices_controller.rb +31 -0
- data/app/controllers/collavre/api/v1/mobile/voice_commands_controller.rb +25 -0
- data/app/controllers/collavre/attachments_controller.rb +30 -2
- data/app/controllers/collavre/comments_controller.rb +1 -1
- data/app/controllers/collavre/creatives/attachments_controller.rb +79 -0
- data/app/controllers/collavre/creatives_controller.rb +107 -6
- data/app/controllers/collavre/tasks_controller.rb +21 -4
- data/app/controllers/collavre/topics_controller.rb +64 -1
- data/app/controllers/collavre/typo_corrections_controller.rb +39 -0
- data/app/controllers/concerns/collavre/comments/approval_actions.rb +57 -14
- data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +16 -1
- data/app/controllers/concerns/collavre/users_controller/registration.rb +41 -1
- data/app/helpers/collavre/application_helper.rb +1 -0
- data/app/javascript/collavre.js +2 -0
- data/app/javascript/components/ImageResizer.jsx +9 -3
- data/app/javascript/components/InlineLexicalEditor.jsx +196 -96
- data/app/javascript/components/creative_tree_row.js +20 -3
- data/app/javascript/components/plugins/attachment_cleanup_plugin.jsx +3 -0
- data/app/javascript/components/plugins/image_upload_plugin.jsx +12 -0
- data/app/javascript/components/plugins/list_tab_indent_plugin.jsx +16 -0
- data/app/javascript/components/plugins/table_hover_actions_plugin.jsx +405 -0
- data/app/javascript/controllers/__tests__/inbox_badge_controller.test.js +73 -0
- data/app/javascript/controllers/__tests__/link_creative_controller.test.js +447 -0
- data/app/javascript/controllers/comment_controller.js +11 -5
- data/app/javascript/controllers/comment_version_controller.js +2 -1
- data/app/javascript/controllers/comments/__tests__/form_controller_double_submit.test.js +159 -0
- data/app/javascript/controllers/comments/__tests__/presence_controller.test.js +111 -2
- data/app/javascript/controllers/comments/__tests__/topics_controller_delete.test.js +94 -0
- data/app/javascript/controllers/comments/form_controller.js +21 -5
- data/app/javascript/controllers/comments/list_controller.js +35 -19
- data/app/javascript/controllers/comments/presence_controller.js +58 -6
- data/app/javascript/controllers/comments/topics_controller.js +14 -8
- data/app/javascript/controllers/creatives/__tests__/tree_controller.test.js +150 -0
- data/app/javascript/controllers/creatives/import_controller.js +2 -1
- data/app/javascript/controllers/creatives/select_mode_controller.js +2 -1
- data/app/javascript/controllers/creatives/tree_controller.js +142 -1
- data/app/javascript/controllers/image_lightbox_controller.js +2 -1
- data/app/javascript/controllers/inbox_badge_controller.js +33 -0
- data/app/javascript/controllers/index.js +4 -1
- data/app/javascript/controllers/link_creative_controller.js +451 -29
- data/app/javascript/controllers/share_modal_controller.js +4 -3
- data/app/javascript/controllers/topic_search_controller.js +2 -1
- data/app/javascript/creatives/drag_drop/event_handlers.js +14 -5
- data/app/javascript/creatives/topic_move_members_popup.js +156 -0
- data/app/javascript/creatives/tree_renderer.js +11 -0
- data/app/javascript/lib/__tests__/turbo_confirm.test.js +81 -0
- data/app/javascript/lib/__tests__/typo_correction.test.js +192 -0
- data/app/javascript/lib/api/__tests__/api_error.test.js +96 -0
- data/app/javascript/lib/api/__tests__/queue_manager.test.js +88 -1
- data/app/javascript/lib/api/api_error.js +108 -0
- data/app/javascript/lib/api/creatives.js +13 -0
- data/app/javascript/lib/api/queue_manager.js +38 -4
- data/app/javascript/lib/common_popup.js +18 -5
- data/app/javascript/lib/editor/__tests__/code_edit_view_token_parity.test.js +121 -0
- data/app/javascript/lib/editor/__tests__/code_language_roundtrip.test.js +152 -0
- data/app/javascript/lib/editor/__tests__/code_languages.test.js +93 -0
- data/app/javascript/lib/editor/code_languages.js +173 -0
- data/app/javascript/lib/editor/code_token_theme.js +41 -0
- data/app/javascript/lib/lexical/__tests__/color_import.test.js +318 -0
- data/app/javascript/lib/lexical/__tests__/image_focus.test.js +139 -0
- data/app/javascript/lib/lexical/__tests__/list_tab_indent.test.js +633 -0
- data/app/javascript/lib/lexical/__tests__/markdown_serialize.test.js +627 -0
- data/app/javascript/lib/lexical/__tests__/minimize_html.test.js +278 -0
- data/app/javascript/lib/lexical/__tests__/selection_boundary.test.js +88 -0
- data/app/javascript/lib/lexical/__tests__/table_transformer.test.js +163 -0
- data/app/javascript/lib/lexical/__tests__/trailing_paragraph.test.js +104 -0
- data/app/javascript/lib/lexical/color_import.js +186 -0
- data/app/javascript/lib/lexical/list_tab_indent.js +210 -0
- data/app/javascript/lib/lexical/markdown_serialize.js +320 -0
- data/app/javascript/lib/lexical/minimize_html.js +182 -0
- data/app/javascript/lib/lexical/selection_boundary.js +58 -0
- data/app/javascript/lib/lexical/table_transformer.js +182 -0
- data/app/javascript/lib/lexical/trailing_paragraph.js +29 -0
- data/app/javascript/lib/lexical/video_node.jsx +96 -0
- data/app/javascript/lib/turbo_confirm.js +46 -0
- data/app/javascript/lib/typo_correction.js +146 -0
- data/app/javascript/lib/utils/__tests__/confirm_dialog.test.js +88 -0
- data/app/javascript/lib/utils/__tests__/dialog.test.js +92 -0
- data/app/javascript/lib/utils/__tests__/markdown.test.js +153 -0
- data/app/javascript/lib/utils/__tests__/sanitize_description.test.js +68 -0
- data/app/javascript/lib/utils/__tests__/table_download.test.js +93 -0
- data/app/javascript/lib/utils/confirm_dialog.js +10 -0
- data/app/javascript/lib/utils/dialog.js +300 -0
- data/app/javascript/lib/utils/markdown.js +154 -67
- data/app/javascript/lib/utils/sanitize_description.js +31 -0
- data/app/javascript/lib/utils/table_download.js +15 -0
- data/app/javascript/modules/__tests__/typo_corrector.test.js +365 -0
- data/app/javascript/modules/creative_row_editor.js +110 -70
- data/app/javascript/modules/export_to_markdown.js +2 -1
- data/app/javascript/modules/lexical_inline_editor.jsx +2 -1
- data/app/javascript/modules/slide_view.js +11 -2
- data/app/javascript/modules/typo_corrector.js +534 -0
- data/app/jobs/collavre/ai_agent_job.rb +92 -3
- data/app/jobs/collavre/cancel_offline_delegated_tasks_job.rb +134 -0
- data/app/jobs/collavre/claude_channel_presence_job.rb +91 -0
- data/app/jobs/collavre/compress_job.rb +6 -2
- data/app/models/collavre/agent_subscription.rb +52 -0
- data/app/models/collavre/comment/broadcastable.rb +46 -7
- data/app/models/collavre/comment/claude_channel_permission.rb +145 -0
- data/app/models/collavre/comment/notifiable.rb +14 -4
- data/app/models/collavre/comment.rb +124 -11
- data/app/models/collavre/creative/describable.rb +220 -4
- data/app/models/collavre/creative_share.rb +1 -0
- data/app/models/collavre/task.rb +49 -5
- data/app/models/collavre/topic.rb +5 -0
- data/app/models/collavre/user.rb +61 -1
- data/app/services/collavre/agent_session_abort.rb +28 -0
- data/app/services/collavre/ai_agent/claude_channel_adapter.rb +79 -0
- data/app/services/collavre/ai_agent/response_finalizer.rb +4 -2
- data/app/services/collavre/ai_agent_service.rb +68 -49
- data/app/services/collavre/ai_client.rb +28 -10
- data/app/services/collavre/attachment_backfill.rb +26 -0
- data/app/services/collavre/auto_theme_generator.rb +1 -1
- data/app/services/collavre/creatives/breadcrumb_resolver.rb +91 -0
- data/app/services/collavre/creatives/filter_pipeline.rb +26 -42
- data/app/services/collavre/creatives/filters/search_filter.rb +12 -2
- data/app/services/collavre/creatives/index_query.rb +195 -24
- data/app/services/collavre/creatives/permission_filter.rb +50 -0
- data/app/services/collavre/creatives/reveal_path_resolver.rb +118 -0
- data/app/services/collavre/creatives/tree_builder.rb +2 -1
- data/app/services/collavre/crons/recurring_task_arguments.rb +28 -0
- data/app/services/collavre/gemini_parent_recommender.rb +1 -1
- data/app/services/collavre/inbox_reply_service.rb +5 -0
- data/app/services/collavre/markdown_converter.rb +13 -3
- data/app/services/collavre/mobile/event_summarizer.rb +40 -0
- data/app/services/collavre/orchestration/agent_orchestrator.rb +33 -7
- data/app/services/collavre/orchestration/arbiter.rb +16 -0
- data/app/services/collavre/orchestration/matcher.rb +79 -4
- data/app/services/collavre/orchestration/policy_resolver.rb +4 -3
- data/app/services/collavre/orchestration/stuck_detector.rb +146 -19
- data/app/services/collavre/tools/creative_attach_files_service.rb +29 -63
- data/app/services/collavre/tools/creative_batch_service.rb +3 -2
- data/app/services/collavre/tools/creative_create_service.rb +8 -8
- data/app/services/collavre/tools/creative_remove_attachment_service.rb +7 -5
- data/app/services/collavre/tools/creative_update_service.rb +23 -8
- data/app/services/collavre/tools/cron_list_service.rb +1 -14
- data/app/services/collavre/topics/orphaned_cron_notifier.rb +68 -0
- data/app/services/collavre/typo_corrector.rb +188 -0
- data/app/views/collavre/admin/integrations/_category.html.erb +1 -1
- data/app/views/collavre/admin/integrations/_setting_row.html.erb +27 -11
- data/app/views/collavre/comments/_comment.html.erb +15 -1
- data/app/views/collavre/comments/_comments_popup.html.erb +18 -3
- data/app/views/collavre/creatives/_inline_edit_form.html.erb +1 -0
- data/app/views/collavre/creatives/_topic_move_members_modal.html.erb +42 -0
- data/app/views/collavre/creatives/index.html.erb +14 -1
- data/app/views/collavre/creatives/slide_view.html.erb +1 -1
- data/app/views/collavre/shared/_link_creative_modal.html.erb +6 -2
- data/app/views/collavre/users/show.html.erb +3 -0
- data/app/views/collavre/users/typo_correction.html.erb +50 -0
- data/app/views/layouts/collavre/slide.html.erb +1 -0
- data/config/locales/channels.en.yml +2 -0
- data/config/locales/channels.ko.yml +2 -0
- data/config/locales/claude_channel.en.yml +16 -0
- data/config/locales/claude_channel.ko.yml +16 -0
- data/config/locales/comments.en.yml +18 -0
- data/config/locales/comments.ko.yml +18 -0
- data/config/locales/creatives.en.yml +2 -0
- data/config/locales/creatives.ko.yml +2 -0
- data/config/locales/integrations.en.yml +13 -2
- data/config/locales/integrations.ko.yml +13 -2
- data/config/locales/mobile.en.yml +16 -0
- data/config/locales/mobile.ko.yml +16 -0
- data/config/locales/orchestration.en.yml +1 -0
- data/config/locales/orchestration.ko.yml +1 -0
- data/config/locales/users.en.yml +15 -0
- data/config/locales/users.ko.yml +15 -0
- data/config/routes.rb +25 -0
- data/db/migrate/20260609000000_drop_action_text_rich_texts.rb +20 -0
- data/db/migrate/20260609005000_add_session_id_to_topics.rb +16 -0
- data/db/migrate/20260609010000_create_agent_subscriptions.rb +19 -0
- data/db/migrate/20260609020000_add_last_seen_at_to_agent_subscriptions.rb +23 -0
- data/db/migrate/20260609030000_add_session_id_to_agent_subscriptions.rb +17 -0
- data/db/migrate/20260609190659_backfill_creative_files_into_description.rb +24 -0
- data/db/migrate/20260612000000_add_topic_concurrency_defer_to_comments.rb +38 -0
- data/db/migrate/20260617090000_add_typo_correction_settings_to_users.rb +18 -0
- data/db/seeds.rb +51 -0
- data/lib/collavre/engine.rb +0 -1
- data/lib/collavre/integration_settings/key_definition.rb +6 -0
- data/lib/collavre/integration_settings/registry.rb +7 -2
- data/lib/collavre/version.rb +1 -1
- data/lib/generators/collavre/install/install_generator.rb +1 -0
- metadata +85 -3
- data/app/services/collavre/openclaw_abort_service.rb +0 -45
- data/app/services/collavre/tools/description_normalizable.rb +0 -16
|
@@ -328,6 +328,13 @@ body.chat-fullscreen {
|
|
|
328
328
|
margin-top: 0.2em;
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
.comment-content img,
|
|
332
|
+
.comment-content video {
|
|
333
|
+
max-width: 100%;
|
|
334
|
+
height: auto;
|
|
335
|
+
border-radius: var(--radius-2);
|
|
336
|
+
}
|
|
337
|
+
|
|
331
338
|
.comment-content pre {
|
|
332
339
|
white-space: pre-wrap;
|
|
333
340
|
word-break: break-word;
|
|
@@ -360,67 +367,8 @@ body.chat-fullscreen {
|
|
|
360
367
|
margin: 0;
|
|
361
368
|
}
|
|
362
369
|
|
|
363
|
-
/* Table styling
|
|
364
|
-
.
|
|
365
|
-
border-collapse: collapse;
|
|
366
|
-
width: 100%;
|
|
367
|
-
font-size: 0.85em;
|
|
368
|
-
margin: 0;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.comment-content table th,
|
|
372
|
-
.comment-content table td {
|
|
373
|
-
border: 1px solid var(--color-border);
|
|
374
|
-
padding: 0.3em 0.6em;
|
|
375
|
-
text-align: left;
|
|
376
|
-
white-space: nowrap;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
.comment-content table th {
|
|
380
|
-
background: var(--color-section-bg);
|
|
381
|
-
font-weight: 600;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
.comment-content table tr:hover td {
|
|
385
|
-
background: color-mix(in srgb, var(--color-section-bg) 40%, transparent);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/* Table download wrapper */
|
|
389
|
-
.table-download-wrapper {
|
|
390
|
-
position: relative;
|
|
391
|
-
overflow-x: auto;
|
|
392
|
-
margin: 0.4em 0;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
.table-download-toolbar {
|
|
396
|
-
display: flex;
|
|
397
|
-
justify-content: flex-end;
|
|
398
|
-
gap: 0.3em;
|
|
399
|
-
padding: 0.15em 0;
|
|
400
|
-
opacity: 0;
|
|
401
|
-
transition: opacity 0.15s ease;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
.table-download-wrapper:hover .table-download-toolbar {
|
|
405
|
-
opacity: 1;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.table-download-btn {
|
|
409
|
-
background: none;
|
|
410
|
-
border: 1px solid var(--color-border);
|
|
411
|
-
border-radius: var(--radius-2);
|
|
412
|
-
color: var(--color-muted);
|
|
413
|
-
font-size: 0.75em;
|
|
414
|
-
padding: 0.15em 0.5em;
|
|
415
|
-
cursor: pointer;
|
|
416
|
-
line-height: 1.4;
|
|
417
|
-
transition: color 0.15s ease, border-color 0.15s ease;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
.table-download-btn:hover {
|
|
421
|
-
color: var(--color-active);
|
|
422
|
-
border-color: var(--color-active);
|
|
423
|
-
}
|
|
370
|
+
/* Table + download-toolbar styling moved to collavre/tables.css (shared with
|
|
371
|
+
creative description tables). Load 'collavre/tables' alongside this file. */
|
|
424
372
|
|
|
425
373
|
/* Quote indicator in form */
|
|
426
374
|
.comment-quote-indicator {
|
|
@@ -806,7 +754,8 @@ body.chat-fullscreen {
|
|
|
806
754
|
}
|
|
807
755
|
|
|
808
756
|
.edit-comment-action-btn,
|
|
809
|
-
.approve-comment-btn
|
|
757
|
+
.approve-comment-btn,
|
|
758
|
+
.deny-comment-btn {
|
|
810
759
|
padding: 0.15em 0.4em;
|
|
811
760
|
border-radius: var(--radius-2);
|
|
812
761
|
font-size: 0.75rem;
|
|
@@ -836,6 +785,18 @@ body.chat-fullscreen {
|
|
|
836
785
|
border-color: var(--color-success);
|
|
837
786
|
}
|
|
838
787
|
|
|
788
|
+
.deny-comment-btn {
|
|
789
|
+
border: 1px solid color-mix(in srgb, var(--color-danger) 35%, transparent);
|
|
790
|
+
background: color-mix(in srgb, var(--color-danger) 15%, transparent);
|
|
791
|
+
color: var(--color-danger);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.deny-comment-btn:hover {
|
|
795
|
+
background: var(--color-danger);
|
|
796
|
+
color: var(--text-on-badge);
|
|
797
|
+
border-color: var(--color-danger);
|
|
798
|
+
}
|
|
799
|
+
|
|
839
800
|
.comment-status-label {
|
|
840
801
|
margin-left: 0.4em;
|
|
841
802
|
font-size: 0.75em;
|
|
@@ -858,6 +819,11 @@ body.chat-fullscreen {
|
|
|
858
819
|
color: var(--color-complete);
|
|
859
820
|
}
|
|
860
821
|
|
|
822
|
+
.comment-status-label.denied-label {
|
|
823
|
+
background-color: color-mix(in srgb, var(--color-danger) 20%, transparent);
|
|
824
|
+
color: var(--color-danger);
|
|
825
|
+
}
|
|
826
|
+
|
|
861
827
|
.comment-status-label.pending-label {
|
|
862
828
|
background-color: color-mix(in srgb, var(--color-warning) 20%, transparent);
|
|
863
829
|
color: var(--color-warning);
|
|
@@ -1111,6 +1077,34 @@ body.chat-fullscreen {
|
|
|
1111
1077
|
gap: var(--space-1);
|
|
1112
1078
|
}
|
|
1113
1079
|
|
|
1080
|
+
/* Horizontally-scrollable viewport for channel chips + typing indicator.
|
|
1081
|
+
Keeps PR/Preview badges and live typing on a single line so they never
|
|
1082
|
+
wrap and push the form down. The scroll-prev button stays pinned at the
|
|
1083
|
+
left because it is a flex sibling of (not inside) this viewport.
|
|
1084
|
+
min-width:0 lets this flex child shrink below its content width, which is
|
|
1085
|
+
what actually enables overflow scrolling. */
|
|
1086
|
+
#typing-scroll-viewport {
|
|
1087
|
+
flex: 1;
|
|
1088
|
+
min-width: 0;
|
|
1089
|
+
display: flex;
|
|
1090
|
+
align-items: center;
|
|
1091
|
+
gap: var(--space-1);
|
|
1092
|
+
flex-wrap: nowrap;
|
|
1093
|
+
overflow-x: auto;
|
|
1094
|
+
overflow-y: hidden;
|
|
1095
|
+
scrollbar-width: thin;
|
|
1096
|
+
scroll-behavior: smooth;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
#typing-scroll-viewport::-webkit-scrollbar {
|
|
1100
|
+
height: 4px;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
#typing-scroll-viewport::-webkit-scrollbar-thumb {
|
|
1104
|
+
background: var(--border-color);
|
|
1105
|
+
border-radius: var(--radius-2);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1114
1108
|
.scroll-prev-msg-btn {
|
|
1115
1109
|
background: none;
|
|
1116
1110
|
border: 1px solid var(--border-color);
|
|
@@ -1131,10 +1125,11 @@ body.chat-fullscreen {
|
|
|
1131
1125
|
|
|
1132
1126
|
#typing-indicator {
|
|
1133
1127
|
font-style: italic;
|
|
1134
|
-
flex:
|
|
1128
|
+
flex: 0 0 auto;
|
|
1135
1129
|
min-height: var(--space-px-5);
|
|
1136
1130
|
display: flex;
|
|
1137
1131
|
align-items: center;
|
|
1132
|
+
white-space: nowrap;
|
|
1138
1133
|
}
|
|
1139
1134
|
|
|
1140
1135
|
#typing-indicator .avatar-wrapper {
|
|
@@ -1188,7 +1183,8 @@ body.chat-fullscreen {
|
|
|
1188
1183
|
#channel-chips-container,
|
|
1189
1184
|
.channel-chips {
|
|
1190
1185
|
display: inline-flex;
|
|
1191
|
-
flex-wrap:
|
|
1186
|
+
flex-wrap: nowrap;
|
|
1187
|
+
flex-shrink: 0;
|
|
1192
1188
|
gap: var(--space-1);
|
|
1193
1189
|
align-items: center;
|
|
1194
1190
|
}
|
|
@@ -1941,3 +1937,112 @@ body.chat-fullscreen {
|
|
|
1941
1937
|
li:hover .topic-create-option {
|
|
1942
1938
|
text-decoration: underline;
|
|
1943
1939
|
}
|
|
1940
|
+
|
|
1941
|
+
/* ── Inline typo correction (volatile overlay; never serialized) ───────────── */
|
|
1942
|
+
/* The backdrop mirrors the textarea text exactly and paints <mark> spans over
|
|
1943
|
+
it. The backdrop sits ON TOP of the textarea (higher z-index) but is
|
|
1944
|
+
pointer-events:none, so clicks pass through to the textarea everywhere EXCEPT
|
|
1945
|
+
over a <mark> (pointer-events:auto) — that's what makes the marks clickable.
|
|
1946
|
+
If the textarea were on top, the browser would hit-test it first and the mark
|
|
1947
|
+
click handlers would never fire. The backdrop's text is transparent, so the
|
|
1948
|
+
textarea's real (opaque) glyphs show through and only the underlines paint. */
|
|
1949
|
+
.typo-input-wrap {
|
|
1950
|
+
position: relative;
|
|
1951
|
+
display: block;
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
.typo-input-wrap > textarea {
|
|
1955
|
+
position: relative;
|
|
1956
|
+
background: transparent;
|
|
1957
|
+
z-index: 0;
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
.typo-backdrop {
|
|
1961
|
+
position: absolute;
|
|
1962
|
+
inset: 0;
|
|
1963
|
+
overflow: hidden;
|
|
1964
|
+
pointer-events: none;
|
|
1965
|
+
z-index: 1;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
.typo-highlights {
|
|
1969
|
+
margin: 0;
|
|
1970
|
+
color: transparent;
|
|
1971
|
+
white-space: pre-wrap;
|
|
1972
|
+
overflow-wrap: break-word;
|
|
1973
|
+
word-break: break-word;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
/* Two states, distinguished by BOTH shape and colour (colour-blind safe). */
|
|
1977
|
+
.typo-mark {
|
|
1978
|
+
background: transparent;
|
|
1979
|
+
color: transparent;
|
|
1980
|
+
pointer-events: auto;
|
|
1981
|
+
cursor: pointer;
|
|
1982
|
+
border-radius: 2px;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
/* Auto-applied (>= threshold): faint straight underline — resolved, dim. */
|
|
1986
|
+
.typo-mark-applied {
|
|
1987
|
+
text-decoration: underline solid var(--color-link);
|
|
1988
|
+
text-decoration-thickness: 1px;
|
|
1989
|
+
text-underline-offset: 2px;
|
|
1990
|
+
opacity: 0.55;
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
/* Candidate (< threshold): wavy dotted amber underline — needs a decision. */
|
|
1994
|
+
.typo-mark-candidate {
|
|
1995
|
+
text-decoration: underline wavy var(--color-warning);
|
|
1996
|
+
text-decoration-thickness: 1px;
|
|
1997
|
+
text-underline-offset: 2px;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
/* Creatable combobox reusing CommonPopup positioning. */
|
|
2001
|
+
.typo-popup {
|
|
2002
|
+
position: absolute;
|
|
2003
|
+
z-index: 100000;
|
|
2004
|
+
min-width: 180px;
|
|
2005
|
+
max-width: 320px;
|
|
2006
|
+
background: var(--surface-section);
|
|
2007
|
+
border: 1px solid var(--border-color);
|
|
2008
|
+
border-radius: 8px;
|
|
2009
|
+
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
|
|
2010
|
+
padding: 6px;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
.typo-popup-input {
|
|
2014
|
+
width: 100%;
|
|
2015
|
+
box-sizing: border-box;
|
|
2016
|
+
padding: 6px 8px;
|
|
2017
|
+
border: 1px solid var(--border-color);
|
|
2018
|
+
border-radius: 6px;
|
|
2019
|
+
font: inherit;
|
|
2020
|
+
margin-bottom: 6px;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
.typo-popup-list {
|
|
2024
|
+
list-style: none;
|
|
2025
|
+
margin: 0;
|
|
2026
|
+
padding: 0;
|
|
2027
|
+
max-height: 200px;
|
|
2028
|
+
overflow-y: auto;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
.typo-popup-list .common-popup-item {
|
|
2032
|
+
padding: 6px 8px;
|
|
2033
|
+
border-radius: 6px;
|
|
2034
|
+
cursor: pointer;
|
|
2035
|
+
display: flex;
|
|
2036
|
+
justify-content: space-between;
|
|
2037
|
+
gap: 8px;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
.typo-popup-list .common-popup-item.active,
|
|
2041
|
+
.typo-popup-list .common-popup-item:hover {
|
|
2042
|
+
background: var(--surface-hover);
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
.typo-popup-role {
|
|
2046
|
+
color: var(--text-muted);
|
|
2047
|
+
font-size: 0.85em;
|
|
2048
|
+
}
|
|
@@ -257,14 +257,23 @@ creative-tree-row.show-edit .creative-row {
|
|
|
257
257
|
word-break: break-word;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
/* Allow attachments and
|
|
260
|
+
/* Allow attachments, images, and videos to be interactive independently of the
|
|
261
|
+
parent link. Without pointer-events on the video, the clickable creative row
|
|
262
|
+
would swallow clicks on the native playback controls (play/pause/fullscreen). */
|
|
261
263
|
.creative-content a[download],
|
|
262
|
-
.creative-content img
|
|
264
|
+
.creative-content img,
|
|
265
|
+
.creative-content video {
|
|
263
266
|
pointer-events: auto;
|
|
264
267
|
position: relative;
|
|
265
268
|
z-index: var(--layer-1);
|
|
266
269
|
}
|
|
267
270
|
|
|
271
|
+
.creative-content video {
|
|
272
|
+
max-width: 100%;
|
|
273
|
+
height: auto;
|
|
274
|
+
border-radius: var(--radius-2);
|
|
275
|
+
}
|
|
276
|
+
|
|
268
277
|
.creative-row:hover .creative-content {
|
|
269
278
|
cursor: pointer;
|
|
270
279
|
}
|
|
@@ -32,6 +32,17 @@
|
|
|
32
32
|
to { opacity: 1; }
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/* Top-layer dialogs (alert/confirm/prompt rendered as <dialog>.showModal())
|
|
36
|
+
* use the native ::backdrop instead of the .modal-dialog-overlay div, so the
|
|
37
|
+
* backdrop covers everything below — including other top-layer surfaces such
|
|
38
|
+
* as the image lightbox. Only matches real <dialog> elements; the <div>
|
|
39
|
+
* consumers of .modal-dialog never get a ::backdrop. */
|
|
40
|
+
dialog.modal-dialog::backdrop {
|
|
41
|
+
background: rgba(0, 0, 0, 0.5);
|
|
42
|
+
backdrop-filter: blur(4px);
|
|
43
|
+
-webkit-backdrop-filter: blur(4px);
|
|
44
|
+
}
|
|
45
|
+
|
|
35
46
|
/* ── Panel ── */
|
|
36
47
|
.modal-dialog {
|
|
37
48
|
display: none;
|
|
@@ -180,6 +191,27 @@ textarea.modal-dialog-input {
|
|
|
180
191
|
opacity: 0.9;
|
|
181
192
|
}
|
|
182
193
|
|
|
194
|
+
/* Destructive confirm action (delete/unlink). Matches .btn-danger convention. */
|
|
195
|
+
.modal-dialog-btn-danger {
|
|
196
|
+
background: var(--color-danger);
|
|
197
|
+
color: var(--text-on-badge);
|
|
198
|
+
border-color: var(--color-danger);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.modal-dialog-btn-danger:hover {
|
|
202
|
+
opacity: 0.9;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* ── Confirm dialog message ──
|
|
206
|
+
* pre-wrap preserves the \n line breaks that native confirm() honored. */
|
|
207
|
+
.confirm-dialog-message {
|
|
208
|
+
white-space: pre-wrap;
|
|
209
|
+
overflow-wrap: break-word;
|
|
210
|
+
color: var(--text-primary);
|
|
211
|
+
font-size: var(--text-1);
|
|
212
|
+
line-height: var(--leading-3, 1.5);
|
|
213
|
+
}
|
|
214
|
+
|
|
183
215
|
/* ── Footer hints (keyboard shortcuts) ── */
|
|
184
216
|
.modal-dialog-hints {
|
|
185
217
|
display: flex;
|
|
@@ -396,3 +396,151 @@ a.popup-menu-item:hover {
|
|
|
396
396
|
min-width: 100%;
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
|
+
|
|
400
|
+
/* ── Link-creative picker: mini-tree + flat search results ── */
|
|
401
|
+
.link-creative-list {
|
|
402
|
+
list-style: none;
|
|
403
|
+
margin: 0;
|
|
404
|
+
padding: 0;
|
|
405
|
+
max-height: 320px;
|
|
406
|
+
overflow-y: auto;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* Tree (browse) rows */
|
|
410
|
+
.link-tree-item {
|
|
411
|
+
list-style: none;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.link-tree-children {
|
|
415
|
+
list-style: none;
|
|
416
|
+
margin: 0;
|
|
417
|
+
padding: 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.link-tree-row {
|
|
421
|
+
display: flex;
|
|
422
|
+
align-items: center;
|
|
423
|
+
gap: 0.35em;
|
|
424
|
+
padding: 0.3em 0.5em;
|
|
425
|
+
border-radius: var(--radius-1);
|
|
426
|
+
cursor: pointer;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.link-tree-row:hover,
|
|
430
|
+
.link-tree-row.active {
|
|
431
|
+
background: var(--surface-hover);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.link-tree-toggle {
|
|
435
|
+
flex: 0 0 auto;
|
|
436
|
+
width: 1.75em;
|
|
437
|
+
height: 1.75em;
|
|
438
|
+
display: inline-flex;
|
|
439
|
+
align-items: center;
|
|
440
|
+
justify-content: center;
|
|
441
|
+
background: transparent;
|
|
442
|
+
border: none;
|
|
443
|
+
border-radius: var(--radius-1);
|
|
444
|
+
padding: 0;
|
|
445
|
+
line-height: 1;
|
|
446
|
+
color: var(--text-secondary);
|
|
447
|
+
cursor: pointer;
|
|
448
|
+
appearance: none;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.link-tree-toggle svg {
|
|
452
|
+
display: block;
|
|
453
|
+
width: 16px;
|
|
454
|
+
height: 16px;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.link-tree-toggle:hover {
|
|
458
|
+
color: var(--text-primary);
|
|
459
|
+
background: var(--surface-hover);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.link-tree-toggle-empty {
|
|
463
|
+
visibility: hidden;
|
|
464
|
+
cursor: default;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.link-tree-label {
|
|
468
|
+
flex: 1 1 auto;
|
|
469
|
+
min-width: 0;
|
|
470
|
+
overflow: hidden;
|
|
471
|
+
text-overflow: ellipsis;
|
|
472
|
+
white-space: nowrap;
|
|
473
|
+
color: var(--text-primary);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.link-tree-loading,
|
|
477
|
+
.link-tree-empty,
|
|
478
|
+
.link-popup-message {
|
|
479
|
+
list-style: none;
|
|
480
|
+
padding: 0.35em 0.6em;
|
|
481
|
+
color: var(--text-muted);
|
|
482
|
+
font-size: var(--text-0);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/* Flat search results with breadcrumb */
|
|
486
|
+
.link-result-item {
|
|
487
|
+
list-style: none;
|
|
488
|
+
padding: 0.4em 0.5em;
|
|
489
|
+
border-radius: var(--radius-1);
|
|
490
|
+
cursor: pointer;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.link-result-item:hover,
|
|
494
|
+
.link-result-item.active {
|
|
495
|
+
background: var(--surface-hover);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.link-result-label {
|
|
499
|
+
color: var(--text-primary);
|
|
500
|
+
overflow: hidden;
|
|
501
|
+
text-overflow: ellipsis;
|
|
502
|
+
white-space: nowrap;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.link-result-path {
|
|
506
|
+
display: flex;
|
|
507
|
+
flex-wrap: wrap;
|
|
508
|
+
align-items: center;
|
|
509
|
+
gap: 0.15em;
|
|
510
|
+
margin-top: 0.15em;
|
|
511
|
+
font-size: var(--text-00);
|
|
512
|
+
color: var(--text-muted);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.link-crumb {
|
|
516
|
+
background: transparent;
|
|
517
|
+
border: none;
|
|
518
|
+
padding: 0 0.1em;
|
|
519
|
+
font-size: inherit;
|
|
520
|
+
color: var(--text-muted);
|
|
521
|
+
cursor: pointer;
|
|
522
|
+
appearance: none;
|
|
523
|
+
max-width: 14ch;
|
|
524
|
+
overflow: hidden;
|
|
525
|
+
text-overflow: ellipsis;
|
|
526
|
+
white-space: nowrap;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.link-crumb:hover {
|
|
530
|
+
color: var(--color-link);
|
|
531
|
+
text-decoration: underline;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
.link-crumb-sep {
|
|
535
|
+
color: var(--text-muted);
|
|
536
|
+
opacity: 0.6;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.link-crumb-restricted {
|
|
540
|
+
cursor: default;
|
|
541
|
+
opacity: 0.6;
|
|
542
|
+
}
|
|
543
|
+
.link-crumb-restricted:hover {
|
|
544
|
+
color: var(--text-muted);
|
|
545
|
+
text-decoration: none;
|
|
546
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Shared markdown table styling + CSV/Excel download toolbar.
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth so chat-message tables (.comment-content) and creative
|
|
5
|
+
* description tables (.creative-content / .creative-title-content) render
|
|
6
|
+
* identically and both expose the same top-right download buttons. The download
|
|
7
|
+
* toolbar markup is produced by lib/utils/table_download.js.
|
|
8
|
+
*
|
|
9
|
+
* Load this wherever either context renders: the creatives index, the slide
|
|
10
|
+
* layout, and any page that shows the comments popup.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* Table styling */
|
|
14
|
+
.comment-content table,
|
|
15
|
+
.creative-content table,
|
|
16
|
+
.creative-title-content table {
|
|
17
|
+
border-collapse: collapse;
|
|
18
|
+
width: 100%;
|
|
19
|
+
font-size: 0.85em;
|
|
20
|
+
margin: 0;
|
|
21
|
+
/* Override legacy actiontext.css fixed layout so creative tables expand to
|
|
22
|
+
content and horizontally scroll like chat tables (tables.css loads after
|
|
23
|
+
actiontext.css; same specificity, so it must restate this property). */
|
|
24
|
+
table-layout: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.comment-content table th,
|
|
28
|
+
.comment-content table td,
|
|
29
|
+
.creative-content table th,
|
|
30
|
+
.creative-content table td,
|
|
31
|
+
.creative-title-content table th,
|
|
32
|
+
.creative-title-content table td {
|
|
33
|
+
border: 1px solid var(--color-border);
|
|
34
|
+
padding: 0.3em 0.6em;
|
|
35
|
+
text-align: left;
|
|
36
|
+
white-space: nowrap;
|
|
37
|
+
/* Clear actiontext.css cell floors so creative cells size to content like
|
|
38
|
+
chat cells instead of forcing a min width / breaking long words. */
|
|
39
|
+
min-width: 0;
|
|
40
|
+
word-break: normal;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.comment-content table th,
|
|
44
|
+
.creative-content table th,
|
|
45
|
+
.creative-title-content table th {
|
|
46
|
+
background: var(--color-section-bg);
|
|
47
|
+
font-weight: 600;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.comment-content table tr:hover td,
|
|
51
|
+
.creative-content table tr:hover td,
|
|
52
|
+
.creative-title-content table tr:hover td {
|
|
53
|
+
background: color-mix(in srgb, var(--color-section-bg) 40%, transparent);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Table download wrapper */
|
|
57
|
+
.table-download-wrapper {
|
|
58
|
+
position: relative;
|
|
59
|
+
overflow-x: auto;
|
|
60
|
+
margin: 0.4em 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.table-download-toolbar {
|
|
64
|
+
display: flex;
|
|
65
|
+
justify-content: flex-end;
|
|
66
|
+
gap: 0.3em;
|
|
67
|
+
padding: 0.15em 0;
|
|
68
|
+
opacity: 0;
|
|
69
|
+
transition: opacity 0.15s ease;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.table-download-wrapper:hover .table-download-toolbar {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.table-download-btn {
|
|
77
|
+
background: none;
|
|
78
|
+
border: 1px solid var(--color-border);
|
|
79
|
+
border-radius: var(--radius-2);
|
|
80
|
+
color: var(--color-muted);
|
|
81
|
+
font-size: 0.75em;
|
|
82
|
+
padding: 0.15em 0.5em;
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
line-height: 1.4;
|
|
85
|
+
transition: color 0.15s ease, border-color 0.15s ease;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.table-download-btn:hover {
|
|
89
|
+
color: var(--color-active);
|
|
90
|
+
border-color: var(--color-active);
|
|
91
|
+
}
|