@waveform-playlist/annotations 9.0.3 → 9.1.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.
package/dist/index.js CHANGED
@@ -402,7 +402,6 @@ var AnnotationBox = ({
402
402
 
403
403
  // src/components/AnnotationBoxesWrapper.tsx
404
404
  var import_styled_components3 = __toESM(require("styled-components"));
405
- var import_ui_components = require("@waveform-playlist/ui-components");
406
405
  var import_jsx_runtime3 = require("react/jsx-runtime");
407
406
  var Container = import_styled_components3.default.div.attrs((props) => ({
408
407
  style: {
@@ -410,23 +409,13 @@ var Container = import_styled_components3.default.div.attrs((props) => ({
410
409
  }
411
410
  }))`
412
411
  position: relative;
413
- display: flex;
414
412
  ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
415
413
  background: transparent;
416
414
  z-index: 110;
417
415
  `;
418
- var ControlsPlaceholder = import_styled_components3.default.div`
419
- position: sticky;
420
- z-index: 200;
421
- left: 0;
422
- height: 100%;
423
- width: ${(props) => props.$controlWidth}px;
424
- flex-shrink: 0;
425
- background: transparent;
426
- `;
427
416
  var BoxesContainer = import_styled_components3.default.div`
428
417
  position: relative;
429
- flex: 1;
418
+ height: 100%;
430
419
  padding-left: ${(props) => props.$offset || 0}px;
431
420
  `;
432
421
  var AnnotationBoxesWrapper = ({
@@ -436,27 +425,11 @@ var AnnotationBoxesWrapper = ({
436
425
  offset = 0,
437
426
  width
438
427
  }) => {
439
- const {
440
- controls: { show, width: controlWidth }
441
- } = (0, import_ui_components.usePlaylistInfo)();
442
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
443
- Container,
444
- {
445
- className,
446
- $height: height,
447
- $controlWidth: show ? controlWidth : 0,
448
- $width: width,
449
- children: [
450
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ControlsPlaceholder, { $controlWidth: show ? controlWidth : 0 }),
451
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BoxesContainer, { $offset: offset, children })
452
- ]
453
- }
454
- );
428
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Container, { className, $height: height, $width: width, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BoxesContainer, { $offset: offset, children }) });
455
429
  };
456
430
 
457
431
  // src/components/AnnotationsTrack.tsx
458
432
  var import_styled_components4 = __toESM(require("styled-components"));
459
- var import_ui_components2 = require("@waveform-playlist/ui-components");
460
433
  var import_jsx_runtime4 = require("react/jsx-runtime");
461
434
  var Container2 = import_styled_components4.default.div.attrs((props) => ({
462
435
  style: {
@@ -464,28 +437,12 @@ var Container2 = import_styled_components4.default.div.attrs((props) => ({
464
437
  }
465
438
  }))`
466
439
  position: relative;
467
- display: flex;
468
440
  ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
469
441
  background: transparent;
470
442
  `;
471
- var ControlsPlaceholder2 = import_styled_components4.default.div`
472
- position: sticky;
473
- z-index: 200;
474
- left: 0;
475
- height: 100%;
476
- width: ${(props) => props.$controlWidth}px;
477
- flex-shrink: 0;
478
- background: transparent;
479
- display: flex;
480
- align-items: center;
481
- justify-content: center;
482
- font-size: 12px;
483
- color: ${(props) => props.theme?.textColorMuted || "#666"};
484
- font-weight: bold;
485
- `;
486
443
  var AnnotationsContainer = import_styled_components4.default.div`
487
444
  position: relative;
488
- flex: 1;
445
+ height: 100%;
489
446
  padding-left: ${(props) => props.$offset || 0}px;
490
447
  `;
491
448
  var AnnotationsTrack = ({
@@ -495,22 +452,7 @@ var AnnotationsTrack = ({
495
452
  offset = 0,
496
453
  width
497
454
  }) => {
498
- const {
499
- controls: { show, width: controlWidth }
500
- } = (0, import_ui_components2.usePlaylistInfo)();
501
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
502
- Container2,
503
- {
504
- className,
505
- $height: height,
506
- $controlWidth: show ? controlWidth : 0,
507
- $width: width,
508
- children: [
509
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlsPlaceholder2, { $controlWidth: show ? controlWidth : 0, children: "Annotations" }),
510
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnnotationsContainer, { $offset: offset, children })
511
- ]
512
- }
513
- );
455
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Container2, { className, $height: height, $width: width, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnnotationsContainer, { $offset: offset, children }) });
514
456
  };
515
457
 
516
458
  // src/components/AnnotationText.tsx
@@ -768,7 +710,7 @@ var AnnotationTextComponent = ({
768
710
  var AnnotationText2 = import_react3.default.memo(AnnotationTextComponent);
769
711
 
770
712
  // src/components/ContinuousPlayCheckbox.tsx
771
- var import_ui_components3 = require("@waveform-playlist/ui-components");
713
+ var import_ui_components = require("@waveform-playlist/ui-components");
772
714
  var import_jsx_runtime6 = require("react/jsx-runtime");
773
715
  var ContinuousPlayCheckbox = ({
774
716
  checked,
@@ -779,9 +721,9 @@ var ContinuousPlayCheckbox = ({
779
721
  const handleChange = (e) => {
780
722
  onChange(e.target.checked);
781
723
  };
782
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui_components3.BaseCheckboxWrapper, { className, children: [
724
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_ui_components.BaseCheckboxWrapper, { className, children: [
783
725
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
784
- import_ui_components3.BaseCheckbox,
726
+ import_ui_components.BaseCheckbox,
785
727
  {
786
728
  type: "checkbox",
787
729
  id: "continuous-play",
@@ -791,12 +733,12 @@ var ContinuousPlayCheckbox = ({
791
733
  disabled
792
734
  }
793
735
  ),
794
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui_components3.BaseCheckboxLabel, { htmlFor: "continuous-play", children: "Continuous Play" })
736
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui_components.BaseCheckboxLabel, { htmlFor: "continuous-play", children: "Continuous Play" })
795
737
  ] });
796
738
  };
797
739
 
798
740
  // src/components/LinkEndpointsCheckbox.tsx
799
- var import_ui_components4 = require("@waveform-playlist/ui-components");
741
+ var import_ui_components2 = require("@waveform-playlist/ui-components");
800
742
  var import_jsx_runtime7 = require("react/jsx-runtime");
801
743
  var LinkEndpointsCheckbox = ({
802
744
  checked,
@@ -807,9 +749,9 @@ var LinkEndpointsCheckbox = ({
807
749
  const handleChange = (e) => {
808
750
  onChange(e.target.checked);
809
751
  };
810
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ui_components4.BaseCheckboxWrapper, { className, children: [
752
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_ui_components2.BaseCheckboxWrapper, { className, children: [
811
753
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
812
- import_ui_components4.BaseCheckbox,
754
+ import_ui_components2.BaseCheckbox,
813
755
  {
814
756
  type: "checkbox",
815
757
  id: "link-endpoints",
@@ -819,21 +761,21 @@ var LinkEndpointsCheckbox = ({
819
761
  disabled
820
762
  }
821
763
  ),
822
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ui_components4.BaseCheckboxLabel, { htmlFor: "link-endpoints", children: "Link Endpoints" })
764
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_ui_components2.BaseCheckboxLabel, { htmlFor: "link-endpoints", children: "Link Endpoints" })
823
765
  ] });
824
766
  };
825
767
 
826
768
  // src/components/EditableCheckbox.tsx
827
- var import_ui_components5 = require("@waveform-playlist/ui-components");
769
+ var import_ui_components3 = require("@waveform-playlist/ui-components");
828
770
  var import_jsx_runtime8 = require("react/jsx-runtime");
829
771
  var EditableCheckbox = ({
830
772
  checked,
831
773
  onChange,
832
774
  className
833
775
  }) => {
834
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ui_components5.BaseCheckboxWrapper, { className, children: [
776
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_ui_components3.BaseCheckboxWrapper, { className, children: [
835
777
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
836
- import_ui_components5.BaseCheckbox,
778
+ import_ui_components3.BaseCheckbox,
837
779
  {
838
780
  type: "checkbox",
839
781
  id: "editable-annotations",
@@ -841,7 +783,7 @@ var EditableCheckbox = ({
841
783
  onChange: (e) => onChange(e.target.checked)
842
784
  }
843
785
  ),
844
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ui_components5.BaseCheckboxLabel, { htmlFor: "editable-annotations", children: "Editable Annotations" })
786
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_ui_components3.BaseCheckboxLabel, { htmlFor: "editable-annotations", children: "Editable Annotations" })
845
787
  ] });
846
788
  };
847
789
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/parsers/aeneas.ts","../src/components/Annotation.tsx","../src/components/AnnotationBox.tsx","../src/components/AnnotationBoxesWrapper.tsx","../src/components/AnnotationsTrack.tsx","../src/components/AnnotationText.tsx","../src/components/ContinuousPlayCheckbox.tsx","../src/components/LinkEndpointsCheckbox.tsx","../src/components/EditableCheckbox.tsx","../src/components/DownloadAnnotationsButton.tsx","../src/AnnotationProvider.tsx","../src/hooks/useAnnotationControls.ts"],"sourcesContent":["// Types from core\nexport type {\n AnnotationData,\n AnnotationFormat,\n AnnotationListOptions,\n AnnotationEventMap,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\n// Parsers\nexport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nexport type { AeneasFragment } from './parsers/aeneas';\n\n// Components\nexport { Annotation } from './components/Annotation';\nexport type { AnnotationProps } from './components/Annotation';\n\nexport { AnnotationBox } from './components/AnnotationBox';\nexport type { AnnotationBoxComponentProps } from './components/AnnotationBox';\n\nexport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nexport type { AnnotationBoxesWrapperProps } from './components/AnnotationBoxesWrapper';\n\nexport { AnnotationsTrack } from './components/AnnotationsTrack';\nexport type { AnnotationsTrackProps } from './components/AnnotationsTrack';\n\nexport { AnnotationText } from './components/AnnotationText';\nexport type { AnnotationTextProps } from './components/AnnotationText';\n\nexport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nexport type { ContinuousPlayCheckboxProps } from './components/ContinuousPlayCheckbox';\n\nexport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nexport type { LinkEndpointsCheckboxProps } from './components/LinkEndpointsCheckbox';\n\nexport { EditableCheckbox } from './components/EditableCheckbox';\nexport type { EditableCheckboxProps } from './components/EditableCheckbox';\n\nexport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\nexport type { DownloadAnnotationsButtonProps } from './components/DownloadAnnotationsButton';\n\n// Provider (registers annotation components with browser package)\nexport { AnnotationProvider } from './AnnotationProvider';\n\n// Hooks\nexport { useAnnotationControls } from './hooks/useAnnotationControls';\nexport type {\n UseAnnotationControlsOptions,\n UseAnnotationControlsReturn,\n AnnotationUpdateParams,\n} from './hooks/useAnnotationControls';\n","import type { AnnotationData } from '@waveform-playlist/core';\n\nexport interface AeneasFragment {\n begin: string;\n end: string;\n id: string;\n language: string;\n lines: string[];\n}\n\nexport function parseAeneas(data: AeneasFragment): AnnotationData {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n language: data.language,\n };\n}\n\nexport function serializeAeneas(annotation: AnnotationData): AeneasFragment {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.language || 'en',\n };\n}\n","import React, { FunctionComponent, useState } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\ninterface AnnotationOverlayProps {\n readonly $left: number;\n readonly $width: number;\n readonly $color: string;\n}\n\nconst AnnotationOverlay = styled.div.attrs<AnnotationOverlayProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<AnnotationOverlayProps>`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\n\nconst AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\n\nconst EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4caf50;\n }\n`;\n\nconst ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\n\nconst ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\n\n// Re-export shared annotation types from core\nexport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\nexport interface AnnotationProps {\n annotation: AnnotationData;\n index: number;\n allAnnotations: AnnotationData[];\n startPosition: number; // Start position in pixels\n endPosition: number; // End position in pixels\n color?: string;\n editable?: boolean;\n controls?: AnnotationAction[];\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n annotationListConfig?: AnnotationActionOptions;\n onClick?: (annotation: AnnotationData) => void;\n}\n\nexport const Annotation: FunctionComponent<AnnotationProps> = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = '#ff9800',\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join('\\n'));\n const width = Math.max(0, endPosition - startPosition);\n\n if (width <= 0) {\n return null;\n }\n\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setEditedText(e.target.value);\n };\n\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split('\\n');\n if (newLines.join('\\n') !== annotation.lines.join('\\n')) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n\n const handleControlClick = (control: AnnotationAction) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n\n const getIconClass = (classString: string) => {\n // Convert \"fas.fa-minus\" to \"fas fa-minus\"\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <AnnotationOverlay\n $left={startPosition}\n $width={width}\n $color={color}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n >\n {controls.length > 0 && (\n <ControlsBar>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={(e) => {\n e.stopPropagation();\n handleControlClick(control);\n }}\n >\n {control.text ? control.text : <i className={getIconClass(control.class || '')} />}\n </ControlButton>\n ))}\n </ControlsBar>\n )}\n {isEditing ? (\n <EditableText\n value={editedText}\n onChange={handleTextChange}\n onBlur={handleTextBlur}\n autoFocus\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n />\n ) : (\n <AnnotationText>{annotation.lines.join('\\n')}</AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/react';\n\ninterface WrapperProps {\n readonly $left: number;\n readonly $width: number;\n}\n\n// Wrapper positions the annotation and contains both Box and ResizeHandles as siblings\nconst Wrapper = styled.div.attrs<WrapperProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<WrapperProps>`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\n\ninterface BoxProps {\n readonly $color: string;\n readonly $isActive?: boolean;\n}\n\nconst Box = styled.div<BoxProps>`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) =>\n props.$isActive\n ? props.theme?.annotationBoxActiveBackground || 'rgba(255, 200, 100, 0.95)'\n : props.theme?.annotationBoxBackground || 'rgba(255, 255, 255, 0.85)'};\n border: ${(props) => (props.$isActive ? '3px' : '2px')} solid\n ${(props) =>\n props.$isActive ? props.theme?.annotationBoxActiveBorder || '#ff9800' : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)'\n : '0 1px 3px rgba(0, 0, 0, 0.1)'};\n\n &:hover {\n background: ${(props) =>\n props.theme?.annotationBoxHoverBackground || 'rgba(255, 255, 255, 0.98)'};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || '#ff9800'};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\n\nconst Label = styled.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || '#2a2a2a'};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\n\ninterface ResizeHandleStyledProps {\n $position: 'left' | 'right';\n $isDragging?: boolean;\n}\n\n// ResizeHandles sit inside their annotation's bounds so adjacent annotations'\n// handles never overlap — each handle is independently grabbable.\nconst ResizeHandle = styled.div<ResizeHandleStyledProps>`\n position: absolute;\n top: 0;\n ${(props) => (props.$position === 'left' ? 'left: 0' : 'right: 0')};\n width: 8px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.2)'\n : 'transparent'};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.8)'\n : props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.4)'};\n border-radius: 2px;\n opacity: ${(props) => (props.$isDragging ? 1 : 0.6)};\n transition:\n opacity 0.2s,\n background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.1)'};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) =>\n props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface AnnotationBoxComponentProps {\n annotationId: string;\n annotationIndex: number;\n startPosition: number;\n endPosition: number;\n label?: string;\n color?: string;\n isActive?: boolean;\n onClick?: () => void;\n editable?: boolean; // Whether to show drag handles\n}\n\nexport const AnnotationBox: FunctionComponent<AnnotationBoxComponentProps> = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = '#ff9800',\n isActive = false,\n onClick,\n editable = true,\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n\n // Left (start) boundary draggable\n // feedback: 'none' disables the Feedback plugin for this draggable — resize visual\n // feedback comes from React state updates repositioning the annotation, not CSS translate.\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const { ref: leftRef, isDragSource: isLeftDragging } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const { ref: rightRef, isDragSource: isRightDragging } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n if (width <= 0) {\n return null;\n }\n\n const handleHandleClick = (e: React.MouseEvent) => {\n // Prevent clicks on resize handles from bubbling to annotation box\n e.stopPropagation();\n };\n\n return (\n <Wrapper $left={startPosition} $width={width}>\n <Box $color={color} $isActive={isActive} onClick={onClick}>\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={leftRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={rightRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n />\n )}\n </Wrapper>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { usePlaylistInfo } from '@waveform-playlist/ui-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $controlWidth: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n display: flex;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\n\nconst ControlsPlaceholder = styled.div<{ $controlWidth: number }>`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n`;\n\nconst BoxesContainer = styled.div<{ $offset?: number }>`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationBoxesWrapperProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationBoxesWrapper: FunctionComponent<AnnotationBoxesWrapperProps> = ({\n children,\n className,\n height = 30,\n offset = 0,\n width,\n}) => {\n const {\n controls: { show, width: controlWidth },\n } = usePlaylistInfo();\n\n return (\n <Container\n className={className}\n $height={height}\n $controlWidth={show ? controlWidth : 0}\n $width={width}\n >\n <ControlsPlaceholder $controlWidth={show ? controlWidth : 0} />\n <BoxesContainer $offset={offset}>{children}</BoxesContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { usePlaylistInfo } from '@waveform-playlist/ui-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $controlWidth: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n display: flex;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n`;\n\nconst ControlsPlaceholder = styled.div<{ $controlWidth: number }>`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n font-weight: bold;\n`;\n\nconst AnnotationsContainer = styled.div<{ $offset?: number }>`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationsTrackProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationsTrack: FunctionComponent<AnnotationsTrackProps> = ({\n children,\n className,\n height = 100,\n offset = 0,\n width,\n}) => {\n const {\n controls: { show, width: controlWidth },\n } = usePlaylistInfo();\n\n return (\n <Container\n className={className}\n $height={height}\n $controlWidth={show ? controlWidth : 0}\n $width={width}\n >\n <ControlsPlaceholder $controlWidth={show ? controlWidth : 0}>Annotations</ControlsPlaceholder>\n <AnnotationsContainer $offset={offset}>{children}</AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\ninterface ContainerProps {\n $height?: number;\n}\n\nconst Container = styled.div<ContainerProps>`\n background: ${(props) => props.theme?.backgroundColor || '#fff'};\n ${(props) => (props.$height ? `height: ${props.$height}px;` : 'max-height: 200px;')}\n overflow-y: auto;\n padding: 8px;\n`;\n\nconst AnnotationItem = styled.div<{ $isActive?: boolean }>`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => (props.$isActive ? '#ff9800' : 'transparent')};\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.15)' : 'transparent')};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)'\n : 'none'};\n\n &:hover {\n background: ${(props) =>\n props.$isActive\n ? 'rgba(255, 152, 0, 0.2)'\n : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)'};\n border-left-color: ${(props) =>\n props.$isActive ? '#ff9800' : props.theme?.borderColor || '#ddd'};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\n\nconst AnnotationHeader = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\n\nconst AnnotationInfo = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\n\nconst AnnotationIdLabel = styled.span<{ $isEditable?: boolean }>`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\nconst TimeRange = styled.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || '#555'};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\n\nconst AnnotationControls = styled.div`\n display: flex;\n gap: 6px;\n`;\n\nconst ControlButton = styled.button`\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n color: ${(props) => props.theme?.textColor || '#333'};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\n\nconst AnnotationTextContent = styled.div<{ $isEditable?: boolean }>`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || '#2a2a2a'};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n padding: ${(props) => (props.$isEditable ? '6px' : '0')};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\n// Re-export from core\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/core';\n\nexport interface AnnotationTextProps {\n annotations: AnnotationData[];\n activeAnnotationId?: string;\n shouldScrollToActive?: boolean;\n /** Where to position the active annotation when scrolling: 'center', 'start', 'end', or 'nearest'. Defaults to 'center'. */\n scrollActivePosition?: ScrollLogicalPosition;\n /** Which scrollable containers to scroll: 'nearest' (only the annotation list) or 'all' (including viewport). Defaults to 'nearest'. */\n scrollActiveContainer?: 'nearest' | 'all';\n editable?: boolean;\n controls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n height?: number;\n onAnnotationClick?: (annotation: AnnotationData) => void;\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n /**\n * Custom render function for annotation items.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation in the list.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n}\n\nconst AnnotationTextComponent: FunctionComponent<AnnotationTextProps> = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n scrollActivePosition = 'center',\n scrollActiveContainer = 'nearest',\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem,\n}) => {\n const activeAnnotationRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const prevActiveIdRef = useRef<string | undefined>(undefined);\n\n // Track component renders and scroll position\n useEffect(() => {\n // Render tracking removed\n });\n\n // Track scroll changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n // Scroll tracking removed\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, []);\n\n // Auto-scroll to active annotation when it changes\n useEffect(() => {\n // Only scroll if parent says we should (prevents scrolling on remount after pause)\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: scrollActivePosition,\n container: scrollActiveContainer,\n } as ScrollIntoViewOptions);\n }\n\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive, scrollActivePosition, scrollActiveContainer]);\n\n const formatTime = (seconds: number): string => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return '0:00.000';\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, '0')}`;\n };\n\n const handleTextEdit = (index: number, newText: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split('\\n'),\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleIdEdit = (index: number, newId: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const trimmedId = newId.trim();\n if (!trimmedId) return; // Don't allow empty IDs\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId,\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleControlClick = (\n control: AnnotationAction,\n annotation: AnnotationData,\n index: number\n ) => {\n if (!onAnnotationUpdate) return;\n\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n\n const getIconClass = (classString: string) => {\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <Container ref={containerRef} $height={height}>\n {annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n\n // Use custom render function if provided\n if (renderAnnotationItem) {\n return (\n <div key={annotation.id} ref={isActive ? activeAnnotationRef : null}>\n {renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime,\n })}\n </div>\n );\n }\n\n // Default rendering\n return (\n <AnnotationItem\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n $isActive={isActive}\n onClick={handleClick}\n >\n <AnnotationHeader>\n <AnnotationInfo>\n <AnnotationIdLabel\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleIdEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.id}\n </AnnotationIdLabel>\n <TimeRange>\n {formatTime(annotation.start)} - {formatTime(annotation.end)}\n </TimeRange>\n </AnnotationInfo>\n {controls.length > 0 && (\n <AnnotationControls onClick={(e) => e.stopPropagation()}>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={() => handleControlClick(control, annotation, index)}\n >\n {control.text ? (\n control.text\n ) : (\n <i className={getIconClass(control.class || '')} />\n )}\n </ControlButton>\n ))}\n </AnnotationControls>\n )}\n </AnnotationHeader>\n <AnnotationTextContent\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleTextEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.lines.join('\\n')}\n </AnnotationTextContent>\n </AnnotationItem>\n );\n })}\n </Container>\n );\n};\n\n// Memoize to prevent unnecessary remounting when parent re-renders\nexport const AnnotationText = React.memo(AnnotationTextComponent);\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface ContinuousPlayCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling continuous play of annotations.\n * When enabled, playback continues from one annotation to the next without stopping.\n */\nexport const ContinuousPlayCheckbox: React.FC<ContinuousPlayCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"continuous-play\"\n className=\"continuous-play\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"continuous-play\">Continuous Play</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface LinkEndpointsCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling linked endpoints between annotations.\n * When enabled, the end time of one annotation is automatically linked to the start time of the next.\n */\nexport const LinkEndpointsCheckbox: React.FC<LinkEndpointsCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"link-endpoints\"\n className=\"link-endpoints\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"link-endpoints\">Link Endpoints</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface EditableCheckboxProps {\n checked: boolean;\n onChange: (enabled: boolean) => void;\n className?: string;\n}\n\nexport const EditableCheckbox: React.FC<EditableCheckboxProps> = ({\n checked,\n onChange,\n className,\n}) => {\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"editable-annotations\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n />\n <BaseCheckboxLabel htmlFor=\"editable-annotations\">Editable Annotations</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport styled from 'styled-components';\nimport { serializeAeneas } from '../parsers/aeneas';\nimport type { AnnotationData } from '../types';\n\nconst StyledButton = styled.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n color: ${(props) => props.theme?.textColor || '#333'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n border-radius: ${(props) => props.theme?.borderRadius || '4px'};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || 'inherit'};\n font-size: ${(props) => props.theme?.fontSize || '14px'};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || '#007bff'}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\n\nexport interface DownloadAnnotationsButtonProps {\n annotations: AnnotationData[];\n filename?: string;\n disabled?: boolean;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport const DownloadAnnotationsButton: React.FC<DownloadAnnotationsButtonProps> = ({\n annotations,\n filename = 'annotations.json',\n disabled = false,\n className,\n children = 'Download JSON',\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n\n // Serialize annotations to Aeneas JSON format\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n // Create a blob and download link\n const blob = new Blob([jsonString], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n\n // Trigger download\n document.body.appendChild(link);\n link.click();\n\n // Cleanup\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n\n return (\n <StyledButton\n onClick={handleDownload}\n disabled={disabled || annotations.length === 0}\n className={className}\n title={\n annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'\n }\n >\n {children}\n </StyledButton>\n );\n};\n","import React from 'react';\nimport { AnnotationIntegrationProvider } from '@waveform-playlist/browser';\nimport type { AnnotationIntegration } from '@waveform-playlist/browser';\nimport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nimport { AnnotationText } from './components/AnnotationText';\nimport { AnnotationBox } from './components/AnnotationBox';\nimport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nimport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nimport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nimport { EditableCheckbox } from './components/EditableCheckbox';\nimport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\n\nconst annotationIntegration: AnnotationIntegration = {\n parseAeneas: parseAeneas as (data: unknown) => import('@waveform-playlist/core').AnnotationData,\n serializeAeneas: serializeAeneas as (\n annotation: import('@waveform-playlist/core').AnnotationData\n ) => unknown,\n AnnotationText,\n AnnotationBox,\n AnnotationBoxesWrapper,\n ContinuousPlayCheckbox,\n LinkEndpointsCheckbox,\n EditableCheckbox,\n DownloadAnnotationsButton,\n};\n\nexport const AnnotationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n return (\n <AnnotationIntegrationProvider value={annotationIntegration}>\n {children}\n </AnnotationIntegrationProvider>\n );\n};\n","import { useState, useCallback } from 'react';\nimport type { AnnotationData } from '../types';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\nexport interface UseAnnotationControlsOptions {\n initialContinuousPlay?: boolean;\n initialLinkEndpoints?: boolean;\n}\n\nexport interface AnnotationUpdateParams {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationData[];\n duration: number;\n linkEndpoints: boolean;\n}\n\nexport interface UseAnnotationControlsReturn {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n setContinuousPlay: (value: boolean) => void;\n setLinkEndpoints: (value: boolean) => void;\n updateAnnotationBoundaries: (params: AnnotationUpdateParams) => AnnotationData[];\n}\n\n/**\n * Hook for managing annotation control state and boundary logic.\n * Handles continuous play mode and linked endpoints behavior.\n */\nexport const useAnnotationControls = (\n options: UseAnnotationControlsOptions = {}\n): UseAnnotationControlsReturn => {\n const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;\n\n const [continuousPlay, setContinuousPlay] = useState(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState(initialLinkEndpoints);\n\n /**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n * Note: linkEndpoints is passed as a parameter to ensure it uses the current value from context.\n */\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n }: AnnotationUpdateParams): AnnotationData[] => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex > 0 &&\n constrainedStart < updatedAnnotations[annotationIndex - 1].end\n ) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex < updatedAnnotations.length - 1 &&\n constrainedEnd > updatedAnnotations[annotationIndex + 1].start\n ) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n },\n []\n );\n\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries,\n };\n};\n"],"mappings":"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","names":["AnnotationText","styled","import_styled_components","import_react","import_jsx_runtime","styled","import_styled_components","import_jsx_runtime","styled","import_styled_components","import_ui_components","import_jsx_runtime","Container","styled","ControlsPlaceholder","import_react","import_styled_components","import_jsx_runtime","Container","styled","ControlButton","AnnotationText","React","import_ui_components","import_jsx_runtime","import_ui_components","import_jsx_runtime","import_ui_components","import_jsx_runtime","import_styled_components","import_jsx_runtime","styled","import_jsx_runtime","AnnotationText","import_react"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/parsers/aeneas.ts","../src/components/Annotation.tsx","../src/components/AnnotationBox.tsx","../src/components/AnnotationBoxesWrapper.tsx","../src/components/AnnotationsTrack.tsx","../src/components/AnnotationText.tsx","../src/components/ContinuousPlayCheckbox.tsx","../src/components/LinkEndpointsCheckbox.tsx","../src/components/EditableCheckbox.tsx","../src/components/DownloadAnnotationsButton.tsx","../src/AnnotationProvider.tsx","../src/hooks/useAnnotationControls.ts"],"sourcesContent":["// Types from core\nexport type {\n AnnotationData,\n AnnotationFormat,\n AnnotationListOptions,\n AnnotationEventMap,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\n// Parsers\nexport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nexport type { AeneasFragment } from './parsers/aeneas';\n\n// Components\nexport { Annotation } from './components/Annotation';\nexport type { AnnotationProps } from './components/Annotation';\n\nexport { AnnotationBox } from './components/AnnotationBox';\nexport type { AnnotationBoxComponentProps } from './components/AnnotationBox';\n\nexport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nexport type { AnnotationBoxesWrapperProps } from './components/AnnotationBoxesWrapper';\n\nexport { AnnotationsTrack } from './components/AnnotationsTrack';\nexport type { AnnotationsTrackProps } from './components/AnnotationsTrack';\n\nexport { AnnotationText } from './components/AnnotationText';\nexport type { AnnotationTextProps } from './components/AnnotationText';\n\nexport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nexport type { ContinuousPlayCheckboxProps } from './components/ContinuousPlayCheckbox';\n\nexport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nexport type { LinkEndpointsCheckboxProps } from './components/LinkEndpointsCheckbox';\n\nexport { EditableCheckbox } from './components/EditableCheckbox';\nexport type { EditableCheckboxProps } from './components/EditableCheckbox';\n\nexport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\nexport type { DownloadAnnotationsButtonProps } from './components/DownloadAnnotationsButton';\n\n// Provider (registers annotation components with browser package)\nexport { AnnotationProvider } from './AnnotationProvider';\n\n// Hooks\nexport { useAnnotationControls } from './hooks/useAnnotationControls';\nexport type {\n UseAnnotationControlsOptions,\n UseAnnotationControlsReturn,\n AnnotationUpdateParams,\n} from './hooks/useAnnotationControls';\n","import type { AnnotationData } from '@waveform-playlist/core';\n\nexport interface AeneasFragment {\n begin: string;\n end: string;\n id: string;\n language: string;\n lines: string[];\n}\n\nexport function parseAeneas(data: AeneasFragment): AnnotationData {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n language: data.language,\n };\n}\n\nexport function serializeAeneas(annotation: AnnotationData): AeneasFragment {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.language || 'en',\n };\n}\n","import React, { FunctionComponent, useState } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\ninterface AnnotationOverlayProps {\n readonly $left: number;\n readonly $width: number;\n readonly $color: string;\n}\n\nconst AnnotationOverlay = styled.div.attrs<AnnotationOverlayProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<AnnotationOverlayProps>`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\n\nconst AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\n\nconst EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4caf50;\n }\n`;\n\nconst ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\n\nconst ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\n\n// Re-export shared annotation types from core\nexport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\nexport interface AnnotationProps {\n annotation: AnnotationData;\n index: number;\n allAnnotations: AnnotationData[];\n startPosition: number; // Start position in pixels\n endPosition: number; // End position in pixels\n color?: string;\n editable?: boolean;\n controls?: AnnotationAction[];\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n annotationListConfig?: AnnotationActionOptions;\n onClick?: (annotation: AnnotationData) => void;\n}\n\nexport const Annotation: FunctionComponent<AnnotationProps> = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = '#ff9800',\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join('\\n'));\n const width = Math.max(0, endPosition - startPosition);\n\n if (width <= 0) {\n return null;\n }\n\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setEditedText(e.target.value);\n };\n\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split('\\n');\n if (newLines.join('\\n') !== annotation.lines.join('\\n')) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n\n const handleControlClick = (control: AnnotationAction) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n\n const getIconClass = (classString: string) => {\n // Convert \"fas.fa-minus\" to \"fas fa-minus\"\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <AnnotationOverlay\n $left={startPosition}\n $width={width}\n $color={color}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n >\n {controls.length > 0 && (\n <ControlsBar>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={(e) => {\n e.stopPropagation();\n handleControlClick(control);\n }}\n >\n {control.text ? control.text : <i className={getIconClass(control.class || '')} />}\n </ControlButton>\n ))}\n </ControlsBar>\n )}\n {isEditing ? (\n <EditableText\n value={editedText}\n onChange={handleTextChange}\n onBlur={handleTextBlur}\n autoFocus\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n />\n ) : (\n <AnnotationText>{annotation.lines.join('\\n')}</AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/react';\n\ninterface WrapperProps {\n readonly $left: number;\n readonly $width: number;\n}\n\n// Wrapper positions the annotation and contains both Box and ResizeHandles as siblings\nconst Wrapper = styled.div.attrs<WrapperProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<WrapperProps>`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\n\ninterface BoxProps {\n readonly $color: string;\n readonly $isActive?: boolean;\n}\n\nconst Box = styled.div<BoxProps>`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) =>\n props.$isActive\n ? props.theme?.annotationBoxActiveBackground || 'rgba(255, 200, 100, 0.95)'\n : props.theme?.annotationBoxBackground || 'rgba(255, 255, 255, 0.85)'};\n border: ${(props) => (props.$isActive ? '3px' : '2px')} solid\n ${(props) =>\n props.$isActive ? props.theme?.annotationBoxActiveBorder || '#ff9800' : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)'\n : '0 1px 3px rgba(0, 0, 0, 0.1)'};\n\n &:hover {\n background: ${(props) =>\n props.theme?.annotationBoxHoverBackground || 'rgba(255, 255, 255, 0.98)'};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || '#ff9800'};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\n\nconst Label = styled.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || '#2a2a2a'};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\n\ninterface ResizeHandleStyledProps {\n $position: 'left' | 'right';\n $isDragging?: boolean;\n}\n\n// ResizeHandles sit inside their annotation's bounds so adjacent annotations'\n// handles never overlap — each handle is independently grabbable.\nconst ResizeHandle = styled.div<ResizeHandleStyledProps>`\n position: absolute;\n top: 0;\n ${(props) => (props.$position === 'left' ? 'left: 0' : 'right: 0')};\n width: 8px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.2)'\n : 'transparent'};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.8)'\n : props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.4)'};\n border-radius: 2px;\n opacity: ${(props) => (props.$isDragging ? 1 : 0.6)};\n transition:\n opacity 0.2s,\n background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.1)'};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) =>\n props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface AnnotationBoxComponentProps {\n annotationId: string;\n annotationIndex: number;\n startPosition: number;\n endPosition: number;\n label?: string;\n color?: string;\n isActive?: boolean;\n onClick?: () => void;\n editable?: boolean; // Whether to show drag handles\n}\n\nexport const AnnotationBox: FunctionComponent<AnnotationBoxComponentProps> = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = '#ff9800',\n isActive = false,\n onClick,\n editable = true,\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n\n // Left (start) boundary draggable\n // feedback: 'none' disables the Feedback plugin for this draggable — resize visual\n // feedback comes from React state updates repositioning the annotation, not CSS translate.\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const { ref: leftRef, isDragSource: isLeftDragging } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const { ref: rightRef, isDragSource: isRightDragging } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n if (width <= 0) {\n return null;\n }\n\n const handleHandleClick = (e: React.MouseEvent) => {\n // Prevent clicks on resize handles from bubbling to annotation box\n e.stopPropagation();\n };\n\n return (\n <Wrapper $left={startPosition} $width={width}>\n <Box $color={color} $isActive={isActive} onClick={onClick}>\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={leftRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={rightRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n />\n )}\n </Wrapper>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\n\nconst BoxesContainer = styled.div<{ $offset?: number }>`\n position: relative;\n height: 100%;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationBoxesWrapperProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationBoxesWrapper: FunctionComponent<AnnotationBoxesWrapperProps> = ({\n children,\n className,\n height = 30,\n offset = 0,\n width,\n}) => {\n return (\n <Container className={className} $height={height} $width={width}>\n <BoxesContainer $offset={offset}>{children}</BoxesContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n`;\n\nconst AnnotationsContainer = styled.div<{ $offset?: number }>`\n position: relative;\n height: 100%;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationsTrackProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationsTrack: FunctionComponent<AnnotationsTrackProps> = ({\n children,\n className,\n height = 100,\n offset = 0,\n width,\n}) => {\n return (\n <Container className={className} $height={height} $width={width}>\n <AnnotationsContainer $offset={offset}>{children}</AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\ninterface ContainerProps {\n $height?: number;\n}\n\nconst Container = styled.div<ContainerProps>`\n background: ${(props) => props.theme?.backgroundColor || '#fff'};\n ${(props) => (props.$height ? `height: ${props.$height}px;` : 'max-height: 200px;')}\n overflow-y: auto;\n padding: 8px;\n`;\n\nconst AnnotationItem = styled.div<{ $isActive?: boolean }>`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => (props.$isActive ? '#ff9800' : 'transparent')};\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.15)' : 'transparent')};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)'\n : 'none'};\n\n &:hover {\n background: ${(props) =>\n props.$isActive\n ? 'rgba(255, 152, 0, 0.2)'\n : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)'};\n border-left-color: ${(props) =>\n props.$isActive ? '#ff9800' : props.theme?.borderColor || '#ddd'};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\n\nconst AnnotationHeader = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\n\nconst AnnotationInfo = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\n\nconst AnnotationIdLabel = styled.span<{ $isEditable?: boolean }>`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\nconst TimeRange = styled.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || '#555'};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\n\nconst AnnotationControls = styled.div`\n display: flex;\n gap: 6px;\n`;\n\nconst ControlButton = styled.button`\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n color: ${(props) => props.theme?.textColor || '#333'};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\n\nconst AnnotationTextContent = styled.div<{ $isEditable?: boolean }>`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || '#2a2a2a'};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n padding: ${(props) => (props.$isEditable ? '6px' : '0')};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\n// Re-export from core\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/core';\n\nexport interface AnnotationTextProps {\n annotations: AnnotationData[];\n activeAnnotationId?: string;\n shouldScrollToActive?: boolean;\n /** Where to position the active annotation when scrolling: 'center', 'start', 'end', or 'nearest'. Defaults to 'center'. */\n scrollActivePosition?: ScrollLogicalPosition;\n /** Which scrollable containers to scroll: 'nearest' (only the annotation list) or 'all' (including viewport). Defaults to 'nearest'. */\n scrollActiveContainer?: 'nearest' | 'all';\n editable?: boolean;\n controls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n height?: number;\n onAnnotationClick?: (annotation: AnnotationData) => void;\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n /**\n * Custom render function for annotation items.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation in the list.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n}\n\nconst AnnotationTextComponent: FunctionComponent<AnnotationTextProps> = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n scrollActivePosition = 'center',\n scrollActiveContainer = 'nearest',\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem,\n}) => {\n const activeAnnotationRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const prevActiveIdRef = useRef<string | undefined>(undefined);\n\n // Track component renders and scroll position\n useEffect(() => {\n // Render tracking removed\n });\n\n // Track scroll changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n // Scroll tracking removed\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, []);\n\n // Auto-scroll to active annotation when it changes\n useEffect(() => {\n // Only scroll if parent says we should (prevents scrolling on remount after pause)\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: scrollActivePosition,\n container: scrollActiveContainer,\n } as ScrollIntoViewOptions);\n }\n\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive, scrollActivePosition, scrollActiveContainer]);\n\n const formatTime = (seconds: number): string => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return '0:00.000';\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, '0')}`;\n };\n\n const handleTextEdit = (index: number, newText: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split('\\n'),\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleIdEdit = (index: number, newId: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const trimmedId = newId.trim();\n if (!trimmedId) return; // Don't allow empty IDs\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId,\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleControlClick = (\n control: AnnotationAction,\n annotation: AnnotationData,\n index: number\n ) => {\n if (!onAnnotationUpdate) return;\n\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n\n const getIconClass = (classString: string) => {\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <Container ref={containerRef} $height={height}>\n {annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n\n // Use custom render function if provided\n if (renderAnnotationItem) {\n return (\n <div key={annotation.id} ref={isActive ? activeAnnotationRef : null}>\n {renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime,\n })}\n </div>\n );\n }\n\n // Default rendering\n return (\n <AnnotationItem\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n $isActive={isActive}\n onClick={handleClick}\n >\n <AnnotationHeader>\n <AnnotationInfo>\n <AnnotationIdLabel\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleIdEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.id}\n </AnnotationIdLabel>\n <TimeRange>\n {formatTime(annotation.start)} - {formatTime(annotation.end)}\n </TimeRange>\n </AnnotationInfo>\n {controls.length > 0 && (\n <AnnotationControls onClick={(e) => e.stopPropagation()}>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={() => handleControlClick(control, annotation, index)}\n >\n {control.text ? (\n control.text\n ) : (\n <i className={getIconClass(control.class || '')} />\n )}\n </ControlButton>\n ))}\n </AnnotationControls>\n )}\n </AnnotationHeader>\n <AnnotationTextContent\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleTextEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.lines.join('\\n')}\n </AnnotationTextContent>\n </AnnotationItem>\n );\n })}\n </Container>\n );\n};\n\n// Memoize to prevent unnecessary remounting when parent re-renders\nexport const AnnotationText = React.memo(AnnotationTextComponent);\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface ContinuousPlayCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling continuous play of annotations.\n * When enabled, playback continues from one annotation to the next without stopping.\n */\nexport const ContinuousPlayCheckbox: React.FC<ContinuousPlayCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"continuous-play\"\n className=\"continuous-play\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"continuous-play\">Continuous Play</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface LinkEndpointsCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling linked endpoints between annotations.\n * When enabled, the end time of one annotation is automatically linked to the start time of the next.\n */\nexport const LinkEndpointsCheckbox: React.FC<LinkEndpointsCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"link-endpoints\"\n className=\"link-endpoints\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"link-endpoints\">Link Endpoints</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface EditableCheckboxProps {\n checked: boolean;\n onChange: (enabled: boolean) => void;\n className?: string;\n}\n\nexport const EditableCheckbox: React.FC<EditableCheckboxProps> = ({\n checked,\n onChange,\n className,\n}) => {\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"editable-annotations\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n />\n <BaseCheckboxLabel htmlFor=\"editable-annotations\">Editable Annotations</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport styled from 'styled-components';\nimport { serializeAeneas } from '../parsers/aeneas';\nimport type { AnnotationData } from '../types';\n\nconst StyledButton = styled.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n color: ${(props) => props.theme?.textColor || '#333'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n border-radius: ${(props) => props.theme?.borderRadius || '4px'};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || 'inherit'};\n font-size: ${(props) => props.theme?.fontSize || '14px'};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || '#007bff'}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\n\nexport interface DownloadAnnotationsButtonProps {\n annotations: AnnotationData[];\n filename?: string;\n disabled?: boolean;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport const DownloadAnnotationsButton: React.FC<DownloadAnnotationsButtonProps> = ({\n annotations,\n filename = 'annotations.json',\n disabled = false,\n className,\n children = 'Download JSON',\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n\n // Serialize annotations to Aeneas JSON format\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n // Create a blob and download link\n const blob = new Blob([jsonString], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n\n // Trigger download\n document.body.appendChild(link);\n link.click();\n\n // Cleanup\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n\n return (\n <StyledButton\n onClick={handleDownload}\n disabled={disabled || annotations.length === 0}\n className={className}\n title={\n annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'\n }\n >\n {children}\n </StyledButton>\n );\n};\n","import React from 'react';\nimport { AnnotationIntegrationProvider } from '@waveform-playlist/browser';\nimport type { AnnotationIntegration } from '@waveform-playlist/browser';\nimport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nimport { AnnotationText } from './components/AnnotationText';\nimport { AnnotationBox } from './components/AnnotationBox';\nimport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nimport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nimport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nimport { EditableCheckbox } from './components/EditableCheckbox';\nimport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\n\nconst annotationIntegration: AnnotationIntegration = {\n parseAeneas: parseAeneas as (data: unknown) => import('@waveform-playlist/core').AnnotationData,\n serializeAeneas: serializeAeneas as (\n annotation: import('@waveform-playlist/core').AnnotationData\n ) => unknown,\n AnnotationText,\n AnnotationBox,\n AnnotationBoxesWrapper,\n ContinuousPlayCheckbox,\n LinkEndpointsCheckbox,\n EditableCheckbox,\n DownloadAnnotationsButton,\n};\n\nexport const AnnotationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n return (\n <AnnotationIntegrationProvider value={annotationIntegration}>\n {children}\n </AnnotationIntegrationProvider>\n );\n};\n","import { useState, useCallback } from 'react';\nimport type { AnnotationData } from '../types';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\nexport interface UseAnnotationControlsOptions {\n initialContinuousPlay?: boolean;\n initialLinkEndpoints?: boolean;\n}\n\nexport interface AnnotationUpdateParams {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationData[];\n duration: number;\n linkEndpoints: boolean;\n}\n\nexport interface UseAnnotationControlsReturn {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n setContinuousPlay: (value: boolean) => void;\n setLinkEndpoints: (value: boolean) => void;\n updateAnnotationBoundaries: (params: AnnotationUpdateParams) => AnnotationData[];\n}\n\n/**\n * Hook for managing annotation control state and boundary logic.\n * Handles continuous play mode and linked endpoints behavior.\n */\nexport const useAnnotationControls = (\n options: UseAnnotationControlsOptions = {}\n): UseAnnotationControlsReturn => {\n const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;\n\n const [continuousPlay, setContinuousPlay] = useState(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState(initialLinkEndpoints);\n\n /**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n * Note: linkEndpoints is passed as a parameter to ensure it uses the current value from context.\n */\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n }: AnnotationUpdateParams): AnnotationData[] => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex > 0 &&\n constrainedStart < updatedAnnotations[annotationIndex - 1].end\n ) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex < updatedAnnotations.length - 1 &&\n constrainedEnd > updatedAnnotations[annotationIndex + 1].start\n ) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n },\n []\n );\n\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries,\n };\n};\n"],"mappings":"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","names":["AnnotationText","styled","import_styled_components","import_react","import_jsx_runtime","styled","import_styled_components","import_jsx_runtime","styled","import_styled_components","import_jsx_runtime","Container","styled","import_react","import_styled_components","import_jsx_runtime","Container","styled","ControlButton","AnnotationText","React","import_jsx_runtime","import_ui_components","import_jsx_runtime","import_ui_components","import_jsx_runtime","import_styled_components","import_jsx_runtime","styled","import_jsx_runtime","AnnotationText","import_react"]}
package/dist/index.mjs CHANGED
@@ -354,31 +354,20 @@ var AnnotationBox = ({
354
354
 
355
355
  // src/components/AnnotationBoxesWrapper.tsx
356
356
  import styled3 from "styled-components";
357
- import { usePlaylistInfo } from "@waveform-playlist/ui-components";
358
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
357
+ import { jsx as jsx3 } from "react/jsx-runtime";
359
358
  var Container = styled3.div.attrs((props) => ({
360
359
  style: {
361
360
  height: `${props.$height}px`
362
361
  }
363
362
  }))`
364
363
  position: relative;
365
- display: flex;
366
364
  ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
367
365
  background: transparent;
368
366
  z-index: 110;
369
367
  `;
370
- var ControlsPlaceholder = styled3.div`
371
- position: sticky;
372
- z-index: 200;
373
- left: 0;
374
- height: 100%;
375
- width: ${(props) => props.$controlWidth}px;
376
- flex-shrink: 0;
377
- background: transparent;
378
- `;
379
368
  var BoxesContainer = styled3.div`
380
369
  position: relative;
381
- flex: 1;
370
+ height: 100%;
382
371
  padding-left: ${(props) => props.$offset || 0}px;
383
372
  `;
384
373
  var AnnotationBoxesWrapper = ({
@@ -388,56 +377,24 @@ var AnnotationBoxesWrapper = ({
388
377
  offset = 0,
389
378
  width
390
379
  }) => {
391
- const {
392
- controls: { show, width: controlWidth }
393
- } = usePlaylistInfo();
394
- return /* @__PURE__ */ jsxs3(
395
- Container,
396
- {
397
- className,
398
- $height: height,
399
- $controlWidth: show ? controlWidth : 0,
400
- $width: width,
401
- children: [
402
- /* @__PURE__ */ jsx3(ControlsPlaceholder, { $controlWidth: show ? controlWidth : 0 }),
403
- /* @__PURE__ */ jsx3(BoxesContainer, { $offset: offset, children })
404
- ]
405
- }
406
- );
380
+ return /* @__PURE__ */ jsx3(Container, { className, $height: height, $width: width, children: /* @__PURE__ */ jsx3(BoxesContainer, { $offset: offset, children }) });
407
381
  };
408
382
 
409
383
  // src/components/AnnotationsTrack.tsx
410
384
  import styled4 from "styled-components";
411
- import { usePlaylistInfo as usePlaylistInfo2 } from "@waveform-playlist/ui-components";
412
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
385
+ import { jsx as jsx4 } from "react/jsx-runtime";
413
386
  var Container2 = styled4.div.attrs((props) => ({
414
387
  style: {
415
388
  height: `${props.$height}px`
416
389
  }
417
390
  }))`
418
391
  position: relative;
419
- display: flex;
420
392
  ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
421
393
  background: transparent;
422
394
  `;
423
- var ControlsPlaceholder2 = styled4.div`
424
- position: sticky;
425
- z-index: 200;
426
- left: 0;
427
- height: 100%;
428
- width: ${(props) => props.$controlWidth}px;
429
- flex-shrink: 0;
430
- background: transparent;
431
- display: flex;
432
- align-items: center;
433
- justify-content: center;
434
- font-size: 12px;
435
- color: ${(props) => props.theme?.textColorMuted || "#666"};
436
- font-weight: bold;
437
- `;
438
395
  var AnnotationsContainer = styled4.div`
439
396
  position: relative;
440
- flex: 1;
397
+ height: 100%;
441
398
  padding-left: ${(props) => props.$offset || 0}px;
442
399
  `;
443
400
  var AnnotationsTrack = ({
@@ -447,28 +404,13 @@ var AnnotationsTrack = ({
447
404
  offset = 0,
448
405
  width
449
406
  }) => {
450
- const {
451
- controls: { show, width: controlWidth }
452
- } = usePlaylistInfo2();
453
- return /* @__PURE__ */ jsxs4(
454
- Container2,
455
- {
456
- className,
457
- $height: height,
458
- $controlWidth: show ? controlWidth : 0,
459
- $width: width,
460
- children: [
461
- /* @__PURE__ */ jsx4(ControlsPlaceholder2, { $controlWidth: show ? controlWidth : 0, children: "Annotations" }),
462
- /* @__PURE__ */ jsx4(AnnotationsContainer, { $offset: offset, children })
463
- ]
464
- }
465
- );
407
+ return /* @__PURE__ */ jsx4(Container2, { className, $height: height, $width: width, children: /* @__PURE__ */ jsx4(AnnotationsContainer, { $offset: offset, children }) });
466
408
  };
467
409
 
468
410
  // src/components/AnnotationText.tsx
469
411
  import React2, { useRef, useEffect } from "react";
470
412
  import styled5 from "styled-components";
471
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
413
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
472
414
  var Container3 = styled5.div`
473
415
  background: ${(props) => props.theme?.backgroundColor || "#fff"};
474
416
  ${(props) => props.$height ? `height: ${props.$height}px;` : "max-height: 200px;"}
@@ -654,15 +596,15 @@ var AnnotationTextComponent = ({
654
596
  formatTime
655
597
  }) }, annotation.id);
656
598
  }
657
- return /* @__PURE__ */ jsxs5(
599
+ return /* @__PURE__ */ jsxs3(
658
600
  AnnotationItem,
659
601
  {
660
602
  ref: isActive ? activeAnnotationRef : null,
661
603
  $isActive: isActive,
662
604
  onClick: handleClick,
663
605
  children: [
664
- /* @__PURE__ */ jsxs5(AnnotationHeader, { children: [
665
- /* @__PURE__ */ jsxs5(AnnotationInfo, { children: [
606
+ /* @__PURE__ */ jsxs3(AnnotationHeader, { children: [
607
+ /* @__PURE__ */ jsxs3(AnnotationInfo, { children: [
666
608
  /* @__PURE__ */ jsx5(
667
609
  AnnotationIdLabel,
668
610
  {
@@ -679,7 +621,7 @@ var AnnotationTextComponent = ({
679
621
  children: annotation.id
680
622
  }
681
623
  ),
682
- /* @__PURE__ */ jsxs5(TimeRange, { children: [
624
+ /* @__PURE__ */ jsxs3(TimeRange, { children: [
683
625
  formatTime(annotation.start),
684
626
  " - ",
685
627
  formatTime(annotation.end)
@@ -725,7 +667,7 @@ import {
725
667
  BaseCheckbox,
726
668
  BaseCheckboxLabel
727
669
  } from "@waveform-playlist/ui-components";
728
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
670
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
729
671
  var ContinuousPlayCheckbox = ({
730
672
  checked,
731
673
  onChange,
@@ -735,7 +677,7 @@ var ContinuousPlayCheckbox = ({
735
677
  const handleChange = (e) => {
736
678
  onChange(e.target.checked);
737
679
  };
738
- return /* @__PURE__ */ jsxs6(BaseCheckboxWrapper, { className, children: [
680
+ return /* @__PURE__ */ jsxs4(BaseCheckboxWrapper, { className, children: [
739
681
  /* @__PURE__ */ jsx6(
740
682
  BaseCheckbox,
741
683
  {
@@ -757,7 +699,7 @@ import {
757
699
  BaseCheckbox as BaseCheckbox2,
758
700
  BaseCheckboxLabel as BaseCheckboxLabel2
759
701
  } from "@waveform-playlist/ui-components";
760
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
702
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
761
703
  var LinkEndpointsCheckbox = ({
762
704
  checked,
763
705
  onChange,
@@ -767,7 +709,7 @@ var LinkEndpointsCheckbox = ({
767
709
  const handleChange = (e) => {
768
710
  onChange(e.target.checked);
769
711
  };
770
- return /* @__PURE__ */ jsxs7(BaseCheckboxWrapper2, { className, children: [
712
+ return /* @__PURE__ */ jsxs5(BaseCheckboxWrapper2, { className, children: [
771
713
  /* @__PURE__ */ jsx7(
772
714
  BaseCheckbox2,
773
715
  {
@@ -789,13 +731,13 @@ import {
789
731
  BaseCheckbox as BaseCheckbox3,
790
732
  BaseCheckboxLabel as BaseCheckboxLabel3
791
733
  } from "@waveform-playlist/ui-components";
792
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
734
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
793
735
  var EditableCheckbox = ({
794
736
  checked,
795
737
  onChange,
796
738
  className
797
739
  }) => {
798
- return /* @__PURE__ */ jsxs8(BaseCheckboxWrapper3, { className, children: [
740
+ return /* @__PURE__ */ jsxs6(BaseCheckboxWrapper3, { className, children: [
799
741
  /* @__PURE__ */ jsx8(
800
742
  BaseCheckbox3,
801
743
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parsers/aeneas.ts","../src/components/Annotation.tsx","../src/components/AnnotationBox.tsx","../src/components/AnnotationBoxesWrapper.tsx","../src/components/AnnotationsTrack.tsx","../src/components/AnnotationText.tsx","../src/components/ContinuousPlayCheckbox.tsx","../src/components/LinkEndpointsCheckbox.tsx","../src/components/EditableCheckbox.tsx","../src/components/DownloadAnnotationsButton.tsx","../src/AnnotationProvider.tsx","../src/hooks/useAnnotationControls.ts"],"sourcesContent":["import type { AnnotationData } from '@waveform-playlist/core';\n\nexport interface AeneasFragment {\n begin: string;\n end: string;\n id: string;\n language: string;\n lines: string[];\n}\n\nexport function parseAeneas(data: AeneasFragment): AnnotationData {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n language: data.language,\n };\n}\n\nexport function serializeAeneas(annotation: AnnotationData): AeneasFragment {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.language || 'en',\n };\n}\n","import React, { FunctionComponent, useState } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\ninterface AnnotationOverlayProps {\n readonly $left: number;\n readonly $width: number;\n readonly $color: string;\n}\n\nconst AnnotationOverlay = styled.div.attrs<AnnotationOverlayProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<AnnotationOverlayProps>`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\n\nconst AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\n\nconst EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4caf50;\n }\n`;\n\nconst ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\n\nconst ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\n\n// Re-export shared annotation types from core\nexport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\nexport interface AnnotationProps {\n annotation: AnnotationData;\n index: number;\n allAnnotations: AnnotationData[];\n startPosition: number; // Start position in pixels\n endPosition: number; // End position in pixels\n color?: string;\n editable?: boolean;\n controls?: AnnotationAction[];\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n annotationListConfig?: AnnotationActionOptions;\n onClick?: (annotation: AnnotationData) => void;\n}\n\nexport const Annotation: FunctionComponent<AnnotationProps> = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = '#ff9800',\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join('\\n'));\n const width = Math.max(0, endPosition - startPosition);\n\n if (width <= 0) {\n return null;\n }\n\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setEditedText(e.target.value);\n };\n\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split('\\n');\n if (newLines.join('\\n') !== annotation.lines.join('\\n')) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n\n const handleControlClick = (control: AnnotationAction) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n\n const getIconClass = (classString: string) => {\n // Convert \"fas.fa-minus\" to \"fas fa-minus\"\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <AnnotationOverlay\n $left={startPosition}\n $width={width}\n $color={color}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n >\n {controls.length > 0 && (\n <ControlsBar>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={(e) => {\n e.stopPropagation();\n handleControlClick(control);\n }}\n >\n {control.text ? control.text : <i className={getIconClass(control.class || '')} />}\n </ControlButton>\n ))}\n </ControlsBar>\n )}\n {isEditing ? (\n <EditableText\n value={editedText}\n onChange={handleTextChange}\n onBlur={handleTextBlur}\n autoFocus\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n />\n ) : (\n <AnnotationText>{annotation.lines.join('\\n')}</AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/react';\n\ninterface WrapperProps {\n readonly $left: number;\n readonly $width: number;\n}\n\n// Wrapper positions the annotation and contains both Box and ResizeHandles as siblings\nconst Wrapper = styled.div.attrs<WrapperProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<WrapperProps>`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\n\ninterface BoxProps {\n readonly $color: string;\n readonly $isActive?: boolean;\n}\n\nconst Box = styled.div<BoxProps>`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) =>\n props.$isActive\n ? props.theme?.annotationBoxActiveBackground || 'rgba(255, 200, 100, 0.95)'\n : props.theme?.annotationBoxBackground || 'rgba(255, 255, 255, 0.85)'};\n border: ${(props) => (props.$isActive ? '3px' : '2px')} solid\n ${(props) =>\n props.$isActive ? props.theme?.annotationBoxActiveBorder || '#ff9800' : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)'\n : '0 1px 3px rgba(0, 0, 0, 0.1)'};\n\n &:hover {\n background: ${(props) =>\n props.theme?.annotationBoxHoverBackground || 'rgba(255, 255, 255, 0.98)'};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || '#ff9800'};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\n\nconst Label = styled.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || '#2a2a2a'};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\n\ninterface ResizeHandleStyledProps {\n $position: 'left' | 'right';\n $isDragging?: boolean;\n}\n\n// ResizeHandles sit inside their annotation's bounds so adjacent annotations'\n// handles never overlap — each handle is independently grabbable.\nconst ResizeHandle = styled.div<ResizeHandleStyledProps>`\n position: absolute;\n top: 0;\n ${(props) => (props.$position === 'left' ? 'left: 0' : 'right: 0')};\n width: 8px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.2)'\n : 'transparent'};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.8)'\n : props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.4)'};\n border-radius: 2px;\n opacity: ${(props) => (props.$isDragging ? 1 : 0.6)};\n transition:\n opacity 0.2s,\n background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.1)'};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) =>\n props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface AnnotationBoxComponentProps {\n annotationId: string;\n annotationIndex: number;\n startPosition: number;\n endPosition: number;\n label?: string;\n color?: string;\n isActive?: boolean;\n onClick?: () => void;\n editable?: boolean; // Whether to show drag handles\n}\n\nexport const AnnotationBox: FunctionComponent<AnnotationBoxComponentProps> = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = '#ff9800',\n isActive = false,\n onClick,\n editable = true,\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n\n // Left (start) boundary draggable\n // feedback: 'none' disables the Feedback plugin for this draggable — resize visual\n // feedback comes from React state updates repositioning the annotation, not CSS translate.\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const { ref: leftRef, isDragSource: isLeftDragging } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const { ref: rightRef, isDragSource: isRightDragging } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n if (width <= 0) {\n return null;\n }\n\n const handleHandleClick = (e: React.MouseEvent) => {\n // Prevent clicks on resize handles from bubbling to annotation box\n e.stopPropagation();\n };\n\n return (\n <Wrapper $left={startPosition} $width={width}>\n <Box $color={color} $isActive={isActive} onClick={onClick}>\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={leftRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={rightRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n />\n )}\n </Wrapper>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { usePlaylistInfo } from '@waveform-playlist/ui-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $controlWidth: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n display: flex;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\n\nconst ControlsPlaceholder = styled.div<{ $controlWidth: number }>`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n`;\n\nconst BoxesContainer = styled.div<{ $offset?: number }>`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationBoxesWrapperProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationBoxesWrapper: FunctionComponent<AnnotationBoxesWrapperProps> = ({\n children,\n className,\n height = 30,\n offset = 0,\n width,\n}) => {\n const {\n controls: { show, width: controlWidth },\n } = usePlaylistInfo();\n\n return (\n <Container\n className={className}\n $height={height}\n $controlWidth={show ? controlWidth : 0}\n $width={width}\n >\n <ControlsPlaceholder $controlWidth={show ? controlWidth : 0} />\n <BoxesContainer $offset={offset}>{children}</BoxesContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { usePlaylistInfo } from '@waveform-playlist/ui-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $controlWidth: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n display: flex;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n`;\n\nconst ControlsPlaceholder = styled.div<{ $controlWidth: number }>`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n font-weight: bold;\n`;\n\nconst AnnotationsContainer = styled.div<{ $offset?: number }>`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationsTrackProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationsTrack: FunctionComponent<AnnotationsTrackProps> = ({\n children,\n className,\n height = 100,\n offset = 0,\n width,\n}) => {\n const {\n controls: { show, width: controlWidth },\n } = usePlaylistInfo();\n\n return (\n <Container\n className={className}\n $height={height}\n $controlWidth={show ? controlWidth : 0}\n $width={width}\n >\n <ControlsPlaceholder $controlWidth={show ? controlWidth : 0}>Annotations</ControlsPlaceholder>\n <AnnotationsContainer $offset={offset}>{children}</AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\ninterface ContainerProps {\n $height?: number;\n}\n\nconst Container = styled.div<ContainerProps>`\n background: ${(props) => props.theme?.backgroundColor || '#fff'};\n ${(props) => (props.$height ? `height: ${props.$height}px;` : 'max-height: 200px;')}\n overflow-y: auto;\n padding: 8px;\n`;\n\nconst AnnotationItem = styled.div<{ $isActive?: boolean }>`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => (props.$isActive ? '#ff9800' : 'transparent')};\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.15)' : 'transparent')};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)'\n : 'none'};\n\n &:hover {\n background: ${(props) =>\n props.$isActive\n ? 'rgba(255, 152, 0, 0.2)'\n : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)'};\n border-left-color: ${(props) =>\n props.$isActive ? '#ff9800' : props.theme?.borderColor || '#ddd'};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\n\nconst AnnotationHeader = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\n\nconst AnnotationInfo = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\n\nconst AnnotationIdLabel = styled.span<{ $isEditable?: boolean }>`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\nconst TimeRange = styled.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || '#555'};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\n\nconst AnnotationControls = styled.div`\n display: flex;\n gap: 6px;\n`;\n\nconst ControlButton = styled.button`\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n color: ${(props) => props.theme?.textColor || '#333'};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\n\nconst AnnotationTextContent = styled.div<{ $isEditable?: boolean }>`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || '#2a2a2a'};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n padding: ${(props) => (props.$isEditable ? '6px' : '0')};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\n// Re-export from core\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/core';\n\nexport interface AnnotationTextProps {\n annotations: AnnotationData[];\n activeAnnotationId?: string;\n shouldScrollToActive?: boolean;\n /** Where to position the active annotation when scrolling: 'center', 'start', 'end', or 'nearest'. Defaults to 'center'. */\n scrollActivePosition?: ScrollLogicalPosition;\n /** Which scrollable containers to scroll: 'nearest' (only the annotation list) or 'all' (including viewport). Defaults to 'nearest'. */\n scrollActiveContainer?: 'nearest' | 'all';\n editable?: boolean;\n controls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n height?: number;\n onAnnotationClick?: (annotation: AnnotationData) => void;\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n /**\n * Custom render function for annotation items.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation in the list.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n}\n\nconst AnnotationTextComponent: FunctionComponent<AnnotationTextProps> = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n scrollActivePosition = 'center',\n scrollActiveContainer = 'nearest',\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem,\n}) => {\n const activeAnnotationRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const prevActiveIdRef = useRef<string | undefined>(undefined);\n\n // Track component renders and scroll position\n useEffect(() => {\n // Render tracking removed\n });\n\n // Track scroll changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n // Scroll tracking removed\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, []);\n\n // Auto-scroll to active annotation when it changes\n useEffect(() => {\n // Only scroll if parent says we should (prevents scrolling on remount after pause)\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: scrollActivePosition,\n container: scrollActiveContainer,\n } as ScrollIntoViewOptions);\n }\n\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive, scrollActivePosition, scrollActiveContainer]);\n\n const formatTime = (seconds: number): string => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return '0:00.000';\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, '0')}`;\n };\n\n const handleTextEdit = (index: number, newText: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split('\\n'),\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleIdEdit = (index: number, newId: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const trimmedId = newId.trim();\n if (!trimmedId) return; // Don't allow empty IDs\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId,\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleControlClick = (\n control: AnnotationAction,\n annotation: AnnotationData,\n index: number\n ) => {\n if (!onAnnotationUpdate) return;\n\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n\n const getIconClass = (classString: string) => {\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <Container ref={containerRef} $height={height}>\n {annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n\n // Use custom render function if provided\n if (renderAnnotationItem) {\n return (\n <div key={annotation.id} ref={isActive ? activeAnnotationRef : null}>\n {renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime,\n })}\n </div>\n );\n }\n\n // Default rendering\n return (\n <AnnotationItem\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n $isActive={isActive}\n onClick={handleClick}\n >\n <AnnotationHeader>\n <AnnotationInfo>\n <AnnotationIdLabel\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleIdEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.id}\n </AnnotationIdLabel>\n <TimeRange>\n {formatTime(annotation.start)} - {formatTime(annotation.end)}\n </TimeRange>\n </AnnotationInfo>\n {controls.length > 0 && (\n <AnnotationControls onClick={(e) => e.stopPropagation()}>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={() => handleControlClick(control, annotation, index)}\n >\n {control.text ? (\n control.text\n ) : (\n <i className={getIconClass(control.class || '')} />\n )}\n </ControlButton>\n ))}\n </AnnotationControls>\n )}\n </AnnotationHeader>\n <AnnotationTextContent\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleTextEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.lines.join('\\n')}\n </AnnotationTextContent>\n </AnnotationItem>\n );\n })}\n </Container>\n );\n};\n\n// Memoize to prevent unnecessary remounting when parent re-renders\nexport const AnnotationText = React.memo(AnnotationTextComponent);\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface ContinuousPlayCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling continuous play of annotations.\n * When enabled, playback continues from one annotation to the next without stopping.\n */\nexport const ContinuousPlayCheckbox: React.FC<ContinuousPlayCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"continuous-play\"\n className=\"continuous-play\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"continuous-play\">Continuous Play</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface LinkEndpointsCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling linked endpoints between annotations.\n * When enabled, the end time of one annotation is automatically linked to the start time of the next.\n */\nexport const LinkEndpointsCheckbox: React.FC<LinkEndpointsCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"link-endpoints\"\n className=\"link-endpoints\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"link-endpoints\">Link Endpoints</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface EditableCheckboxProps {\n checked: boolean;\n onChange: (enabled: boolean) => void;\n className?: string;\n}\n\nexport const EditableCheckbox: React.FC<EditableCheckboxProps> = ({\n checked,\n onChange,\n className,\n}) => {\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"editable-annotations\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n />\n <BaseCheckboxLabel htmlFor=\"editable-annotations\">Editable Annotations</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport styled from 'styled-components';\nimport { serializeAeneas } from '../parsers/aeneas';\nimport type { AnnotationData } from '../types';\n\nconst StyledButton = styled.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n color: ${(props) => props.theme?.textColor || '#333'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n border-radius: ${(props) => props.theme?.borderRadius || '4px'};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || 'inherit'};\n font-size: ${(props) => props.theme?.fontSize || '14px'};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || '#007bff'}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\n\nexport interface DownloadAnnotationsButtonProps {\n annotations: AnnotationData[];\n filename?: string;\n disabled?: boolean;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport const DownloadAnnotationsButton: React.FC<DownloadAnnotationsButtonProps> = ({\n annotations,\n filename = 'annotations.json',\n disabled = false,\n className,\n children = 'Download JSON',\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n\n // Serialize annotations to Aeneas JSON format\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n // Create a blob and download link\n const blob = new Blob([jsonString], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n\n // Trigger download\n document.body.appendChild(link);\n link.click();\n\n // Cleanup\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n\n return (\n <StyledButton\n onClick={handleDownload}\n disabled={disabled || annotations.length === 0}\n className={className}\n title={\n annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'\n }\n >\n {children}\n </StyledButton>\n );\n};\n","import React from 'react';\nimport { AnnotationIntegrationProvider } from '@waveform-playlist/browser';\nimport type { AnnotationIntegration } from '@waveform-playlist/browser';\nimport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nimport { AnnotationText } from './components/AnnotationText';\nimport { AnnotationBox } from './components/AnnotationBox';\nimport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nimport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nimport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nimport { EditableCheckbox } from './components/EditableCheckbox';\nimport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\n\nconst annotationIntegration: AnnotationIntegration = {\n parseAeneas: parseAeneas as (data: unknown) => import('@waveform-playlist/core').AnnotationData,\n serializeAeneas: serializeAeneas as (\n annotation: import('@waveform-playlist/core').AnnotationData\n ) => unknown,\n AnnotationText,\n AnnotationBox,\n AnnotationBoxesWrapper,\n ContinuousPlayCheckbox,\n LinkEndpointsCheckbox,\n EditableCheckbox,\n DownloadAnnotationsButton,\n};\n\nexport const AnnotationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n return (\n <AnnotationIntegrationProvider value={annotationIntegration}>\n {children}\n </AnnotationIntegrationProvider>\n );\n};\n","import { useState, useCallback } from 'react';\nimport type { AnnotationData } from '../types';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\nexport interface UseAnnotationControlsOptions {\n initialContinuousPlay?: boolean;\n initialLinkEndpoints?: boolean;\n}\n\nexport interface AnnotationUpdateParams {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationData[];\n duration: number;\n linkEndpoints: boolean;\n}\n\nexport interface UseAnnotationControlsReturn {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n setContinuousPlay: (value: boolean) => void;\n setLinkEndpoints: (value: boolean) => void;\n updateAnnotationBoundaries: (params: AnnotationUpdateParams) => AnnotationData[];\n}\n\n/**\n * Hook for managing annotation control state and boundary logic.\n * Handles continuous play mode and linked endpoints behavior.\n */\nexport const useAnnotationControls = (\n options: UseAnnotationControlsOptions = {}\n): UseAnnotationControlsReturn => {\n const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;\n\n const [continuousPlay, setContinuousPlay] = useState(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState(initialLinkEndpoints);\n\n /**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n * Note: linkEndpoints is passed as a parameter to ensure it uses the current value from context.\n */\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n }: AnnotationUpdateParams): AnnotationData[] => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex > 0 &&\n constrainedStart < updatedAnnotations[annotationIndex - 1].end\n ) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex < updatedAnnotations.length - 1 &&\n constrainedEnd > updatedAnnotations[annotationIndex + 1].start\n ) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n },\n []\n );\n\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries,\n };\n};\n"],"mappings":"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","names":["styled","jsx","jsxs","styled","jsx","jsxs","styled","usePlaylistInfo","jsx","jsxs","Container","ControlsPlaceholder","React","styled","jsx","jsxs","Container","ControlButton","AnnotationText","jsx","jsxs","BaseCheckboxWrapper","BaseCheckbox","BaseCheckboxLabel","jsx","jsxs","BaseCheckboxWrapper","BaseCheckbox","BaseCheckboxLabel","jsx","jsxs","styled","jsx","styled","jsx","AnnotationText","useState"]}
1
+ {"version":3,"sources":["../src/parsers/aeneas.ts","../src/components/Annotation.tsx","../src/components/AnnotationBox.tsx","../src/components/AnnotationBoxesWrapper.tsx","../src/components/AnnotationsTrack.tsx","../src/components/AnnotationText.tsx","../src/components/ContinuousPlayCheckbox.tsx","../src/components/LinkEndpointsCheckbox.tsx","../src/components/EditableCheckbox.tsx","../src/components/DownloadAnnotationsButton.tsx","../src/AnnotationProvider.tsx","../src/hooks/useAnnotationControls.ts"],"sourcesContent":["import type { AnnotationData } from '@waveform-playlist/core';\n\nexport interface AeneasFragment {\n begin: string;\n end: string;\n id: string;\n language: string;\n lines: string[];\n}\n\nexport function parseAeneas(data: AeneasFragment): AnnotationData {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n language: data.language,\n };\n}\n\nexport function serializeAeneas(annotation: AnnotationData): AeneasFragment {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.language || 'en',\n };\n}\n","import React, { FunctionComponent, useState } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\ninterface AnnotationOverlayProps {\n readonly $left: number;\n readonly $width: number;\n readonly $color: string;\n}\n\nconst AnnotationOverlay = styled.div.attrs<AnnotationOverlayProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<AnnotationOverlayProps>`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\n\nconst AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\n\nconst EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4caf50;\n }\n`;\n\nconst ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\n\nconst ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\n\n// Re-export shared annotation types from core\nexport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n} from '@waveform-playlist/core';\n\nexport interface AnnotationProps {\n annotation: AnnotationData;\n index: number;\n allAnnotations: AnnotationData[];\n startPosition: number; // Start position in pixels\n endPosition: number; // End position in pixels\n color?: string;\n editable?: boolean;\n controls?: AnnotationAction[];\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n annotationListConfig?: AnnotationActionOptions;\n onClick?: (annotation: AnnotationData) => void;\n}\n\nexport const Annotation: FunctionComponent<AnnotationProps> = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = '#ff9800',\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick,\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join('\\n'));\n const width = Math.max(0, endPosition - startPosition);\n\n if (width <= 0) {\n return null;\n }\n\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n\n const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setEditedText(e.target.value);\n };\n\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split('\\n');\n if (newLines.join('\\n') !== annotation.lines.join('\\n')) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n\n const handleControlClick = (control: AnnotationAction) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n\n const getIconClass = (classString: string) => {\n // Convert \"fas.fa-minus\" to \"fas fa-minus\"\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <AnnotationOverlay\n $left={startPosition}\n $width={width}\n $color={color}\n onClick={handleClick}\n onDoubleClick={handleDoubleClick}\n >\n {controls.length > 0 && (\n <ControlsBar>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={(e) => {\n e.stopPropagation();\n handleControlClick(control);\n }}\n >\n {control.text ? control.text : <i className={getIconClass(control.class || '')} />}\n </ControlButton>\n ))}\n </ControlsBar>\n )}\n {isEditing ? (\n <EditableText\n value={editedText}\n onChange={handleTextChange}\n onBlur={handleTextBlur}\n autoFocus\n onClick={(e) => e.stopPropagation()}\n onDoubleClick={(e) => e.stopPropagation()}\n />\n ) : (\n <AnnotationText>{annotation.lines.join('\\n')}</AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/react';\n\ninterface WrapperProps {\n readonly $left: number;\n readonly $width: number;\n}\n\n// Wrapper positions the annotation and contains both Box and ResizeHandles as siblings\nconst Wrapper = styled.div.attrs<WrapperProps>((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`,\n },\n}))<WrapperProps>`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\n\ninterface BoxProps {\n readonly $color: string;\n readonly $isActive?: boolean;\n}\n\nconst Box = styled.div<BoxProps>`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) =>\n props.$isActive\n ? props.theme?.annotationBoxActiveBackground || 'rgba(255, 200, 100, 0.95)'\n : props.theme?.annotationBoxBackground || 'rgba(255, 255, 255, 0.85)'};\n border: ${(props) => (props.$isActive ? '3px' : '2px')} solid\n ${(props) =>\n props.$isActive ? props.theme?.annotationBoxActiveBorder || '#ff9800' : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)'\n : '0 1px 3px rgba(0, 0, 0, 0.1)'};\n\n &:hover {\n background: ${(props) =>\n props.theme?.annotationBoxHoverBackground || 'rgba(255, 255, 255, 0.98)'};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || '#ff9800'};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\n\nconst Label = styled.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || '#2a2a2a'};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\n\ninterface ResizeHandleStyledProps {\n $position: 'left' | 'right';\n $isDragging?: boolean;\n}\n\n// ResizeHandles sit inside their annotation's bounds so adjacent annotations'\n// handles never overlap — each handle is independently grabbable.\nconst ResizeHandle = styled.div<ResizeHandleStyledProps>`\n position: absolute;\n top: 0;\n ${(props) => (props.$position === 'left' ? 'left: 0' : 'right: 0')};\n width: 8px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.2)'\n : 'transparent'};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) =>\n props.$isDragging\n ? props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.8)'\n : props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.4)'};\n border-radius: 2px;\n opacity: ${(props) => (props.$isDragging ? 1 : 0.6)};\n transition:\n opacity 0.2s,\n background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || 'rgba(0, 0, 0, 0.1)'};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) =>\n props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface AnnotationBoxComponentProps {\n annotationId: string;\n annotationIndex: number;\n startPosition: number;\n endPosition: number;\n label?: string;\n color?: string;\n isActive?: boolean;\n onClick?: () => void;\n editable?: boolean; // Whether to show drag handles\n}\n\nexport const AnnotationBox: FunctionComponent<AnnotationBoxComponentProps> = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = '#ff9800',\n isActive = false,\n onClick,\n editable = true,\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n\n // Left (start) boundary draggable\n // feedback: 'none' disables the Feedback plugin for this draggable — resize visual\n // feedback comes from React state updates repositioning the annotation, not CSS translate.\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const { ref: leftRef, isDragSource: isLeftDragging } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const { ref: rightRef, isDragSource: isRightDragging } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n feedback: 'none',\n });\n\n if (width <= 0) {\n return null;\n }\n\n const handleHandleClick = (e: React.MouseEvent) => {\n // Prevent clicks on resize handles from bubbling to annotation box\n e.stopPropagation();\n };\n\n return (\n <Wrapper $left={startPosition} $width={width}>\n <Box $color={color} $isActive={isActive} onClick={onClick}>\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={leftRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={rightRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n />\n )}\n </Wrapper>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\n\nconst BoxesContainer = styled.div<{ $offset?: number }>`\n position: relative;\n height: 100%;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationBoxesWrapperProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationBoxesWrapper: FunctionComponent<AnnotationBoxesWrapperProps> = ({\n children,\n className,\n height = 30,\n offset = 0,\n width,\n}) => {\n return (\n <Container className={className} $height={height} $width={width}>\n <BoxesContainer $offset={offset}>{children}</BoxesContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\n\ninterface ContainerProps {\n readonly $height: number;\n readonly $width?: number;\n}\n\nconst Container = styled.div.attrs<ContainerProps>((props) => ({\n style: {\n height: `${props.$height}px`,\n },\n}))<ContainerProps>`\n position: relative;\n ${(props) => props.$width !== undefined && `width: ${props.$width}px;`}\n background: transparent;\n`;\n\nconst AnnotationsContainer = styled.div<{ $offset?: number }>`\n position: relative;\n height: 100%;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\n\nexport interface AnnotationsTrackProps {\n className?: string;\n children?: React.ReactNode;\n height?: number;\n offset?: number;\n width?: number;\n}\n\nexport const AnnotationsTrack: FunctionComponent<AnnotationsTrackProps> = ({\n children,\n className,\n height = 100,\n offset = 0,\n width,\n}) => {\n return (\n <Container className={className} $height={height} $width={width}>\n <AnnotationsContainer $offset={offset}>{children}</AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type {\n AnnotationData,\n AnnotationAction,\n AnnotationActionOptions,\n RenderAnnotationItemProps,\n} from '@waveform-playlist/core';\n\ninterface ContainerProps {\n $height?: number;\n}\n\nconst Container = styled.div<ContainerProps>`\n background: ${(props) => props.theme?.backgroundColor || '#fff'};\n ${(props) => (props.$height ? `height: ${props.$height}px;` : 'max-height: 200px;')}\n overflow-y: auto;\n padding: 8px;\n`;\n\nconst AnnotationItem = styled.div<{ $isActive?: boolean }>`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => (props.$isActive ? '#ff9800' : 'transparent')};\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.15)' : 'transparent')};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) =>\n props.$isActive\n ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)'\n : 'none'};\n\n &:hover {\n background: ${(props) =>\n props.$isActive\n ? 'rgba(255, 152, 0, 0.2)'\n : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)'};\n border-left-color: ${(props) =>\n props.$isActive ? '#ff9800' : props.theme?.borderColor || '#ddd'};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\n\nconst AnnotationHeader = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\n\nconst AnnotationInfo = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\n\nconst AnnotationIdLabel = styled.span<{ $isEditable?: boolean }>`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || '#666'};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\nconst TimeRange = styled.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || '#555'};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\n\nconst AnnotationControls = styled.div`\n display: flex;\n gap: 6px;\n`;\n\nconst ControlButton = styled.button`\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n color: ${(props) => props.theme?.textColor || '#333'};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\n\nconst AnnotationTextContent = styled.div<{ $isEditable?: boolean }>`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || '#2a2a2a'};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) =>\n props.$isEditable ? `1px dashed ${props.theme?.borderColor || '#ddd'}` : 'none'};\n padding: ${(props) => (props.$isEditable ? '6px' : '0')};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\n\n// Re-export from core\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/core';\n\nexport interface AnnotationTextProps {\n annotations: AnnotationData[];\n activeAnnotationId?: string;\n shouldScrollToActive?: boolean;\n /** Where to position the active annotation when scrolling: 'center', 'start', 'end', or 'nearest'. Defaults to 'center'. */\n scrollActivePosition?: ScrollLogicalPosition;\n /** Which scrollable containers to scroll: 'nearest' (only the annotation list) or 'all' (including viewport). Defaults to 'nearest'. */\n scrollActiveContainer?: 'nearest' | 'all';\n editable?: boolean;\n controls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n height?: number;\n onAnnotationClick?: (annotation: AnnotationData) => void;\n onAnnotationUpdate?: (updatedAnnotations: AnnotationData[]) => void;\n /**\n * Custom render function for annotation items.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation in the list.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n}\n\nconst AnnotationTextComponent: FunctionComponent<AnnotationTextProps> = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n scrollActivePosition = 'center',\n scrollActiveContainer = 'nearest',\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem,\n}) => {\n const activeAnnotationRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const prevActiveIdRef = useRef<string | undefined>(undefined);\n\n // Track component renders and scroll position\n useEffect(() => {\n // Render tracking removed\n });\n\n // Track scroll changes\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleScroll = () => {\n // Scroll tracking removed\n };\n\n container.addEventListener('scroll', handleScroll);\n return () => container.removeEventListener('scroll', handleScroll);\n }, []);\n\n // Auto-scroll to active annotation when it changes\n useEffect(() => {\n // Only scroll if parent says we should (prevents scrolling on remount after pause)\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: 'smooth',\n block: scrollActivePosition,\n container: scrollActiveContainer,\n } as ScrollIntoViewOptions);\n }\n\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive, scrollActivePosition, scrollActiveContainer]);\n\n const formatTime = (seconds: number): string => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return '0:00.000';\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, '0')}`;\n };\n\n const handleTextEdit = (index: number, newText: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split('\\n'),\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleIdEdit = (index: number, newId: string) => {\n if (!editable || !onAnnotationUpdate) return;\n\n const trimmedId = newId.trim();\n if (!trimmedId) return; // Don't allow empty IDs\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId,\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n\n const handleControlClick = (\n control: AnnotationAction,\n annotation: AnnotationData,\n index: number\n ) => {\n if (!onAnnotationUpdate) return;\n\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n\n const getIconClass = (classString: string) => {\n return classString.replace(/\\./g, ' ');\n };\n\n return (\n <Container ref={containerRef} $height={height}>\n {annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n\n // Use custom render function if provided\n if (renderAnnotationItem) {\n return (\n <div key={annotation.id} ref={isActive ? activeAnnotationRef : null}>\n {renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime,\n })}\n </div>\n );\n }\n\n // Default rendering\n return (\n <AnnotationItem\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n $isActive={isActive}\n onClick={handleClick}\n >\n <AnnotationHeader>\n <AnnotationInfo>\n <AnnotationIdLabel\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleIdEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.id}\n </AnnotationIdLabel>\n <TimeRange>\n {formatTime(annotation.start)} - {formatTime(annotation.end)}\n </TimeRange>\n </AnnotationInfo>\n {controls.length > 0 && (\n <AnnotationControls onClick={(e) => e.stopPropagation()}>\n {controls.map((control, idx) => (\n <ControlButton\n key={idx}\n title={control.title}\n onClick={() => handleControlClick(control, annotation, index)}\n >\n {control.text ? (\n control.text\n ) : (\n <i className={getIconClass(control.class || '')} />\n )}\n </ControlButton>\n ))}\n </AnnotationControls>\n )}\n </AnnotationHeader>\n <AnnotationTextContent\n $isEditable={editable}\n contentEditable={editable}\n suppressContentEditableWarning\n onBlur={(e) => handleTextEdit(index, e.currentTarget.textContent || '')}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).blur();\n }\n }}\n >\n {annotation.lines.join('\\n')}\n </AnnotationTextContent>\n </AnnotationItem>\n );\n })}\n </Container>\n );\n};\n\n// Memoize to prevent unnecessary remounting when parent re-renders\nexport const AnnotationText = React.memo(AnnotationTextComponent);\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface ContinuousPlayCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling continuous play of annotations.\n * When enabled, playback continues from one annotation to the next without stopping.\n */\nexport const ContinuousPlayCheckbox: React.FC<ContinuousPlayCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"continuous-play\"\n className=\"continuous-play\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"continuous-play\">Continuous Play</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface LinkEndpointsCheckboxProps {\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * Checkbox control for enabling/disabling linked endpoints between annotations.\n * When enabled, the end time of one annotation is automatically linked to the start time of the next.\n */\nexport const LinkEndpointsCheckbox: React.FC<LinkEndpointsCheckboxProps> = ({\n checked,\n onChange,\n disabled = false,\n className,\n}) => {\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.checked);\n };\n\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"link-endpoints\"\n className=\"link-endpoints\"\n checked={checked}\n onChange={handleChange}\n disabled={disabled}\n />\n <BaseCheckboxLabel htmlFor=\"link-endpoints\">Link Endpoints</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport {\n BaseCheckboxWrapper,\n BaseCheckbox,\n BaseCheckboxLabel,\n} from '@waveform-playlist/ui-components';\n\nexport interface EditableCheckboxProps {\n checked: boolean;\n onChange: (enabled: boolean) => void;\n className?: string;\n}\n\nexport const EditableCheckbox: React.FC<EditableCheckboxProps> = ({\n checked,\n onChange,\n className,\n}) => {\n return (\n <BaseCheckboxWrapper className={className}>\n <BaseCheckbox\n type=\"checkbox\"\n id=\"editable-annotations\"\n checked={checked}\n onChange={(e) => onChange(e.target.checked)}\n />\n <BaseCheckboxLabel htmlFor=\"editable-annotations\">Editable Annotations</BaseCheckboxLabel>\n </BaseCheckboxWrapper>\n );\n};\n","import React from 'react';\nimport styled from 'styled-components';\nimport { serializeAeneas } from '../parsers/aeneas';\nimport type { AnnotationData } from '../types';\n\nconst StyledButton = styled.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || '#f5f5f5'};\n color: ${(props) => props.theme?.textColor || '#333'};\n border: 1px solid ${(props) => props.theme?.borderColor || '#ccc'};\n border-radius: ${(props) => props.theme?.borderRadius || '4px'};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || 'inherit'};\n font-size: ${(props) => props.theme?.fontSize || '14px'};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || '#3d3d3d'};\n border-color: ${(props) => props.theme?.textColorMuted || '#999'};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || '#007bff'}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\n\nexport interface DownloadAnnotationsButtonProps {\n annotations: AnnotationData[];\n filename?: string;\n disabled?: boolean;\n className?: string;\n children?: React.ReactNode;\n}\n\nexport const DownloadAnnotationsButton: React.FC<DownloadAnnotationsButtonProps> = ({\n annotations,\n filename = 'annotations.json',\n disabled = false,\n className,\n children = 'Download JSON',\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n\n // Serialize annotations to Aeneas JSON format\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n\n // Create a blob and download link\n const blob = new Blob([jsonString], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n\n // Trigger download\n document.body.appendChild(link);\n link.click();\n\n // Cleanup\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n\n return (\n <StyledButton\n onClick={handleDownload}\n disabled={disabled || annotations.length === 0}\n className={className}\n title={\n annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'\n }\n >\n {children}\n </StyledButton>\n );\n};\n","import React from 'react';\nimport { AnnotationIntegrationProvider } from '@waveform-playlist/browser';\nimport type { AnnotationIntegration } from '@waveform-playlist/browser';\nimport { parseAeneas, serializeAeneas } from './parsers/aeneas';\nimport { AnnotationText } from './components/AnnotationText';\nimport { AnnotationBox } from './components/AnnotationBox';\nimport { AnnotationBoxesWrapper } from './components/AnnotationBoxesWrapper';\nimport { ContinuousPlayCheckbox } from './components/ContinuousPlayCheckbox';\nimport { LinkEndpointsCheckbox } from './components/LinkEndpointsCheckbox';\nimport { EditableCheckbox } from './components/EditableCheckbox';\nimport { DownloadAnnotationsButton } from './components/DownloadAnnotationsButton';\n\nconst annotationIntegration: AnnotationIntegration = {\n parseAeneas: parseAeneas as (data: unknown) => import('@waveform-playlist/core').AnnotationData,\n serializeAeneas: serializeAeneas as (\n annotation: import('@waveform-playlist/core').AnnotationData\n ) => unknown,\n AnnotationText,\n AnnotationBox,\n AnnotationBoxesWrapper,\n ContinuousPlayCheckbox,\n LinkEndpointsCheckbox,\n EditableCheckbox,\n DownloadAnnotationsButton,\n};\n\nexport const AnnotationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n return (\n <AnnotationIntegrationProvider value={annotationIntegration}>\n {children}\n </AnnotationIntegrationProvider>\n );\n};\n","import { useState, useCallback } from 'react';\nimport type { AnnotationData } from '../types';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\nexport interface UseAnnotationControlsOptions {\n initialContinuousPlay?: boolean;\n initialLinkEndpoints?: boolean;\n}\n\nexport interface AnnotationUpdateParams {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationData[];\n duration: number;\n linkEndpoints: boolean;\n}\n\nexport interface UseAnnotationControlsReturn {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n setContinuousPlay: (value: boolean) => void;\n setLinkEndpoints: (value: boolean) => void;\n updateAnnotationBoundaries: (params: AnnotationUpdateParams) => AnnotationData[];\n}\n\n/**\n * Hook for managing annotation control state and boundary logic.\n * Handles continuous play mode and linked endpoints behavior.\n */\nexport const useAnnotationControls = (\n options: UseAnnotationControlsOptions = {}\n): UseAnnotationControlsReturn => {\n const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;\n\n const [continuousPlay, setContinuousPlay] = useState(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState(initialLinkEndpoints);\n\n /**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n * Note: linkEndpoints is passed as a parameter to ensure it uses the current value from context.\n */\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n }: AnnotationUpdateParams): AnnotationData[] => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex > 0 &&\n constrainedStart < updatedAnnotations[annotationIndex - 1].end\n ) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (\n !shouldLinkEndpoints &&\n annotationIndex < updatedAnnotations.length - 1 &&\n constrainedEnd > updatedAnnotations[annotationIndex + 1].start\n ) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n },\n []\n );\n\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries,\n };\n};\n"],"mappings":"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","names":["styled","jsx","jsxs","styled","jsx","styled","jsx","Container","React","styled","jsx","jsxs","Container","ControlButton","AnnotationText","jsx","jsxs","BaseCheckboxWrapper","BaseCheckbox","BaseCheckboxLabel","jsx","jsxs","BaseCheckboxWrapper","BaseCheckbox","BaseCheckboxLabel","jsx","jsxs","styled","jsx","styled","jsx","AnnotationText","useState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waveform-playlist/annotations",
3
- "version": "9.0.3",
3
+ "version": "9.1.0",
4
4
  "description": "Annotation support for waveform-playlist",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -39,17 +39,17 @@
39
39
  "@types/styled-components": "^5.1.26",
40
40
  "tsup": "^8.0.1",
41
41
  "typescript": "^5.3.3",
42
- "@waveform-playlist/browser": "9.0.3"
42
+ "@waveform-playlist/browser": "9.1.0"
43
43
  },
44
44
  "dependencies": {
45
- "@waveform-playlist/ui-components": "9.0.3",
46
- "@waveform-playlist/core": "9.0.3"
45
+ "@waveform-playlist/ui-components": "9.1.0",
46
+ "@waveform-playlist/core": "9.1.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@dnd-kit/react": "^0.3.0",
50
50
  "react": "^18.0.0",
51
51
  "styled-components": "^6.0.0",
52
- "@waveform-playlist/browser": "9.0.3"
52
+ "@waveform-playlist/browser": "9.1.0"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsup",