@emberai-engg/task-board 0.4.1 → 0.5.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 CHANGED
@@ -101,8 +101,13 @@ the consumer owns navigation.
101
101
  active/completed filter, per-thread title and complete/reopen, thread
102
102
  composer with attachments and public/internal toggle
103
103
  - **Highlight-to-comment** — select text in a description section to attach a
104
- thread anchor; clicking the anchor pill scrolls back to the section and
105
- pulses it
104
+ thread anchor; the source text stays wrapped in a yellow `<mark>` so you
105
+ can see where threads attach. Clicking the mark (or the anchor pill on a
106
+ thread card) scrolls back to the section and pulses the highlight.
107
+ - **Edit + delete on messages and threads** — hover a message you wrote in a
108
+ thread for an Edit / Delete kebab. The thread-detail header has its own
109
+ kebab (Edit title + Delete thread). Deleting a thread cascades to its
110
+ replies on the backend.
106
111
 
107
112
  ## Props / Config Reference
108
113
 
package/dist/index.d.mts CHANGED
@@ -363,8 +363,12 @@ interface MentionTextareaProps {
363
363
  rows?: number;
364
364
  className?: string;
365
365
  disabled?: boolean;
366
+ /** Focus the underlying textarea on mount. Use for composers that should be
367
+ * immediately writable (e.g. when the user opens the new-thread composer
368
+ * from a highlight-to-comment selection). */
369
+ autoFocus?: boolean;
366
370
  }
367
- declare function MentionTextarea({ value, onChange, onKeyDown, placeholder, rows, className, disabled, }: MentionTextareaProps): react_jsx_runtime.JSX.Element;
371
+ declare function MentionTextarea({ value, onChange, onKeyDown, placeholder, rows, className, disabled, autoFocus, }: MentionTextareaProps): react_jsx_runtime.JSX.Element;
368
372
 
369
373
  declare function SkeletonPulse({ className }: {
370
374
  className?: string;
@@ -433,6 +437,13 @@ interface DescriptionSectionProps {
433
437
  onStatusChange: (next: SectionStatus) => void;
434
438
  /** Optional saving indicator passed through to the editor. */
435
439
  saving?: boolean;
440
+ /** Threads anchored to this section — drives the inline `<mark>` highlights. */
441
+ anchors?: Array<{
442
+ snippet: string;
443
+ threadId: string;
444
+ }>;
445
+ /** Click handler when the user clicks on a highlighted snippet. */
446
+ onAnchorClick?: (threadId: string) => void;
436
447
  }
437
448
  /**
438
449
  * One free-text description section (Problem / User Story / etc.) with:
@@ -440,8 +451,10 @@ interface DescriptionSectionProps {
440
451
  * - read-mode `MarkdownView`
441
452
  * - click-to-focus WYSIWYG `MarkdownEditor`
442
453
  * - `data-section={sectionKey}` so highlight-to-comment can anchor here
454
+ * - inline `<mark class="eb-tb-annot">` wrapping each anchor's snippet
455
+ * (clicking the mark opens that thread in the right panel)
443
456
  */
444
- declare function DescriptionSection({ sectionKey, label, placeholder, value, onChange, status, onStatusChange, saving, }: DescriptionSectionProps): react_jsx_runtime.JSX.Element;
457
+ declare function DescriptionSection({ sectionKey, label, placeholder, value, onChange, status, onStatusChange, saving, anchors, onAnchorClick, }: DescriptionSectionProps): react_jsx_runtime.JSX.Element;
445
458
 
446
459
  /**
447
460
  * Lightweight read-mode markdown renderer for description sections, thread
@@ -536,6 +549,8 @@ interface Thread {
536
549
  status: ThreadStatus;
537
550
  /** Original mention-tagged text, used when rendering the message. */
538
551
  rawContent: string;
552
+ /** Whether the thread root has been edited at least once. */
553
+ edited?: boolean;
539
554
  anchor?: ThreadAnchor | null;
540
555
  attachments: Attachment[];
541
556
  replies: ThreadReply[];
@@ -547,6 +562,7 @@ interface ThreadReply {
547
562
  content: string;
548
563
  created_at: string;
549
564
  is_internal: boolean;
565
+ edited?: boolean;
550
566
  }
551
567
  /** Group a flat comments list into threads (top-level + replies + resolved attachments). */
552
568
  declare function deriveThreads(comments: Comment[], attachments: Attachment[]): Thread[];
@@ -559,6 +575,8 @@ interface ThreadsPanelProps {
559
575
  threads: Thread[];
560
576
  activity: ActivityEntry[];
561
577
  attachments: Attachment[];
578
+ /** Username of the logged-in user — used by the detail view to flag own messages. */
579
+ currentUsername: string;
562
580
  /** Open / close state. Lift this to the page so the bubble + main padding can coordinate. */
563
581
  open: boolean;
564
582
  onToggle: () => void;
@@ -589,6 +607,12 @@ interface ThreadsPanelProps {
589
607
  title?: string;
590
608
  thread_status?: ThreadStatus;
591
609
  }) => Promise<void>;
610
+ /** Edit a single comment (thread root or reply). Author-only on the backend. */
611
+ onEditMessage: (messageId: string, content: string) => Promise<void>;
612
+ /** Delete a single reply. Backend keeps the parent thread intact. */
613
+ onDeleteMessage: (messageId: string) => Promise<void>;
614
+ /** Delete the whole thread (root + replies). Backend cascades. */
615
+ onDeleteThread: (threadId: string) => Promise<void>;
592
616
  /** Upload a file attachment for the current task. Returns the new row. */
593
617
  onUploadAttachment: (file: File) => Promise<Attachment>;
594
618
  /** Add a link/recording attachment for the current task. */
@@ -599,7 +623,7 @@ interface ThreadsPanelProps {
599
623
  * thread detail view, and the new-thread composer. Designed to be `xl:flex
600
624
  * hidden` and `fixed` to the right edge by the consuming page.
601
625
  */
602
- declare function ThreadsPanel({ threads, activity, attachments, open, onToggle, openThreadId, onOpenThread, pendingAnchor, onClearAnchor, onAnchorClick, shimmeringThreadIds, isInternalUser, onCreateThread, onCreateReply, onUpdateThread, onUploadAttachment, onAddLinkAttachment, }: ThreadsPanelProps): react_jsx_runtime.JSX.Element;
626
+ declare function ThreadsPanel({ threads, activity, attachments, currentUsername, open, onToggle, openThreadId, onOpenThread, pendingAnchor, onClearAnchor, onAnchorClick, shimmeringThreadIds, isInternalUser, onCreateThread, onCreateReply, onUpdateThread, onEditMessage, onDeleteMessage, onDeleteThread, onUploadAttachment, onAddLinkAttachment, }: ThreadsPanelProps): react_jsx_runtime.JSX.Element;
603
627
 
604
628
  interface ThreadCardProps {
605
629
  thread: Thread;
@@ -619,18 +643,26 @@ declare function ThreadCard({ thread, onOpen, onAnchorClick, shimmer }: ThreadCa
619
643
 
620
644
  interface ThreadDetailViewProps {
621
645
  thread: Thread;
646
+ /** Username of the logged-in user, for own-message detection. */
647
+ currentUsername: string;
622
648
  onBack: () => void;
623
649
  onReply: (content: string, isInternal: boolean) => Promise<void>;
624
650
  onUpdateThread: (body: {
625
651
  title?: string;
626
652
  thread_status?: ThreadStatus;
627
653
  }) => Promise<void>;
654
+ /** Edit a single message (thread root or reply). Author-only on the backend. */
655
+ onEditMessage: (messageId: string, content: string) => Promise<void>;
656
+ /** Delete a single reply. Backend keeps the parent thread intact. */
657
+ onDeleteMessage: (messageId: string) => Promise<void>;
658
+ /** Delete the whole thread (root + replies). Backend cascades. */
659
+ onDeleteThread: (threadId: string) => Promise<void>;
628
660
  onAnchorClick: (anchor: ThreadAnchor) => void;
629
661
  /** Whether the current user can post internal-only replies. */
630
662
  isInternalUser: boolean;
631
663
  }
632
664
  /** Detail view shown inside the threads panel when a thread card is clicked. */
633
- declare function ThreadDetailView({ thread, onBack, onReply, onUpdateThread, onAnchorClick, isInternalUser, }: ThreadDetailViewProps): react_jsx_runtime.JSX.Element;
665
+ declare function ThreadDetailView({ thread, currentUsername, onBack, onReply, onUpdateThread, onEditMessage, onDeleteMessage, onDeleteThread, onAnchorClick, isInternalUser, }: ThreadDetailViewProps): react_jsx_runtime.JSX.Element;
634
666
 
635
667
  interface ThreadComposerProps {
636
668
  /** Existing attachments on the task — used to render chips for already-uploaded files. */
package/dist/index.d.ts CHANGED
@@ -363,8 +363,12 @@ interface MentionTextareaProps {
363
363
  rows?: number;
364
364
  className?: string;
365
365
  disabled?: boolean;
366
+ /** Focus the underlying textarea on mount. Use for composers that should be
367
+ * immediately writable (e.g. when the user opens the new-thread composer
368
+ * from a highlight-to-comment selection). */
369
+ autoFocus?: boolean;
366
370
  }
367
- declare function MentionTextarea({ value, onChange, onKeyDown, placeholder, rows, className, disabled, }: MentionTextareaProps): react_jsx_runtime.JSX.Element;
371
+ declare function MentionTextarea({ value, onChange, onKeyDown, placeholder, rows, className, disabled, autoFocus, }: MentionTextareaProps): react_jsx_runtime.JSX.Element;
368
372
 
369
373
  declare function SkeletonPulse({ className }: {
370
374
  className?: string;
@@ -433,6 +437,13 @@ interface DescriptionSectionProps {
433
437
  onStatusChange: (next: SectionStatus) => void;
434
438
  /** Optional saving indicator passed through to the editor. */
435
439
  saving?: boolean;
440
+ /** Threads anchored to this section — drives the inline `<mark>` highlights. */
441
+ anchors?: Array<{
442
+ snippet: string;
443
+ threadId: string;
444
+ }>;
445
+ /** Click handler when the user clicks on a highlighted snippet. */
446
+ onAnchorClick?: (threadId: string) => void;
436
447
  }
437
448
  /**
438
449
  * One free-text description section (Problem / User Story / etc.) with:
@@ -440,8 +451,10 @@ interface DescriptionSectionProps {
440
451
  * - read-mode `MarkdownView`
441
452
  * - click-to-focus WYSIWYG `MarkdownEditor`
442
453
  * - `data-section={sectionKey}` so highlight-to-comment can anchor here
454
+ * - inline `<mark class="eb-tb-annot">` wrapping each anchor's snippet
455
+ * (clicking the mark opens that thread in the right panel)
443
456
  */
444
- declare function DescriptionSection({ sectionKey, label, placeholder, value, onChange, status, onStatusChange, saving, }: DescriptionSectionProps): react_jsx_runtime.JSX.Element;
457
+ declare function DescriptionSection({ sectionKey, label, placeholder, value, onChange, status, onStatusChange, saving, anchors, onAnchorClick, }: DescriptionSectionProps): react_jsx_runtime.JSX.Element;
445
458
 
446
459
  /**
447
460
  * Lightweight read-mode markdown renderer for description sections, thread
@@ -536,6 +549,8 @@ interface Thread {
536
549
  status: ThreadStatus;
537
550
  /** Original mention-tagged text, used when rendering the message. */
538
551
  rawContent: string;
552
+ /** Whether the thread root has been edited at least once. */
553
+ edited?: boolean;
539
554
  anchor?: ThreadAnchor | null;
540
555
  attachments: Attachment[];
541
556
  replies: ThreadReply[];
@@ -547,6 +562,7 @@ interface ThreadReply {
547
562
  content: string;
548
563
  created_at: string;
549
564
  is_internal: boolean;
565
+ edited?: boolean;
550
566
  }
551
567
  /** Group a flat comments list into threads (top-level + replies + resolved attachments). */
552
568
  declare function deriveThreads(comments: Comment[], attachments: Attachment[]): Thread[];
@@ -559,6 +575,8 @@ interface ThreadsPanelProps {
559
575
  threads: Thread[];
560
576
  activity: ActivityEntry[];
561
577
  attachments: Attachment[];
578
+ /** Username of the logged-in user — used by the detail view to flag own messages. */
579
+ currentUsername: string;
562
580
  /** Open / close state. Lift this to the page so the bubble + main padding can coordinate. */
563
581
  open: boolean;
564
582
  onToggle: () => void;
@@ -589,6 +607,12 @@ interface ThreadsPanelProps {
589
607
  title?: string;
590
608
  thread_status?: ThreadStatus;
591
609
  }) => Promise<void>;
610
+ /** Edit a single comment (thread root or reply). Author-only on the backend. */
611
+ onEditMessage: (messageId: string, content: string) => Promise<void>;
612
+ /** Delete a single reply. Backend keeps the parent thread intact. */
613
+ onDeleteMessage: (messageId: string) => Promise<void>;
614
+ /** Delete the whole thread (root + replies). Backend cascades. */
615
+ onDeleteThread: (threadId: string) => Promise<void>;
592
616
  /** Upload a file attachment for the current task. Returns the new row. */
593
617
  onUploadAttachment: (file: File) => Promise<Attachment>;
594
618
  /** Add a link/recording attachment for the current task. */
@@ -599,7 +623,7 @@ interface ThreadsPanelProps {
599
623
  * thread detail view, and the new-thread composer. Designed to be `xl:flex
600
624
  * hidden` and `fixed` to the right edge by the consuming page.
601
625
  */
602
- declare function ThreadsPanel({ threads, activity, attachments, open, onToggle, openThreadId, onOpenThread, pendingAnchor, onClearAnchor, onAnchorClick, shimmeringThreadIds, isInternalUser, onCreateThread, onCreateReply, onUpdateThread, onUploadAttachment, onAddLinkAttachment, }: ThreadsPanelProps): react_jsx_runtime.JSX.Element;
626
+ declare function ThreadsPanel({ threads, activity, attachments, currentUsername, open, onToggle, openThreadId, onOpenThread, pendingAnchor, onClearAnchor, onAnchorClick, shimmeringThreadIds, isInternalUser, onCreateThread, onCreateReply, onUpdateThread, onEditMessage, onDeleteMessage, onDeleteThread, onUploadAttachment, onAddLinkAttachment, }: ThreadsPanelProps): react_jsx_runtime.JSX.Element;
603
627
 
604
628
  interface ThreadCardProps {
605
629
  thread: Thread;
@@ -619,18 +643,26 @@ declare function ThreadCard({ thread, onOpen, onAnchorClick, shimmer }: ThreadCa
619
643
 
620
644
  interface ThreadDetailViewProps {
621
645
  thread: Thread;
646
+ /** Username of the logged-in user, for own-message detection. */
647
+ currentUsername: string;
622
648
  onBack: () => void;
623
649
  onReply: (content: string, isInternal: boolean) => Promise<void>;
624
650
  onUpdateThread: (body: {
625
651
  title?: string;
626
652
  thread_status?: ThreadStatus;
627
653
  }) => Promise<void>;
654
+ /** Edit a single message (thread root or reply). Author-only on the backend. */
655
+ onEditMessage: (messageId: string, content: string) => Promise<void>;
656
+ /** Delete a single reply. Backend keeps the parent thread intact. */
657
+ onDeleteMessage: (messageId: string) => Promise<void>;
658
+ /** Delete the whole thread (root + replies). Backend cascades. */
659
+ onDeleteThread: (threadId: string) => Promise<void>;
628
660
  onAnchorClick: (anchor: ThreadAnchor) => void;
629
661
  /** Whether the current user can post internal-only replies. */
630
662
  isInternalUser: boolean;
631
663
  }
632
664
  /** Detail view shown inside the threads panel when a thread card is clicked. */
633
- declare function ThreadDetailView({ thread, onBack, onReply, onUpdateThread, onAnchorClick, isInternalUser, }: ThreadDetailViewProps): react_jsx_runtime.JSX.Element;
665
+ declare function ThreadDetailView({ thread, currentUsername, onBack, onReply, onUpdateThread, onEditMessage, onDeleteMessage, onDeleteThread, onAnchorClick, isInternalUser, }: ThreadDetailViewProps): react_jsx_runtime.JSX.Element;
634
666
 
635
667
  interface ThreadComposerProps {
636
668
  /** Existing attachments on the task — used to render chips for already-uploaded files. */