@waveform-playlist/annotations 7.1.1 → 7.1.3
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 +21 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -127,7 +127,7 @@ var EditableText = import_styled_components.default.textarea`
|
|
|
127
127
|
|
|
128
128
|
&:focus {
|
|
129
129
|
outline: none;
|
|
130
|
-
border-color: #
|
|
130
|
+
border-color: #4caf50;
|
|
131
131
|
}
|
|
132
132
|
`;
|
|
133
133
|
var ControlsBar = import_styled_components.default.div`
|
|
@@ -277,7 +277,8 @@ var Box = import_styled_components2.default.div`
|
|
|
277
277
|
right: 0;
|
|
278
278
|
height: 100%;
|
|
279
279
|
background: ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBackground || "rgba(255, 200, 100, 0.95)" : props.theme?.annotationBoxBackground || "rgba(255, 255, 255, 0.85)"};
|
|
280
|
-
border: ${(props) => props.$isActive ? "3px" : "2px"} solid
|
|
280
|
+
border: ${(props) => props.$isActive ? "3px" : "2px"} solid
|
|
281
|
+
${(props) => props.$isActive ? props.theme?.annotationBoxActiveBorder || "#ff9800" : props.$color};
|
|
281
282
|
border-radius: 4px;
|
|
282
283
|
cursor: pointer;
|
|
283
284
|
pointer-events: auto;
|
|
@@ -330,7 +331,9 @@ var ResizeHandle = import_styled_components2.default.div`
|
|
|
330
331
|
background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleActiveColor || "rgba(0, 0, 0, 0.8)" : props.theme?.annotationResizeHandleColor || "rgba(0, 0, 0, 0.4)"};
|
|
331
332
|
border-radius: 2px;
|
|
332
333
|
opacity: ${(props) => props.$isDragging ? 1 : 0.6};
|
|
333
|
-
transition:
|
|
334
|
+
transition:
|
|
335
|
+
opacity 0.2s,
|
|
336
|
+
background 0.2s;
|
|
334
337
|
}
|
|
335
338
|
|
|
336
339
|
&:hover {
|
|
@@ -389,15 +392,7 @@ var AnnotationBox = ({
|
|
|
389
392
|
e.stopPropagation();
|
|
390
393
|
};
|
|
391
394
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Wrapper, { $left: startPosition, $width: width, children: [
|
|
392
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
393
|
-
Box,
|
|
394
|
-
{
|
|
395
|
-
$color: color,
|
|
396
|
-
$isActive: isActive,
|
|
397
|
-
onClick,
|
|
398
|
-
children: label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: label })
|
|
399
|
-
}
|
|
400
|
-
),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box, { $color: color, $isActive: isActive, onClick, children: label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Label, { children: label }) }),
|
|
401
396
|
editable && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
402
397
|
ResizeHandle,
|
|
403
398
|
{
|
|
@@ -406,7 +401,9 @@ var AnnotationBox = ({
|
|
|
406
401
|
$isDragging: isLeftDragging,
|
|
407
402
|
onClick: handleHandleClick,
|
|
408
403
|
...leftListeners,
|
|
409
|
-
onPointerDown: createPointerDownHandler(
|
|
404
|
+
onPointerDown: createPointerDownHandler(
|
|
405
|
+
leftListeners?.onPointerDown
|
|
406
|
+
),
|
|
410
407
|
...leftAttributes
|
|
411
408
|
}
|
|
412
409
|
),
|
|
@@ -418,7 +415,9 @@ var AnnotationBox = ({
|
|
|
418
415
|
$isDragging: isRightDragging,
|
|
419
416
|
onClick: handleHandleClick,
|
|
420
417
|
...rightListeners,
|
|
421
|
-
onPointerDown: createPointerDownHandler(
|
|
418
|
+
onPointerDown: createPointerDownHandler(
|
|
419
|
+
rightListeners?.onPointerDown
|
|
420
|
+
),
|
|
422
421
|
...rightAttributes
|
|
423
422
|
}
|
|
424
423
|
)
|
|
@@ -719,20 +718,13 @@ var AnnotationTextComponent = ({
|
|
|
719
718
|
const isActive = annotation.id === activeAnnotationId;
|
|
720
719
|
const handleClick = () => onAnnotationClick?.(annotation);
|
|
721
720
|
if (renderAnnotationItem) {
|
|
722
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
isActive,
|
|
730
|
-
onClick: handleClick,
|
|
731
|
-
formatTime
|
|
732
|
-
})
|
|
733
|
-
},
|
|
734
|
-
annotation.id
|
|
735
|
-
);
|
|
721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: isActive ? activeAnnotationRef : null, children: renderAnnotationItem({
|
|
722
|
+
annotation,
|
|
723
|
+
index,
|
|
724
|
+
isActive,
|
|
725
|
+
onClick: handleClick,
|
|
726
|
+
formatTime
|
|
727
|
+
}) }, annotation.id);
|
|
736
728
|
}
|
|
737
729
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
738
730
|
AnnotationItem,
|
|
@@ -964,10 +956,7 @@ var AnnotationProvider = ({ children }) => {
|
|
|
964
956
|
var import_react3 = require("react");
|
|
965
957
|
var LINK_THRESHOLD = 0.01;
|
|
966
958
|
var useAnnotationControls = (options = {}) => {
|
|
967
|
-
const {
|
|
968
|
-
initialContinuousPlay = false,
|
|
969
|
-
initialLinkEndpoints = true
|
|
970
|
-
} = options;
|
|
959
|
+
const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;
|
|
971
960
|
const [continuousPlay, setContinuousPlay] = (0, import_react3.useState)(initialContinuousPlay);
|
|
972
961
|
const [linkEndpoints, setLinkEndpoints] = (0, import_react3.useState)(initialLinkEndpoints);
|
|
973
962
|
const updateAnnotationBoundaries = (0, import_react3.useCallback)(
|
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 { AnnotationData, AnnotationAction, AnnotationActionOptions } 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 { AnnotationData, AnnotationAction, AnnotationActionOptions } 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>\n {annotation.lines.join('\\n')}\n </AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/core';\nimport type { DraggableAttributes } from '@dnd-kit/core';\nimport type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';\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) => 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 ${(props) => props.$isActive\n ? (props.theme?.annotationBoxActiveBorder || '#ff9800')\n : 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) => 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) => 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) => 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) => 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: opacity 0.2s, 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) => props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface DragHandleProps {\n attributes: DraggableAttributes;\n listeners: SyntheticListenerMap | undefined;\n setActivatorNodeRef: (element: HTMLElement | null) => void;\n isDragging: boolean;\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 const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging,\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging,\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n });\n\n if (width <= 0) {\n return null;\n }\n\n // Wrap @dnd-kit pointer handlers to also stop propagation\n // This prevents the ClickOverlay from capturing the event\n const createPointerDownHandler = (dndKitHandler?: (e: React.PointerEvent) => void) => {\n return (e: React.PointerEvent) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\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\n $color={color}\n $isActive={isActive}\n onClick={onClick}\n >\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={setLeftActivatorRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n {...leftListeners}\n onPointerDown={createPointerDownHandler(leftListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined)}\n {...leftAttributes}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={setRightActivatorRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n {...rightListeners}\n onPointerDown={createPointerDownHandler(rightListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined)}\n {...rightAttributes}\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}>\n {children}\n </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}>\n Annotations\n </ControlsPlaceholder>\n <AnnotationsContainer $offset={offset}>\n {children}\n </AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type { AnnotationData, AnnotationAction, AnnotationActionOptions, RenderAnnotationItemProps } 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) => (props.$isActive ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)' : 'none')};\n\n &:hover {\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.2)' : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)')};\n border-left-color: ${(props) => (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) => (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) => (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 = (control: AnnotationAction, annotation: AnnotationData, index: number) => {\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\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n >\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 ? control.text : <i className={getIconClass(control.class || '')} />}\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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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={annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'}\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 (annotation: import('@waveform-playlist/core').AnnotationData) => 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 {\n initialContinuousPlay = false,\n initialLinkEndpoints = true,\n } = 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 (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\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 (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\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_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/core';\nimport type { DraggableAttributes } from '@dnd-kit/core';\nimport type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';\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 DragHandleProps {\n attributes: DraggableAttributes;\n listeners: SyntheticListenerMap | undefined;\n setActivatorNodeRef: (element: HTMLElement | null) => void;\n isDragging: boolean;\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 const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging,\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging,\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n });\n\n if (width <= 0) {\n return null;\n }\n\n // Wrap @dnd-kit pointer handlers to also stop propagation\n // This prevents the ClickOverlay from capturing the event\n const createPointerDownHandler = (dndKitHandler?: (e: React.PointerEvent) => void) => {\n return (e: React.PointerEvent) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\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={setLeftActivatorRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n {...leftListeners}\n onPointerDown={createPointerDownHandler(\n leftListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined\n )}\n {...leftAttributes}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={setRightActivatorRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n {...rightListeners}\n onPointerDown={createPointerDownHandler(\n rightListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined\n )}\n {...rightAttributes}\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_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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -79,7 +79,7 @@ var EditableText = styled.textarea`
|
|
|
79
79
|
|
|
80
80
|
&:focus {
|
|
81
81
|
outline: none;
|
|
82
|
-
border-color: #
|
|
82
|
+
border-color: #4caf50;
|
|
83
83
|
}
|
|
84
84
|
`;
|
|
85
85
|
var ControlsBar = styled.div`
|
|
@@ -229,7 +229,8 @@ var Box = styled2.div`
|
|
|
229
229
|
right: 0;
|
|
230
230
|
height: 100%;
|
|
231
231
|
background: ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBackground || "rgba(255, 200, 100, 0.95)" : props.theme?.annotationBoxBackground || "rgba(255, 255, 255, 0.85)"};
|
|
232
|
-
border: ${(props) => props.$isActive ? "3px" : "2px"} solid
|
|
232
|
+
border: ${(props) => props.$isActive ? "3px" : "2px"} solid
|
|
233
|
+
${(props) => props.$isActive ? props.theme?.annotationBoxActiveBorder || "#ff9800" : props.$color};
|
|
233
234
|
border-radius: 4px;
|
|
234
235
|
cursor: pointer;
|
|
235
236
|
pointer-events: auto;
|
|
@@ -282,7 +283,9 @@ var ResizeHandle = styled2.div`
|
|
|
282
283
|
background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleActiveColor || "rgba(0, 0, 0, 0.8)" : props.theme?.annotationResizeHandleColor || "rgba(0, 0, 0, 0.4)"};
|
|
283
284
|
border-radius: 2px;
|
|
284
285
|
opacity: ${(props) => props.$isDragging ? 1 : 0.6};
|
|
285
|
-
transition:
|
|
286
|
+
transition:
|
|
287
|
+
opacity 0.2s,
|
|
288
|
+
background 0.2s;
|
|
286
289
|
}
|
|
287
290
|
|
|
288
291
|
&:hover {
|
|
@@ -341,15 +344,7 @@ var AnnotationBox = ({
|
|
|
341
344
|
e.stopPropagation();
|
|
342
345
|
};
|
|
343
346
|
return /* @__PURE__ */ jsxs2(Wrapper, { $left: startPosition, $width: width, children: [
|
|
344
|
-
/* @__PURE__ */ jsx2(
|
|
345
|
-
Box,
|
|
346
|
-
{
|
|
347
|
-
$color: color,
|
|
348
|
-
$isActive: isActive,
|
|
349
|
-
onClick,
|
|
350
|
-
children: label && /* @__PURE__ */ jsx2(Label, { children: label })
|
|
351
|
-
}
|
|
352
|
-
),
|
|
347
|
+
/* @__PURE__ */ jsx2(Box, { $color: color, $isActive: isActive, onClick, children: label && /* @__PURE__ */ jsx2(Label, { children: label }) }),
|
|
353
348
|
editable && /* @__PURE__ */ jsx2(
|
|
354
349
|
ResizeHandle,
|
|
355
350
|
{
|
|
@@ -358,7 +353,9 @@ var AnnotationBox = ({
|
|
|
358
353
|
$isDragging: isLeftDragging,
|
|
359
354
|
onClick: handleHandleClick,
|
|
360
355
|
...leftListeners,
|
|
361
|
-
onPointerDown: createPointerDownHandler(
|
|
356
|
+
onPointerDown: createPointerDownHandler(
|
|
357
|
+
leftListeners?.onPointerDown
|
|
358
|
+
),
|
|
362
359
|
...leftAttributes
|
|
363
360
|
}
|
|
364
361
|
),
|
|
@@ -370,7 +367,9 @@ var AnnotationBox = ({
|
|
|
370
367
|
$isDragging: isRightDragging,
|
|
371
368
|
onClick: handleHandleClick,
|
|
372
369
|
...rightListeners,
|
|
373
|
-
onPointerDown: createPointerDownHandler(
|
|
370
|
+
onPointerDown: createPointerDownHandler(
|
|
371
|
+
rightListeners?.onPointerDown
|
|
372
|
+
),
|
|
374
373
|
...rightAttributes
|
|
375
374
|
}
|
|
376
375
|
)
|
|
@@ -671,20 +670,13 @@ var AnnotationTextComponent = ({
|
|
|
671
670
|
const isActive = annotation.id === activeAnnotationId;
|
|
672
671
|
const handleClick = () => onAnnotationClick?.(annotation);
|
|
673
672
|
if (renderAnnotationItem) {
|
|
674
|
-
return /* @__PURE__ */ jsx5(
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
isActive,
|
|
682
|
-
onClick: handleClick,
|
|
683
|
-
formatTime
|
|
684
|
-
})
|
|
685
|
-
},
|
|
686
|
-
annotation.id
|
|
687
|
-
);
|
|
673
|
+
return /* @__PURE__ */ jsx5("div", { ref: isActive ? activeAnnotationRef : null, children: renderAnnotationItem({
|
|
674
|
+
annotation,
|
|
675
|
+
index,
|
|
676
|
+
isActive,
|
|
677
|
+
onClick: handleClick,
|
|
678
|
+
formatTime
|
|
679
|
+
}) }, annotation.id);
|
|
688
680
|
}
|
|
689
681
|
return /* @__PURE__ */ jsxs5(
|
|
690
682
|
AnnotationItem,
|
|
@@ -752,7 +744,11 @@ var AnnotationTextComponent = ({
|
|
|
752
744
|
var AnnotationText2 = React2.memo(AnnotationTextComponent);
|
|
753
745
|
|
|
754
746
|
// src/components/ContinuousPlayCheckbox.tsx
|
|
755
|
-
import {
|
|
747
|
+
import {
|
|
748
|
+
BaseCheckboxWrapper,
|
|
749
|
+
BaseCheckbox,
|
|
750
|
+
BaseCheckboxLabel
|
|
751
|
+
} from "@waveform-playlist/ui-components";
|
|
756
752
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
757
753
|
var ContinuousPlayCheckbox = ({
|
|
758
754
|
checked,
|
|
@@ -780,7 +776,11 @@ var ContinuousPlayCheckbox = ({
|
|
|
780
776
|
};
|
|
781
777
|
|
|
782
778
|
// src/components/LinkEndpointsCheckbox.tsx
|
|
783
|
-
import {
|
|
779
|
+
import {
|
|
780
|
+
BaseCheckboxWrapper as BaseCheckboxWrapper2,
|
|
781
|
+
BaseCheckbox as BaseCheckbox2,
|
|
782
|
+
BaseCheckboxLabel as BaseCheckboxLabel2
|
|
783
|
+
} from "@waveform-playlist/ui-components";
|
|
784
784
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
785
785
|
var LinkEndpointsCheckbox = ({
|
|
786
786
|
checked,
|
|
@@ -808,7 +808,11 @@ var LinkEndpointsCheckbox = ({
|
|
|
808
808
|
};
|
|
809
809
|
|
|
810
810
|
// src/components/EditableCheckbox.tsx
|
|
811
|
-
import {
|
|
811
|
+
import {
|
|
812
|
+
BaseCheckboxWrapper as BaseCheckboxWrapper3,
|
|
813
|
+
BaseCheckbox as BaseCheckbox3,
|
|
814
|
+
BaseCheckboxLabel as BaseCheckboxLabel3
|
|
815
|
+
} from "@waveform-playlist/ui-components";
|
|
812
816
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
813
817
|
var EditableCheckbox = ({
|
|
814
818
|
checked,
|
|
@@ -916,10 +920,7 @@ var AnnotationProvider = ({ children }) => {
|
|
|
916
920
|
import { useState as useState2, useCallback } from "react";
|
|
917
921
|
var LINK_THRESHOLD = 0.01;
|
|
918
922
|
var useAnnotationControls = (options = {}) => {
|
|
919
|
-
const {
|
|
920
|
-
initialContinuousPlay = false,
|
|
921
|
-
initialLinkEndpoints = true
|
|
922
|
-
} = options;
|
|
923
|
+
const { initialContinuousPlay = false, initialLinkEndpoints = true } = options;
|
|
923
924
|
const [continuousPlay, setContinuousPlay] = useState2(initialContinuousPlay);
|
|
924
925
|
const [linkEndpoints, setLinkEndpoints] = useState2(initialLinkEndpoints);
|
|
925
926
|
const updateAnnotationBoundaries = useCallback(
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 { AnnotationData, AnnotationAction, AnnotationActionOptions } 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 { AnnotationData, AnnotationAction, AnnotationActionOptions } 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>\n {annotation.lines.join('\\n')}\n </AnnotationText>\n )}\n </AnnotationOverlay>\n );\n};\n","import React, { FunctionComponent } from 'react';\nimport styled from 'styled-components';\nimport { useDraggable } from '@dnd-kit/core';\nimport type { DraggableAttributes } from '@dnd-kit/core';\nimport type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';\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) => 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 ${(props) => props.$isActive\n ? (props.theme?.annotationBoxActiveBorder || '#ff9800')\n : 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) => 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) => 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) => 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) => 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: opacity 0.2s, 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) => props.theme?.annotationResizeHandleActiveColor || 'rgba(0, 0, 0, 0.7)'};\n }\n`;\n\nexport interface DragHandleProps {\n attributes: DraggableAttributes;\n listeners: SyntheticListenerMap | undefined;\n setActivatorNodeRef: (element: HTMLElement | null) => void;\n isDragging: boolean;\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 const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging,\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging,\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n });\n\n if (width <= 0) {\n return null;\n }\n\n // Wrap @dnd-kit pointer handlers to also stop propagation\n // This prevents the ClickOverlay from capturing the event\n const createPointerDownHandler = (dndKitHandler?: (e: React.PointerEvent) => void) => {\n return (e: React.PointerEvent) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\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\n $color={color}\n $isActive={isActive}\n onClick={onClick}\n >\n {label && <Label>{label}</Label>}\n </Box>\n {editable && (\n <ResizeHandle\n ref={setLeftActivatorRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n {...leftListeners}\n onPointerDown={createPointerDownHandler(leftListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined)}\n {...leftAttributes}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={setRightActivatorRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n {...rightListeners}\n onPointerDown={createPointerDownHandler(rightListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined)}\n {...rightAttributes}\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}>\n {children}\n </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}>\n Annotations\n </ControlsPlaceholder>\n <AnnotationsContainer $offset={offset}>\n {children}\n </AnnotationsContainer>\n </Container>\n );\n};\n","import React, { FunctionComponent, useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport type { AnnotationData, AnnotationAction, AnnotationActionOptions, RenderAnnotationItemProps } 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) => (props.$isActive ? '0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)' : 'none')};\n\n &:hover {\n background: ${(props) => (props.$isActive ? 'rgba(255, 152, 0, 0.2)' : props.theme?.annotationTextItemHoverBackground || 'rgba(0, 0, 0, 0.05)')};\n border-left-color: ${(props) => (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) => (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) => (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 = (control: AnnotationAction, annotation: AnnotationData, index: number) => {\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\n key={annotation.id}\n ref={isActive ? activeAnnotationRef : null}\n >\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 ? control.text : <i className={getIconClass(control.class || '')} />}\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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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 { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } 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={annotations.length === 0 ? 'No annotations to download' : 'Download the annotations as JSON'}\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 (annotation: import('@waveform-playlist/core').AnnotationData) => 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 {\n initialContinuousPlay = false,\n initialLinkEndpoints = true,\n } = 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 (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\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 (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\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/core';\nimport type { DraggableAttributes } from '@dnd-kit/core';\nimport type { SyntheticListenerMap } from '@dnd-kit/core/dist/hooks/utilities';\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 DragHandleProps {\n attributes: DraggableAttributes;\n listeners: SyntheticListenerMap | undefined;\n setActivatorNodeRef: (element: HTMLElement | null) => void;\n isDragging: boolean;\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 const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging,\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: 'start' as const },\n disabled: !editable,\n });\n\n // Right (end) boundary draggable\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging,\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: 'end' as const },\n disabled: !editable,\n });\n\n if (width <= 0) {\n return null;\n }\n\n // Wrap @dnd-kit pointer handlers to also stop propagation\n // This prevents the ClickOverlay from capturing the event\n const createPointerDownHandler = (dndKitHandler?: (e: React.PointerEvent) => void) => {\n return (e: React.PointerEvent) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\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={setLeftActivatorRef}\n $position=\"left\"\n $isDragging={isLeftDragging}\n onClick={handleHandleClick}\n {...leftListeners}\n onPointerDown={createPointerDownHandler(\n leftListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined\n )}\n {...leftAttributes}\n />\n )}\n {editable && (\n <ResizeHandle\n ref={setRightActivatorRef}\n $position=\"right\"\n $isDragging={isRightDragging}\n onClick={handleHandleClick}\n {...rightListeners}\n onPointerDown={createPointerDownHandler(\n rightListeners?.onPointerDown as ((e: React.PointerEvent) => void) | undefined\n )}\n {...rightAttributes}\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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waveform-playlist/annotations",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.3",
|
|
4
4
|
"description": "Annotation support for waveform-playlist",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -39,18 +39,18 @@
|
|
|
39
39
|
"@types/styled-components": "^5.1.26",
|
|
40
40
|
"tsup": "^8.0.1",
|
|
41
41
|
"typescript": "^5.3.3",
|
|
42
|
-
"@waveform-playlist/browser": "7.1.
|
|
42
|
+
"@waveform-playlist/browser": "7.1.3"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@waveform-playlist/
|
|
46
|
-
"@waveform-playlist/
|
|
45
|
+
"@waveform-playlist/ui-components": "7.1.3",
|
|
46
|
+
"@waveform-playlist/core": "7.1.3"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@dnd-kit/core": "^6.0.0",
|
|
50
50
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
51
51
|
"react": "^18.0.0",
|
|
52
52
|
"styled-components": "^6.0.0",
|
|
53
|
-
"@waveform-playlist/browser": "7.1.
|
|
53
|
+
"@waveform-playlist/browser": "7.1.3"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsup",
|