@editframe/elements 0.26.4-beta.0 → 0.30.0-beta.13
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/elements/EFSourceMixin.js +1 -1
- package/dist/elements/EFSourceMixin.js.map +1 -1
- package/dist/elements/EFSurface.d.ts +4 -4
- package/dist/elements/EFText.d.ts +52 -0
- package/dist/elements/EFText.js +319 -0
- package/dist/elements/EFText.js.map +1 -0
- package/dist/elements/EFTextSegment.d.ts +30 -0
- package/dist/elements/EFTextSegment.js +94 -0
- package/dist/elements/EFTextSegment.js.map +1 -0
- package/dist/elements/EFThumbnailStrip.d.ts +4 -4
- package/dist/elements/EFWaveform.d.ts +4 -4
- package/dist/elements/FetchMixin.js +22 -7
- package/dist/elements/FetchMixin.js.map +1 -1
- package/dist/elements/easingUtils.js +62 -0
- package/dist/elements/easingUtils.js.map +1 -0
- package/dist/elements/updateAnimations.js +57 -10
- package/dist/elements/updateAnimations.js.map +1 -1
- package/dist/gui/ContextMixin.js +11 -2
- package/dist/gui/ContextMixin.js.map +1 -1
- package/dist/gui/EFConfiguration.d.ts +4 -4
- package/dist/gui/EFControls.d.ts +2 -2
- package/dist/gui/EFDial.d.ts +4 -4
- package/dist/gui/EFDial.js +4 -2
- package/dist/gui/EFDial.js.map +1 -1
- package/dist/gui/EFFilmstrip.d.ts +32 -6
- package/dist/gui/EFFilmstrip.js +314 -50
- package/dist/gui/EFFilmstrip.js.map +1 -1
- package/dist/gui/EFFitScale.js +39 -15
- package/dist/gui/EFFitScale.js.map +1 -1
- package/dist/gui/EFFocusOverlay.d.ts +4 -4
- package/dist/gui/EFPause.d.ts +4 -4
- package/dist/gui/EFPlay.d.ts +4 -4
- package/dist/gui/EFPreview.d.ts +4 -4
- package/dist/gui/EFPreview.js +2 -2
- package/dist/gui/EFPreview.js.map +1 -1
- package/dist/gui/EFResizableBox.d.ts +4 -4
- package/dist/gui/EFResizableBox.js +6 -3
- package/dist/gui/EFResizableBox.js.map +1 -1
- package/dist/gui/EFScrubber.d.ts +8 -5
- package/dist/gui/EFScrubber.js +64 -12
- package/dist/gui/EFScrubber.js.map +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +4 -4
- package/dist/gui/EFToggleLoop.d.ts +4 -4
- package/dist/gui/EFTogglePlay.d.ts +4 -4
- package/dist/gui/EFWorkbench.d.ts +4 -4
- package/dist/gui/EFWorkbench.js +16 -3
- package/dist/gui/EFWorkbench.js.map +1 -1
- package/dist/gui/TWMixin.js +1 -1
- package/dist/gui/TWMixin.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/style.css +7 -120
- package/package.json +3 -3
- package/scripts/build-css.js +2 -6
- package/test/constants.ts +8 -0
- package/test/recordReplayProxyPlugin.js +76 -10
- package/test/setup.ts +32 -0
- package/test/useMSW.ts +3 -0
- package/test/useTranscodeMSW.ts +191 -0
- package/tsdown.config.ts +6 -4
- package/types.json +1 -1
|
@@ -230,6 +230,7 @@ let EFResizableBox = class EFResizableBox$1 extends LitElement {
|
|
|
230
230
|
};
|
|
231
231
|
this.handlePointerMove = (e) => {
|
|
232
232
|
if (!this.isDragging || !this.interaction || e.pointerId !== this.interaction.pointerId) return;
|
|
233
|
+
e.preventDefault();
|
|
233
234
|
const deltaX = e.clientX - this.interaction.startPoint.x;
|
|
234
235
|
const deltaY = e.clientY - this.interaction.startPoint.y;
|
|
235
236
|
this.modifiers = {
|
|
@@ -270,7 +271,9 @@ let EFResizableBox = class EFResizableBox$1 extends LitElement {
|
|
|
270
271
|
}
|
|
271
272
|
this.dispatchBoundsChange();
|
|
272
273
|
};
|
|
273
|
-
this.handlePointerUp = () => {
|
|
274
|
+
this.handlePointerUp = (e) => {
|
|
275
|
+
if (this.interaction && e.pointerId !== this.interaction.pointerId) return;
|
|
276
|
+
e.preventDefault();
|
|
274
277
|
this.isDragging = false;
|
|
275
278
|
this.dragMode = null;
|
|
276
279
|
this.interaction = null;
|
|
@@ -340,8 +343,8 @@ let EFResizableBox = class EFResizableBox$1 extends LitElement {
|
|
|
340
343
|
shift: e.shiftKey,
|
|
341
344
|
alt: e.altKey
|
|
342
345
|
};
|
|
343
|
-
document.addEventListener("pointermove", this.handlePointerMove);
|
|
344
|
-
document.addEventListener("pointerup", this.handlePointerUp);
|
|
346
|
+
document.addEventListener("pointermove", this.handlePointerMove, { passive: false });
|
|
347
|
+
document.addEventListener("pointerup", this.handlePointerUp, { passive: false });
|
|
345
348
|
}
|
|
346
349
|
calculateBoundsWithModeAwareConstraints(context, handle) {
|
|
347
350
|
const { modifiers, constraints, container, initialBounds } = context;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFResizableBox.js","names":["movementValue: number","newBounds: BoxBounds","EFResizableBox","context: ResizeContext","idealBounds: BoxBounds","result: BoxBounds"],"sources":["../../src/gui/EFResizableBox.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\n\n// Constants\nconst DEFAULT_MIN_SIZE = 10;\nconst CENTER_RESIZE_MULTIPLIER = 2;\n\nexport interface BoxBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ntype ResizeCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\ntype ResizeSide = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype ResizeHandle = ResizeCorner | ResizeSide;\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\ninterface ResizeContext {\n readonly initialBounds: BoxBounds;\n readonly container: Dimensions;\n readonly constraints: {\n minSize: number;\n aspectRatio?: number;\n };\n readonly movement: {\n deltaX: number;\n deltaY: number;\n };\n readonly modifiers: {\n centerResize: boolean;\n preserveAspectRatio: boolean;\n };\n}\n\n// Pure calculation functions\nfunction constrainMovementDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n container: Dimensions,\n): { deltaX: number; deltaY: number } {\n const maxLeftMovement = -initialBounds.x;\n const maxRightMovement =\n container.width - (initialBounds.x + initialBounds.width);\n const maxUpMovement = -initialBounds.y;\n const maxDownMovement =\n container.height - (initialBounds.y + initialBounds.height);\n\n return {\n deltaX: Math.max(maxLeftMovement, Math.min(maxRightMovement, deltaX)),\n deltaY: Math.max(maxUpMovement, Math.min(maxDownMovement, deltaY)),\n };\n}\n\nfunction calculateNormalResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n switch (handle) {\n case \"bottom-right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n height: initialBounds.height + deltaY,\n };\n\n case \"top-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newX = initialBounds.x + deltaX;\n const newY = initialBounds.y + deltaY;\n\n return {\n x: newX,\n y: newY,\n width: rightEdge - newX,\n height: bottomEdge - newY,\n };\n }\n\n case \"top-right\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n width: initialBounds.width + deltaX,\n height: bottomEdge - newY,\n };\n }\n\n case \"bottom-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n height: initialBounds.height + deltaY,\n };\n }\n\n case \"top\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n height: bottomEdge - newY,\n };\n }\n\n case \"right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n };\n\n case \"bottom\":\n return {\n ...initialBounds,\n height: initialBounds.height + deltaY,\n };\n\n case \"left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n };\n }\n\n default:\n return initialBounds;\n }\n}\n\nfunction calculateAspectRatioResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const widthMovement = deltaX;\n const heightMovement = deltaY * aspectRatio;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n case \"top-left\":\n movementValue = (widthMovement + heightMovement) / 2;\n break;\n case \"top-right\":\n case \"bottom-left\":\n movementValue = (widthMovement - heightMovement) / 2;\n break;\n default:\n movementValue = widthMovement;\n }\n\n const baseWidth =\n handle === \"top-left\" || handle === \"bottom-left\"\n ? initialBounds.width - movementValue\n : initialBounds.width + movementValue;\n\n const width = Math.max(constraints.minSize, baseWidth);\n const height = width / aspectRatio;\n\n const newBounds: BoxBounds = { ...initialBounds, width, height };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"top-right\":\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"bottom-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n break;\n }\n\n return newBounds;\n}\n\nfunction calculateCenterResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let widthChange = 0;\n let heightChange = 0;\n\n switch (handle) {\n case \"bottom-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"bottom-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top\":\n case \"bottom\":\n heightChange =\n (handle === \"bottom\" ? deltaY : -deltaY) * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"left\":\n case \"right\":\n widthChange =\n (handle === \"right\" ? deltaX : -deltaX) * CENTER_RESIZE_MULTIPLIER;\n break;\n }\n\n const newWidth = initialBounds.width + widthChange;\n const newHeight = initialBounds.height + heightChange;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\n}\n\nfunction calculateCenterResizeWithAspectRatio(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n movementValue = Math.max(deltaX, deltaY);\n break;\n case \"top-left\":\n movementValue = -Math.max(-deltaX, -deltaY);\n break;\n case \"top-right\":\n movementValue = Math.max(deltaX, -deltaY);\n break;\n case \"bottom-left\":\n movementValue = Math.max(-deltaX, deltaY);\n break;\n case \"top\":\n case \"bottom\":\n movementValue = handle === \"bottom\" ? deltaY : -deltaY;\n break;\n case \"left\":\n case \"right\":\n movementValue = handle === \"right\" ? deltaX : -deltaX;\n break;\n default:\n movementValue = Math.max(deltaX, deltaY);\n }\n\n const newWidth = Math.max(\n constraints.minSize,\n initialBounds.width + movementValue * CENTER_RESIZE_MULTIPLIER,\n );\n const newHeight = newWidth / aspectRatio;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\n}\n\n@customElement(\"ef-resizable-box\")\nexport class EFResizableBox extends LitElement {\n @property({ type: Object })\n bounds: BoxBounds = { x: 0, y: 0, width: 100, height: 100 };\n\n @state()\n private containerWidth = 0;\n\n @state()\n private containerHeight = 0;\n\n @property({ type: Number })\n minSize = DEFAULT_MIN_SIZE;\n\n @state()\n private isDragging = false;\n\n @state()\n private dragMode: \"move\" | \"resize\" | null = null;\n\n private interaction: {\n startPoint: { x: number; y: number };\n target: { mode: \"move\" | \"resize\"; handle?: ResizeHandle };\n initialBounds: BoxBounds;\n pointerId: number;\n } | null = null;\n\n private modifiers = { shift: false, alt: false };\n\n static styles = css`\n .box {\n position: absolute;\n border: 2px solid var(--ef-resizable-box-border-color, #3b82f6);\n background-color: var(--ef-resizable-box-bg-color, rgba(59, 130, 246, 0.2));\n cursor: grab;\n }\n .box.dragging {\n border-color: var(--ef-resizable-box-dragging-border-color, #2563eb);\n background-color: var(--ef-resizable-box-dragging-bg-color, rgba(37, 99, 235, 0.3));\n }\n .handle {\n position: absolute;\n background-color: var(--ef-resizable-box-handle-color, #3b82f6);\n touch-action: none;\n }\n .top-left { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top-right { top: -4px; right: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-left { bottom: -4px; left: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-right { bottom: -4px; right: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top { top: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .right { top: 4px; bottom: 4px; right: -4px; width: 8px; cursor: ew-resize; }\n .bottom { bottom: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .left { top: 4px; bottom: 4px; left: -4px; width: 8px; cursor: ew-resize; }\n `;\n\n private resizeObserver?: ResizeObserver;\n\n connectedCallback() {\n super.connectedCallback();\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n this.resizeObserver = new ResizeObserver(() => {\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n });\n if (this.offsetParent) {\n this.resizeObserver.observe(this.offsetParent);\n }\n }\n\n private handlePointerDown(\n e: PointerEvent,\n mode: \"move\" | \"resize\",\n handle?: ResizeHandle,\n ) {\n e.preventDefault();\n e.stopPropagation();\n this.isDragging = true;\n this.dragMode = mode;\n\n this.interaction = {\n startPoint: { x: e.clientX, y: e.clientY },\n target: { mode, handle },\n initialBounds: { ...this.bounds },\n pointerId: e.pointerId,\n };\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\n\n document.addEventListener(\"pointermove\", this.handlePointerMove);\n document.addEventListener(\"pointerup\", this.handlePointerUp);\n }\n\n private handlePointerMove = (e: PointerEvent) => {\n if (\n !this.isDragging ||\n !this.interaction ||\n e.pointerId !== this.interaction.pointerId\n )\n return;\n\n const deltaX = e.clientX - this.interaction.startPoint.x;\n const deltaY = e.clientY - this.interaction.startPoint.y;\n\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\n\n if (this.dragMode === \"move\") {\n const constrainedMovement = constrainMovementDeltas(\n this.interaction.initialBounds,\n deltaX,\n deltaY,\n { width: this.containerWidth, height: this.containerHeight },\n );\n this.bounds = {\n ...this.interaction.initialBounds,\n x: this.interaction.initialBounds.x + constrainedMovement.deltaX,\n y: this.interaction.initialBounds.y + constrainedMovement.deltaY,\n };\n } else if (this.dragMode === \"resize\" && this.interaction.target.handle) {\n const context: ResizeContext = {\n initialBounds: this.interaction.initialBounds,\n container: { width: this.containerWidth, height: this.containerHeight },\n constraints: {\n minSize: this.minSize,\n aspectRatio: this.modifiers.shift\n ? this.interaction.initialBounds.width /\n this.interaction.initialBounds.height\n : undefined,\n },\n movement: { deltaX, deltaY },\n modifiers: {\n centerResize: this.modifiers.alt,\n preserveAspectRatio: this.modifiers.shift,\n },\n };\n this.bounds = this.calculateBoundsWithModeAwareConstraints(\n context,\n this.interaction.target.handle,\n );\n }\n\n this.dispatchBoundsChange();\n };\n\n private handlePointerUp = () => {\n this.isDragging = false;\n this.dragMode = null;\n this.interaction = null;\n document.removeEventListener(\"pointermove\", this.handlePointerMove);\n document.removeEventListener(\"pointerup\", this.handlePointerUp);\n };\n\n private calculateBoundsWithModeAwareConstraints(\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { modifiers, constraints, container, initialBounds } = context;\n\n // For normal resize, use the simple delta constraint approach\n if (!modifiers.centerResize && !modifiers.preserveAspectRatio) {\n const constrainedMovement = this.constrainResizeDeltas(\n initialBounds,\n context.movement.deltaX,\n context.movement.deltaY,\n handle,\n container,\n constraints.minSize,\n );\n\n return calculateNormalResize(\n {\n ...context,\n movement: constrainedMovement,\n },\n handle,\n );\n }\n\n // For modifier-based resizes, calculate ideal bounds then constrain smartly\n let idealBounds: BoxBounds;\n\n if (modifiers.centerResize && modifiers.preserveAspectRatio) {\n idealBounds = calculateCenterResizeWithAspectRatio(context, handle);\n } else if (modifiers.centerResize) {\n idealBounds = calculateCenterResize(context, handle);\n } else {\n idealBounds = calculateAspectRatioResize(context, handle);\n }\n\n // Smart constraint that preserves the resize mode's behavior\n return this.constrainBoundsForMode(idealBounds, context, handle);\n }\n\n private constrainBoundsForMode(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, modifiers } = context;\n\n // Check if bounds are already valid\n if (this.isValidBounds(idealBounds, container, constraints.minSize)) {\n return idealBounds;\n }\n\n // For combined center + aspect ratio, need special handling\n if (\n modifiers.centerResize &&\n modifiers.preserveAspectRatio &&\n constraints.aspectRatio\n ) {\n return this.constrainCenterResizeWithAspectRatio(idealBounds, context);\n }\n\n // For aspect ratio modes, we need to scale the bounds proportionally\n if (modifiers.preserveAspectRatio && constraints.aspectRatio) {\n return this.constrainWithAspectRatio(idealBounds, context, handle);\n }\n\n // For center resize, we need to adjust from the center\n if (modifiers.centerResize) {\n return this.constrainCenterResize(idealBounds, context);\n }\n\n // Fallback to simple constraint\n return this.simpleConstrainBounds(\n idealBounds,\n container,\n constraints.minSize,\n );\n }\n\n private isValidBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width >= minSize &&\n bounds.height >= minSize &&\n bounds.x + bounds.width <= container.width &&\n bounds.y + bounds.height <= container.height\n );\n }\n\n private constrainWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n // Calculate maximum allowed dimensions\n const maxWidth = container.width - Math.max(0, idealBounds.x);\n const maxHeight = container.height - Math.max(0, idealBounds.y);\n\n // Find the largest size that fits both constraints\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidth, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height is too big, constrain by height instead\n if (constrainedHeight > maxHeight) {\n constrainedHeight = Math.max(constraints.minSize, maxHeight);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure we don't go smaller than minimum\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n const result: BoxBounds = {\n ...idealBounds,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"top-right\":\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"bottom-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n break;\n }\n\n // Ensure position is within bounds\n result.x = Math.max(0, Math.min(container.width - result.width, result.x));\n result.y = Math.max(\n 0,\n Math.min(container.height - result.height, result.y),\n );\n\n return result;\n }\n\n private constrainCenterResize(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n const constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n const constrainedHeight = Math.max(\n constraints.minSize,\n Math.min(maxHeightFromCenter, idealBounds.height),\n );\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private constrainCenterResizeWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center while maintaining aspect ratio\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n // Start with the ideal width, then constrain\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height doesn't fit, constrain by height instead\n if (constrainedHeight > maxHeightFromCenter) {\n constrainedHeight = Math.max(constraints.minSize, maxHeightFromCenter);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure minimum size\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n if (constrainedHeight < constraints.minSize) {\n constrainedHeight = constraints.minSize;\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private simpleConstrainBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): BoxBounds {\n return {\n x: Math.max(0, Math.min(container.width - bounds.width, bounds.x)),\n y: Math.max(0, Math.min(container.height - bounds.height, bounds.y)),\n width: Math.max(\n minSize,\n Math.min(container.width - bounds.x, bounds.width),\n ),\n height: Math.max(\n minSize,\n Math.min(container.height - bounds.y, bounds.height),\n ),\n };\n }\n\n private constrainResizeDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n handle: ResizeHandle,\n container: Dimensions,\n minSize: number,\n ): { deltaX: number; deltaY: number } {\n let constrainedDeltaX = deltaX;\n let constrainedDeltaY = deltaY;\n\n switch (handle) {\n case \"bottom-right\":\n // Can't make smaller than minSize, can't go beyond container\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top-left\":\n // Can't make smaller than minSize, can't go beyond 0\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"top-right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"bottom-left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n break;\n\n case \"left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n break;\n\n case \"bottom\":\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top\":\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n }\n\n return { deltaX: constrainedDeltaX, deltaY: constrainedDeltaY };\n }\n\n private dispatchBoundsChange() {\n this.dispatchEvent(\n new CustomEvent(\"bounds-change\", {\n detail: { bounds: this.bounds },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n const boxStyles = {\n left: `${this.bounds.x}px`,\n top: `${this.bounds.y}px`,\n width: `${this.bounds.width}px`,\n height: `${this.bounds.height}px`,\n };\n\n return html`\n <div\n class=\"box ${this.isDragging ? \"dragging\" : \"\"}\"\n style=${styleMap(boxStyles)}\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"move\")}\n >\n ${this.renderHandles()}\n <slot></slot>\n </div>\n `;\n }\n\n private renderHandles() {\n const handles: ResizeHandle[] = [\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n ];\n return handles.map(\n (handle) => html`\n <div\n class=\"handle ${handle}\"\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"resize\", handle)}\n ></div>\n `,\n );\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EFResizableBox.js","names":["movementValue: number","newBounds: BoxBounds","EFResizableBox","context: ResizeContext","idealBounds: BoxBounds","result: BoxBounds"],"sources":["../../src/gui/EFResizableBox.ts"],"sourcesContent":["import { css, html, LitElement } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { styleMap } from \"lit/directives/style-map.js\";\n\n// Constants\nconst DEFAULT_MIN_SIZE = 10;\nconst CENTER_RESIZE_MULTIPLIER = 2;\n\nexport interface BoxBounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\ntype ResizeCorner = \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\ntype ResizeSide = \"top\" | \"right\" | \"bottom\" | \"left\";\ntype ResizeHandle = ResizeCorner | ResizeSide;\n\ninterface Dimensions {\n width: number;\n height: number;\n}\n\ninterface ResizeContext {\n readonly initialBounds: BoxBounds;\n readonly container: Dimensions;\n readonly constraints: {\n minSize: number;\n aspectRatio?: number;\n };\n readonly movement: {\n deltaX: number;\n deltaY: number;\n };\n readonly modifiers: {\n centerResize: boolean;\n preserveAspectRatio: boolean;\n };\n}\n\n// Pure calculation functions\nfunction constrainMovementDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n container: Dimensions,\n): { deltaX: number; deltaY: number } {\n const maxLeftMovement = -initialBounds.x;\n const maxRightMovement =\n container.width - (initialBounds.x + initialBounds.width);\n const maxUpMovement = -initialBounds.y;\n const maxDownMovement =\n container.height - (initialBounds.y + initialBounds.height);\n\n return {\n deltaX: Math.max(maxLeftMovement, Math.min(maxRightMovement, deltaX)),\n deltaY: Math.max(maxUpMovement, Math.min(maxDownMovement, deltaY)),\n };\n}\n\nfunction calculateNormalResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n switch (handle) {\n case \"bottom-right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n height: initialBounds.height + deltaY,\n };\n\n case \"top-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newX = initialBounds.x + deltaX;\n const newY = initialBounds.y + deltaY;\n\n return {\n x: newX,\n y: newY,\n width: rightEdge - newX,\n height: bottomEdge - newY,\n };\n }\n\n case \"top-right\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n width: initialBounds.width + deltaX,\n height: bottomEdge - newY,\n };\n }\n\n case \"bottom-left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n height: initialBounds.height + deltaY,\n };\n }\n\n case \"top\": {\n const bottomEdge = initialBounds.y + initialBounds.height;\n const newY = initialBounds.y + deltaY;\n\n return {\n ...initialBounds,\n y: newY,\n height: bottomEdge - newY,\n };\n }\n\n case \"right\":\n return {\n ...initialBounds,\n width: initialBounds.width + deltaX,\n };\n\n case \"bottom\":\n return {\n ...initialBounds,\n height: initialBounds.height + deltaY,\n };\n\n case \"left\": {\n const rightEdge = initialBounds.x + initialBounds.width;\n const newX = initialBounds.x + deltaX;\n\n return {\n ...initialBounds,\n x: newX,\n width: rightEdge - newX,\n };\n }\n\n default:\n return initialBounds;\n }\n}\n\nfunction calculateAspectRatioResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const widthMovement = deltaX;\n const heightMovement = deltaY * aspectRatio;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n case \"top-left\":\n movementValue = (widthMovement + heightMovement) / 2;\n break;\n case \"top-right\":\n case \"bottom-left\":\n movementValue = (widthMovement - heightMovement) / 2;\n break;\n default:\n movementValue = widthMovement;\n }\n\n const baseWidth =\n handle === \"top-left\" || handle === \"bottom-left\"\n ? initialBounds.width - movementValue\n : initialBounds.width + movementValue;\n\n const width = Math.max(constraints.minSize, baseWidth);\n const height = width / aspectRatio;\n\n const newBounds: BoxBounds = { ...initialBounds, width, height };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"top-right\":\n newBounds.y = initialBounds.y + initialBounds.height - height;\n break;\n case \"bottom-left\":\n newBounds.x = initialBounds.x + initialBounds.width - width;\n break;\n }\n\n return newBounds;\n}\n\nfunction calculateCenterResize(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement } = context;\n const { deltaX, deltaY } = movement;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let widthChange = 0;\n let heightChange = 0;\n\n switch (handle) {\n case \"bottom-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top-right\":\n widthChange = deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = -deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"bottom-left\":\n widthChange = -deltaX * CENTER_RESIZE_MULTIPLIER;\n heightChange = deltaY * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"top\":\n case \"bottom\":\n heightChange =\n (handle === \"bottom\" ? deltaY : -deltaY) * CENTER_RESIZE_MULTIPLIER;\n break;\n case \"left\":\n case \"right\":\n widthChange =\n (handle === \"right\" ? deltaX : -deltaX) * CENTER_RESIZE_MULTIPLIER;\n break;\n }\n\n const newWidth = initialBounds.width + widthChange;\n const newHeight = initialBounds.height + heightChange;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\n}\n\nfunction calculateCenterResizeWithAspectRatio(\n context: ResizeContext,\n handle: ResizeHandle,\n): BoxBounds {\n const { initialBounds, movement, constraints } = context;\n const { deltaX, deltaY } = movement;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n let movementValue: number;\n switch (handle) {\n case \"bottom-right\":\n movementValue = Math.max(deltaX, deltaY);\n break;\n case \"top-left\":\n movementValue = -Math.max(-deltaX, -deltaY);\n break;\n case \"top-right\":\n movementValue = Math.max(deltaX, -deltaY);\n break;\n case \"bottom-left\":\n movementValue = Math.max(-deltaX, deltaY);\n break;\n case \"top\":\n case \"bottom\":\n movementValue = handle === \"bottom\" ? deltaY : -deltaY;\n break;\n case \"left\":\n case \"right\":\n movementValue = handle === \"right\" ? deltaX : -deltaX;\n break;\n default:\n movementValue = Math.max(deltaX, deltaY);\n }\n\n const newWidth = Math.max(\n constraints.minSize,\n initialBounds.width + movementValue * CENTER_RESIZE_MULTIPLIER,\n );\n const newHeight = newWidth / aspectRatio;\n\n return {\n x: centerX - newWidth / 2,\n y: centerY - newHeight / 2,\n width: newWidth,\n height: newHeight,\n };\n}\n\n@customElement(\"ef-resizable-box\")\nexport class EFResizableBox extends LitElement {\n @property({ type: Object })\n bounds: BoxBounds = { x: 0, y: 0, width: 100, height: 100 };\n\n @state()\n private containerWidth = 0;\n\n @state()\n private containerHeight = 0;\n\n @property({ type: Number })\n minSize = DEFAULT_MIN_SIZE;\n\n @state()\n private isDragging = false;\n\n @state()\n private dragMode: \"move\" | \"resize\" | null = null;\n\n private interaction: {\n startPoint: { x: number; y: number };\n target: { mode: \"move\" | \"resize\"; handle?: ResizeHandle };\n initialBounds: BoxBounds;\n pointerId: number;\n } | null = null;\n\n private modifiers = { shift: false, alt: false };\n\n static styles = css`\n .box {\n position: absolute;\n border: 2px solid var(--ef-resizable-box-border-color, #3b82f6);\n background-color: var(--ef-resizable-box-bg-color, rgba(59, 130, 246, 0.2));\n cursor: grab;\n }\n .box.dragging {\n border-color: var(--ef-resizable-box-dragging-border-color, #2563eb);\n background-color: var(--ef-resizable-box-dragging-bg-color, rgba(37, 99, 235, 0.3));\n }\n .handle {\n position: absolute;\n background-color: var(--ef-resizable-box-handle-color, #3b82f6);\n touch-action: none;\n }\n .top-left { top: -4px; left: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top-right { top: -4px; right: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-left { bottom: -4px; left: -4px; width: 8px; height: 8px; cursor: nesw-resize; }\n .bottom-right { bottom: -4px; right: -4px; width: 8px; height: 8px; cursor: nwse-resize; }\n .top { top: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .right { top: 4px; bottom: 4px; right: -4px; width: 8px; cursor: ew-resize; }\n .bottom { bottom: -4px; left: 4px; right: 4px; height: 8px; cursor: ns-resize; }\n .left { top: 4px; bottom: 4px; left: -4px; width: 8px; cursor: ew-resize; }\n `;\n\n private resizeObserver?: ResizeObserver;\n\n connectedCallback() {\n super.connectedCallback();\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n this.resizeObserver = new ResizeObserver(() => {\n if (this.offsetParent) {\n this.containerWidth = this.offsetParent.clientWidth;\n this.containerHeight = this.offsetParent.clientHeight;\n }\n });\n if (this.offsetParent) {\n this.resizeObserver.observe(this.offsetParent);\n }\n }\n\n private handlePointerDown(\n e: PointerEvent,\n mode: \"move\" | \"resize\",\n handle?: ResizeHandle,\n ) {\n e.preventDefault();\n e.stopPropagation();\n this.isDragging = true;\n this.dragMode = mode;\n\n this.interaction = {\n startPoint: { x: e.clientX, y: e.clientY },\n target: { mode, handle },\n initialBounds: { ...this.bounds },\n pointerId: e.pointerId,\n };\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\n\n document.addEventListener(\"pointermove\", this.handlePointerMove, {\n passive: false,\n });\n document.addEventListener(\"pointerup\", this.handlePointerUp, {\n passive: false,\n });\n }\n\n private handlePointerMove = (e: PointerEvent) => {\n if (\n !this.isDragging ||\n !this.interaction ||\n e.pointerId !== this.interaction.pointerId\n )\n return;\n\n e.preventDefault();\n\n const deltaX = e.clientX - this.interaction.startPoint.x;\n const deltaY = e.clientY - this.interaction.startPoint.y;\n\n this.modifiers = { shift: e.shiftKey, alt: e.altKey };\n\n if (this.dragMode === \"move\") {\n const constrainedMovement = constrainMovementDeltas(\n this.interaction.initialBounds,\n deltaX,\n deltaY,\n { width: this.containerWidth, height: this.containerHeight },\n );\n this.bounds = {\n ...this.interaction.initialBounds,\n x: this.interaction.initialBounds.x + constrainedMovement.deltaX,\n y: this.interaction.initialBounds.y + constrainedMovement.deltaY,\n };\n } else if (this.dragMode === \"resize\" && this.interaction.target.handle) {\n const context: ResizeContext = {\n initialBounds: this.interaction.initialBounds,\n container: { width: this.containerWidth, height: this.containerHeight },\n constraints: {\n minSize: this.minSize,\n aspectRatio: this.modifiers.shift\n ? this.interaction.initialBounds.width /\n this.interaction.initialBounds.height\n : undefined,\n },\n movement: { deltaX, deltaY },\n modifiers: {\n centerResize: this.modifiers.alt,\n preserveAspectRatio: this.modifiers.shift,\n },\n };\n this.bounds = this.calculateBoundsWithModeAwareConstraints(\n context,\n this.interaction.target.handle,\n );\n }\n\n this.dispatchBoundsChange();\n };\n\n private handlePointerUp = (e: PointerEvent) => {\n if (this.interaction && e.pointerId !== this.interaction.pointerId) {\n return;\n }\n e.preventDefault();\n this.isDragging = false;\n this.dragMode = null;\n this.interaction = null;\n document.removeEventListener(\"pointermove\", this.handlePointerMove);\n document.removeEventListener(\"pointerup\", this.handlePointerUp);\n };\n\n private calculateBoundsWithModeAwareConstraints(\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { modifiers, constraints, container, initialBounds } = context;\n\n // For normal resize, use the simple delta constraint approach\n if (!modifiers.centerResize && !modifiers.preserveAspectRatio) {\n const constrainedMovement = this.constrainResizeDeltas(\n initialBounds,\n context.movement.deltaX,\n context.movement.deltaY,\n handle,\n container,\n constraints.minSize,\n );\n\n return calculateNormalResize(\n {\n ...context,\n movement: constrainedMovement,\n },\n handle,\n );\n }\n\n // For modifier-based resizes, calculate ideal bounds then constrain smartly\n let idealBounds: BoxBounds;\n\n if (modifiers.centerResize && modifiers.preserveAspectRatio) {\n idealBounds = calculateCenterResizeWithAspectRatio(context, handle);\n } else if (modifiers.centerResize) {\n idealBounds = calculateCenterResize(context, handle);\n } else {\n idealBounds = calculateAspectRatioResize(context, handle);\n }\n\n // Smart constraint that preserves the resize mode's behavior\n return this.constrainBoundsForMode(idealBounds, context, handle);\n }\n\n private constrainBoundsForMode(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, modifiers } = context;\n\n // Check if bounds are already valid\n if (this.isValidBounds(idealBounds, container, constraints.minSize)) {\n return idealBounds;\n }\n\n // For combined center + aspect ratio, need special handling\n if (\n modifiers.centerResize &&\n modifiers.preserveAspectRatio &&\n constraints.aspectRatio\n ) {\n return this.constrainCenterResizeWithAspectRatio(idealBounds, context);\n }\n\n // For aspect ratio modes, we need to scale the bounds proportionally\n if (modifiers.preserveAspectRatio && constraints.aspectRatio) {\n return this.constrainWithAspectRatio(idealBounds, context, handle);\n }\n\n // For center resize, we need to adjust from the center\n if (modifiers.centerResize) {\n return this.constrainCenterResize(idealBounds, context);\n }\n\n // Fallback to simple constraint\n return this.simpleConstrainBounds(\n idealBounds,\n container,\n constraints.minSize,\n );\n }\n\n private isValidBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width >= minSize &&\n bounds.height >= minSize &&\n bounds.x + bounds.width <= container.width &&\n bounds.y + bounds.height <= container.height\n );\n }\n\n private constrainWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n handle: ResizeHandle,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n // Calculate maximum allowed dimensions\n const maxWidth = container.width - Math.max(0, idealBounds.x);\n const maxHeight = container.height - Math.max(0, idealBounds.y);\n\n // Find the largest size that fits both constraints\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidth, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height is too big, constrain by height instead\n if (constrainedHeight > maxHeight) {\n constrainedHeight = Math.max(constraints.minSize, maxHeight);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure we don't go smaller than minimum\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n const result: BoxBounds = {\n ...idealBounds,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n\n // Adjust position for handles that move the origin\n switch (handle) {\n case \"top-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"top-right\":\n result.y = initialBounds.y + initialBounds.height - constrainedHeight;\n break;\n case \"bottom-left\":\n result.x = initialBounds.x + initialBounds.width - constrainedWidth;\n break;\n }\n\n // Ensure position is within bounds\n result.x = Math.max(0, Math.min(container.width - result.width, result.x));\n result.y = Math.max(\n 0,\n Math.min(container.height - result.height, result.y),\n );\n\n return result;\n }\n\n private constrainCenterResize(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n const constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n const constrainedHeight = Math.max(\n constraints.minSize,\n Math.min(maxHeightFromCenter, idealBounds.height),\n );\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private constrainCenterResizeWithAspectRatio(\n idealBounds: BoxBounds,\n context: ResizeContext,\n ): BoxBounds {\n const { container, constraints, initialBounds } = context;\n if (!constraints.aspectRatio) {\n return initialBounds;\n }\n const aspectRatio = constraints.aspectRatio;\n\n const centerX = initialBounds.x + initialBounds.width / 2;\n const centerY = initialBounds.y + initialBounds.height / 2;\n\n // Calculate maximum dimensions from center while maintaining aspect ratio\n const maxWidthFromCenter = Math.min(\n centerX * 2,\n (container.width - centerX) * 2,\n );\n const maxHeightFromCenter = Math.min(\n centerY * 2,\n (container.height - centerY) * 2,\n );\n\n // Start with the ideal width, then constrain\n let constrainedWidth = Math.max(\n constraints.minSize,\n Math.min(maxWidthFromCenter, idealBounds.width),\n );\n let constrainedHeight = constrainedWidth / aspectRatio;\n\n // If height doesn't fit, constrain by height instead\n if (constrainedHeight > maxHeightFromCenter) {\n constrainedHeight = Math.max(constraints.minSize, maxHeightFromCenter);\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n // Ensure minimum size\n if (constrainedWidth < constraints.minSize) {\n constrainedWidth = constraints.minSize;\n constrainedHeight = constrainedWidth / aspectRatio;\n }\n\n if (constrainedHeight < constraints.minSize) {\n constrainedHeight = constraints.minSize;\n constrainedWidth = constrainedHeight * aspectRatio;\n }\n\n return {\n x: centerX - constrainedWidth / 2,\n y: centerY - constrainedHeight / 2,\n width: constrainedWidth,\n height: constrainedHeight,\n };\n }\n\n private simpleConstrainBounds(\n bounds: BoxBounds,\n container: Dimensions,\n minSize: number,\n ): BoxBounds {\n return {\n x: Math.max(0, Math.min(container.width - bounds.width, bounds.x)),\n y: Math.max(0, Math.min(container.height - bounds.height, bounds.y)),\n width: Math.max(\n minSize,\n Math.min(container.width - bounds.x, bounds.width),\n ),\n height: Math.max(\n minSize,\n Math.min(container.height - bounds.y, bounds.height),\n ),\n };\n }\n\n private constrainResizeDeltas(\n initialBounds: BoxBounds,\n deltaX: number,\n deltaY: number,\n handle: ResizeHandle,\n container: Dimensions,\n minSize: number,\n ): { deltaX: number; deltaY: number } {\n let constrainedDeltaX = deltaX;\n let constrainedDeltaY = deltaY;\n\n switch (handle) {\n case \"bottom-right\":\n // Can't make smaller than minSize, can't go beyond container\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top-left\":\n // Can't make smaller than minSize, can't go beyond 0\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"top-right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n\n case \"bottom-left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"right\":\n constrainedDeltaX = Math.max(\n minSize - initialBounds.width,\n Math.min(\n container.width - initialBounds.x - initialBounds.width,\n deltaX,\n ),\n );\n break;\n\n case \"left\":\n constrainedDeltaX = Math.max(\n -initialBounds.x,\n Math.min(initialBounds.width - minSize, deltaX),\n );\n break;\n\n case \"bottom\":\n constrainedDeltaY = Math.max(\n minSize - initialBounds.height,\n Math.min(\n container.height - initialBounds.y - initialBounds.height,\n deltaY,\n ),\n );\n break;\n\n case \"top\":\n constrainedDeltaY = Math.max(\n -initialBounds.y,\n Math.min(initialBounds.height - minSize, deltaY),\n );\n break;\n }\n\n return { deltaX: constrainedDeltaX, deltaY: constrainedDeltaY };\n }\n\n private dispatchBoundsChange() {\n this.dispatchEvent(\n new CustomEvent(\"bounds-change\", {\n detail: { bounds: this.bounds },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n const boxStyles = {\n left: `${this.bounds.x}px`,\n top: `${this.bounds.y}px`,\n width: `${this.bounds.width}px`,\n height: `${this.bounds.height}px`,\n };\n\n return html`\n <div\n class=\"box ${this.isDragging ? \"dragging\" : \"\"}\"\n style=${styleMap(boxStyles)}\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"move\")}\n >\n ${this.renderHandles()}\n <slot></slot>\n </div>\n `;\n }\n\n private renderHandles() {\n const handles: ResizeHandle[] = [\n \"top-left\",\n \"top-right\",\n \"bottom-left\",\n \"bottom-right\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n ];\n return handles.map(\n (handle) => html`\n <div\n class=\"handle ${handle}\"\n @pointerdown=${(e: PointerEvent) => this.handlePointerDown(e, \"resize\", handle)}\n ></div>\n `,\n );\n }\n}\n"],"mappings":"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"}
|
package/dist/gui/EFScrubber.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit20 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html18 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFScrubber.d.ts
|
|
7
7
|
declare const EFScrubber_base: (new (...args: any[]) => {
|
|
@@ -10,7 +10,7 @@ declare const EFScrubber_base: (new (...args: any[]) => {
|
|
|
10
10
|
effectiveContext: ControllableInterface | null;
|
|
11
11
|
}) & typeof LitElement;
|
|
12
12
|
declare class EFScrubber extends EFScrubber_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit20.CSSResult[];
|
|
14
14
|
playing: boolean;
|
|
15
15
|
currentTimeMs: number;
|
|
16
16
|
durationMs: number;
|
|
@@ -18,11 +18,14 @@ declare class EFScrubber extends EFScrubber_base {
|
|
|
18
18
|
private scrubProgress;
|
|
19
19
|
private isMoving;
|
|
20
20
|
private scrubberRef?;
|
|
21
|
+
private capturedPointerId;
|
|
21
22
|
private updateProgress;
|
|
22
|
-
private
|
|
23
|
+
private handlePointerDown;
|
|
23
24
|
private boundHandlePointerMove;
|
|
24
25
|
private boundHandlePointerUp;
|
|
25
|
-
|
|
26
|
+
private boundHandlePointerCancel;
|
|
27
|
+
private boundHandleContextMenu;
|
|
28
|
+
render(): lit_html18.TemplateResult<1>;
|
|
26
29
|
connectedCallback(): void;
|
|
27
30
|
disconnectedCallback(): void;
|
|
28
31
|
}
|
package/dist/gui/EFScrubber.js
CHANGED
|
@@ -6,7 +6,7 @@ import { efContext } from "./efContext.js";
|
|
|
6
6
|
import { TargetOrContextMixin } from "./TargetOrContextMixin.js";
|
|
7
7
|
import { consume } from "@lit/context";
|
|
8
8
|
import { LitElement, css, html } from "lit";
|
|
9
|
-
import { customElement, state } from "lit/decorators.js";
|
|
9
|
+
import { customElement, eventOptions, state } from "lit/decorators.js";
|
|
10
10
|
import { ref } from "lit/directives/ref.js";
|
|
11
11
|
|
|
12
12
|
//#region src/gui/EFScrubber.ts
|
|
@@ -18,16 +18,39 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
18
18
|
this.durationMs = 0;
|
|
19
19
|
this.scrubProgress = 0;
|
|
20
20
|
this.isMoving = false;
|
|
21
|
-
this.
|
|
22
|
-
this.isMoving = true;
|
|
23
|
-
e.preventDefault();
|
|
24
|
-
this.updateProgress(e);
|
|
25
|
-
};
|
|
21
|
+
this.capturedPointerId = null;
|
|
26
22
|
this.boundHandlePointerMove = (e) => {
|
|
27
|
-
if (this.isMoving
|
|
23
|
+
if (this.isMoving && e.pointerId === this.capturedPointerId) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
e.stopPropagation();
|
|
26
|
+
this.updateProgress(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
this.boundHandlePointerUp = (e) => {
|
|
30
|
+
if (e.pointerId === this.capturedPointerId && this.scrubberRef) {
|
|
31
|
+
e.preventDefault();
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
try {
|
|
34
|
+
this.scrubberRef.releasePointerCapture(e.pointerId);
|
|
35
|
+
} catch (_err) {}
|
|
36
|
+
this.capturedPointerId = null;
|
|
37
|
+
this.isMoving = false;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
this.boundHandlePointerCancel = (e) => {
|
|
41
|
+
if (e.pointerId === this.capturedPointerId && this.scrubberRef) {
|
|
42
|
+
try {
|
|
43
|
+
this.scrubberRef.releasePointerCapture(e.pointerId);
|
|
44
|
+
} catch (_err) {}
|
|
45
|
+
this.capturedPointerId = null;
|
|
46
|
+
this.isMoving = false;
|
|
47
|
+
}
|
|
28
48
|
};
|
|
29
|
-
this.
|
|
30
|
-
this.isMoving
|
|
49
|
+
this.boundHandleContextMenu = (e) => {
|
|
50
|
+
if (this.isMoving) {
|
|
51
|
+
e.preventDefault();
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
}
|
|
31
54
|
};
|
|
32
55
|
}
|
|
33
56
|
static {
|
|
@@ -43,6 +66,11 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
43
66
|
justify-content: center;
|
|
44
67
|
}
|
|
45
68
|
|
|
69
|
+
:host(.dark), :host-context(.dark) {
|
|
70
|
+
--ef-scrubber-background: rgb(75 85 99);
|
|
71
|
+
--ef-scrubber-progress-color: rgb(96 165 250);
|
|
72
|
+
}
|
|
73
|
+
|
|
46
74
|
.scrubber {
|
|
47
75
|
width: 100%;
|
|
48
76
|
height: var(--ef-scrubber-height);
|
|
@@ -50,6 +78,8 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
50
78
|
position: relative;
|
|
51
79
|
cursor: pointer;
|
|
52
80
|
border-radius: 2px;
|
|
81
|
+
touch-action: none;
|
|
82
|
+
user-select: none;
|
|
53
83
|
}
|
|
54
84
|
|
|
55
85
|
.progress {
|
|
@@ -87,6 +117,19 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
87
117
|
this.scrubProgress = progress;
|
|
88
118
|
this.context.currentTimeMs = progress * this.durationMs;
|
|
89
119
|
}
|
|
120
|
+
handlePointerDown(e) {
|
|
121
|
+
if (!this.scrubberRef) return;
|
|
122
|
+
this.isMoving = true;
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
e.stopPropagation();
|
|
125
|
+
this.capturedPointerId = e.pointerId;
|
|
126
|
+
try {
|
|
127
|
+
this.scrubberRef.setPointerCapture(e.pointerId);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
console.warn("Failed to set pointer capture:", err);
|
|
130
|
+
}
|
|
131
|
+
this.updateProgress(e);
|
|
132
|
+
}
|
|
90
133
|
render() {
|
|
91
134
|
const currentProgress = this.durationMs > 0 ? (this.currentTimeMs ?? 0) / this.durationMs : 0;
|
|
92
135
|
const displayProgress = this.isMoving ? this.scrubProgress : currentProgress;
|
|
@@ -97,7 +140,8 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
97
140
|
})}
|
|
98
141
|
part="scrubber"
|
|
99
142
|
class="scrubber"
|
|
100
|
-
@
|
|
143
|
+
@pointerdown=${this.handlePointerDown}
|
|
144
|
+
@contextmenu=${this.boundHandleContextMenu}
|
|
101
145
|
>
|
|
102
146
|
<div class="progress" style="width: ${displayProgress * 100}%"></div>
|
|
103
147
|
<div class="handle" style="left: ${displayProgress * 100}%"></div>
|
|
@@ -106,13 +150,17 @@ let EFScrubber = class EFScrubber$1 extends TargetOrContextMixin(LitElement, efC
|
|
|
106
150
|
}
|
|
107
151
|
connectedCallback() {
|
|
108
152
|
super.connectedCallback();
|
|
109
|
-
window.addEventListener("pointerup", this.boundHandlePointerUp);
|
|
110
|
-
window.addEventListener("pointermove", this.boundHandlePointerMove);
|
|
153
|
+
window.addEventListener("pointerup", this.boundHandlePointerUp, { passive: false });
|
|
154
|
+
window.addEventListener("pointermove", this.boundHandlePointerMove, { passive: false });
|
|
155
|
+
window.addEventListener("pointercancel", this.boundHandlePointerCancel, { passive: false });
|
|
156
|
+
this.addEventListener("contextmenu", this.boundHandleContextMenu, { passive: false });
|
|
111
157
|
}
|
|
112
158
|
disconnectedCallback() {
|
|
113
159
|
super.disconnectedCallback();
|
|
114
160
|
window.removeEventListener("pointerup", this.boundHandlePointerUp);
|
|
115
161
|
window.removeEventListener("pointermove", this.boundHandlePointerMove);
|
|
162
|
+
window.removeEventListener("pointercancel", this.boundHandlePointerCancel);
|
|
163
|
+
this.removeEventListener("contextmenu", this.boundHandleContextMenu);
|
|
116
164
|
}
|
|
117
165
|
};
|
|
118
166
|
__decorate([consume({
|
|
@@ -129,6 +177,10 @@ __decorate([consume({
|
|
|
129
177
|
})], EFScrubber.prototype, "durationMs", void 0);
|
|
130
178
|
__decorate([state()], EFScrubber.prototype, "scrubProgress", void 0);
|
|
131
179
|
__decorate([state()], EFScrubber.prototype, "isMoving", void 0);
|
|
180
|
+
__decorate([eventOptions({
|
|
181
|
+
passive: false,
|
|
182
|
+
capture: false
|
|
183
|
+
})], EFScrubber.prototype, "handlePointerDown", null);
|
|
132
184
|
EFScrubber = __decorate([customElement("ef-scrubber")], EFScrubber);
|
|
133
185
|
|
|
134
186
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFScrubber.js","names":["EFScrubber"],"sources":["../../src/gui/EFScrubber.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\n\nimport { ref } from \"lit/directives/ref.js\";\nimport type { ControllableInterface } from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { efContext } from \"./efContext.js\";\nimport { playingContext } from \"./playingContext.js\";\nimport { TargetOrContextMixin } from \"./TargetOrContextMixin.js\";\n\n@customElement(\"ef-scrubber\")\nexport class EFScrubber extends TargetOrContextMixin(LitElement, efContext) {\n static styles = [\n css`\n :host {\n --ef-scrubber-height: 4px;\n --ef-scrubber-background: rgb(209 213 219);\n --ef-scrubber-progress-color: rgb(37 99 235);\n --ef-scrubber-handle-size: 12px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n .scrubber {\n width: 100%;\n height: var(--ef-scrubber-height);\n background: var(--ef-scrubber-background);\n position: relative;\n cursor: pointer;\n border-radius: 2px;\n }\n\n .progress {\n position: absolute;\n height: 100%;\n background: var(--ef-scrubber-progress-color);\n border-radius: 2px;\n }\n\n .handle {\n position: absolute;\n width: var(--ef-scrubber-handle-size);\n height: var(--ef-scrubber-handle-size);\n background: var(--ef-scrubber-progress-color);\n border-radius: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n cursor: grab;\n }\n\n /* Add CSS Shadow Parts */\n ::part(scrubber) { }\n ::part(progress) { }\n ::part(handle) { }\n `,\n ];\n\n @consume({ context: playingContext, subscribe: true })\n playing = false;\n\n @consume({ context: currentTimeContext, subscribe: true })\n currentTimeMs = Number.NaN;\n\n @consume({ context: durationContext, subscribe: true })\n durationMs = 0;\n\n get context(): ControllableInterface | null {\n return this.effectiveContext;\n }\n\n @state()\n private scrubProgress = 0;\n\n @state()\n private isMoving = false;\n\n private scrubberRef?: HTMLElement;\n\n private updateProgress(e:
|
|
1
|
+
{"version":3,"file":"EFScrubber.js","names":["EFScrubber"],"sources":["../../src/gui/EFScrubber.ts"],"sourcesContent":["import { consume } from \"@lit/context\";\nimport { css, html, LitElement } from \"lit\";\nimport { customElement, eventOptions, state } from \"lit/decorators.js\";\n\nimport { ref } from \"lit/directives/ref.js\";\nimport type { ControllableInterface } from \"./Controllable.js\";\nimport { currentTimeContext } from \"./currentTimeContext.js\";\nimport { durationContext } from \"./durationContext.js\";\nimport { efContext } from \"./efContext.js\";\nimport { playingContext } from \"./playingContext.js\";\nimport { TargetOrContextMixin } from \"./TargetOrContextMixin.js\";\n\n@customElement(\"ef-scrubber\")\nexport class EFScrubber extends TargetOrContextMixin(LitElement, efContext) {\n static styles = [\n css`\n :host {\n --ef-scrubber-height: 4px;\n --ef-scrubber-background: rgb(209 213 219);\n --ef-scrubber-progress-color: rgb(37 99 235);\n --ef-scrubber-handle-size: 12px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n :host(.dark), :host-context(.dark) {\n --ef-scrubber-background: rgb(75 85 99);\n --ef-scrubber-progress-color: rgb(96 165 250);\n }\n \n .scrubber {\n width: 100%;\n height: var(--ef-scrubber-height);\n background: var(--ef-scrubber-background);\n position: relative;\n cursor: pointer;\n border-radius: 2px;\n touch-action: none;\n user-select: none;\n }\n\n .progress {\n position: absolute;\n height: 100%;\n background: var(--ef-scrubber-progress-color);\n border-radius: 2px;\n }\n\n .handle {\n position: absolute;\n width: var(--ef-scrubber-handle-size);\n height: var(--ef-scrubber-handle-size);\n background: var(--ef-scrubber-progress-color);\n border-radius: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n cursor: grab;\n }\n\n /* Add CSS Shadow Parts */\n ::part(scrubber) { }\n ::part(progress) { }\n ::part(handle) { }\n `,\n ];\n\n @consume({ context: playingContext, subscribe: true })\n playing = false;\n\n @consume({ context: currentTimeContext, subscribe: true })\n currentTimeMs = Number.NaN;\n\n @consume({ context: durationContext, subscribe: true })\n durationMs = 0;\n\n get context(): ControllableInterface | null {\n return this.effectiveContext;\n }\n\n @state()\n private scrubProgress = 0;\n\n @state()\n private isMoving = false;\n\n private scrubberRef?: HTMLElement;\n private capturedPointerId: number | null = null;\n\n private updateProgress(e: PointerEvent) {\n if (!this.context || !this.scrubberRef) return;\n\n const rect = this.scrubberRef.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const progress = Math.max(0, Math.min(1, x / rect.width));\n\n this.scrubProgress = progress;\n this.context.currentTimeMs = progress * this.durationMs;\n }\n\n @eventOptions({ passive: false, capture: false })\n private handlePointerDown(e: PointerEvent) {\n if (!this.scrubberRef) return;\n\n this.isMoving = true;\n e.preventDefault();\n e.stopPropagation();\n this.capturedPointerId = e.pointerId;\n try {\n this.scrubberRef.setPointerCapture(e.pointerId);\n } catch (err) {\n // setPointerCapture may fail in some cases, continue anyway\n console.warn(\"Failed to set pointer capture:\", err);\n }\n this.updateProgress(e);\n }\n\n private boundHandlePointerMove = (e: PointerEvent) => {\n if (this.isMoving && e.pointerId === this.capturedPointerId) {\n e.preventDefault();\n e.stopPropagation();\n this.updateProgress(e);\n }\n };\n\n private boundHandlePointerUp = (e: PointerEvent) => {\n if (e.pointerId === this.capturedPointerId && this.scrubberRef) {\n e.preventDefault();\n e.stopPropagation();\n try {\n this.scrubberRef.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n }\n };\n\n private boundHandlePointerCancel = (e: PointerEvent) => {\n if (e.pointerId === this.capturedPointerId && this.scrubberRef) {\n try {\n this.scrubberRef.releasePointerCapture(e.pointerId);\n } catch (_err) {\n // releasePointerCapture may fail if capture was already lost\n }\n this.capturedPointerId = null;\n this.isMoving = false;\n }\n };\n\n private boundHandleContextMenu = (e: Event) => {\n if (this.isMoving) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n\n render() {\n // Calculate progress from currentTimeMs and duration\n const currentProgress =\n this.durationMs > 0 ? (this.currentTimeMs ?? 0) / this.durationMs : 0;\n\n const displayProgress = this.isMoving\n ? this.scrubProgress\n : currentProgress;\n\n return html`\n <div \n ${ref((el) => {\n this.scrubberRef = el as HTMLElement;\n })}\n part=\"scrubber\"\n class=\"scrubber\"\n @pointerdown=${this.handlePointerDown}\n @contextmenu=${this.boundHandleContextMenu}\n >\n <div class=\"progress\" style=\"width: ${displayProgress * 100}%\"></div>\n <div class=\"handle\" style=\"left: ${displayProgress * 100}%\"></div>\n </div>\n `;\n }\n\n connectedCallback() {\n super.connectedCallback();\n window.addEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n { passive: false },\n );\n window.addEventListener(\"pointermove\", this.boundHandlePointerMove, {\n passive: false,\n });\n window.addEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n { passive: false },\n );\n this.addEventListener(\"contextmenu\", this.boundHandleContextMenu, {\n passive: false,\n });\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n window.removeEventListener(\n \"pointerup\",\n this.boundHandlePointerUp as EventListener,\n );\n window.removeEventListener(\"pointermove\", this.boundHandlePointerMove);\n window.removeEventListener(\n \"pointercancel\",\n this.boundHandlePointerCancel as EventListener,\n );\n this.removeEventListener(\"contextmenu\", this.boundHandleContextMenu);\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-scrubber\": EFScrubber;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit21 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html19 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFTimeDisplay.d.ts
|
|
7
7
|
declare const EFTimeDisplay_base: (new (...args: any[]) => {
|
|
@@ -10,11 +10,11 @@ declare const EFTimeDisplay_base: (new (...args: any[]) => {
|
|
|
10
10
|
effectiveContext: ControllableInterface | null;
|
|
11
11
|
}) & typeof LitElement;
|
|
12
12
|
declare class EFTimeDisplay extends EFTimeDisplay_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit21.CSSResult;
|
|
14
14
|
currentTimeMs: number;
|
|
15
15
|
durationMs: number;
|
|
16
16
|
private formatTime;
|
|
17
|
-
render():
|
|
17
|
+
render(): lit_html19.TemplateResult<1>;
|
|
18
18
|
}
|
|
19
19
|
declare global {
|
|
20
20
|
interface HTMLElementTagNameMap {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit19 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html17 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFToggleLoop.d.ts
|
|
7
7
|
declare const EFToggleLoop_base: (new (...args: any[]) => {
|
|
@@ -10,9 +10,9 @@ declare const EFToggleLoop_base: (new (...args: any[]) => {
|
|
|
10
10
|
effectiveContext: ControllableInterface | null;
|
|
11
11
|
}) & typeof LitElement;
|
|
12
12
|
declare class EFToggleLoop extends EFToggleLoop_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit19.CSSResult[];
|
|
14
14
|
get context(): ControllableInterface | null;
|
|
15
|
-
render():
|
|
15
|
+
render(): lit_html17.TemplateResult<1>;
|
|
16
16
|
}
|
|
17
17
|
declare global {
|
|
18
18
|
interface HTMLElementTagNameMap {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ControllableInterface } from "./Controllable.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit16 from "lit";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html14 from "lit-html";
|
|
5
5
|
|
|
6
6
|
//#region src/gui/EFTogglePlay.d.ts
|
|
7
7
|
declare const EFTogglePlay_base: (new (...args: any[]) => {
|
|
@@ -10,12 +10,12 @@ declare const EFTogglePlay_base: (new (...args: any[]) => {
|
|
|
10
10
|
effectiveContext: ControllableInterface | null;
|
|
11
11
|
}) & typeof LitElement;
|
|
12
12
|
declare class EFTogglePlay extends EFTogglePlay_base {
|
|
13
|
-
static styles:
|
|
13
|
+
static styles: lit16.CSSResult[];
|
|
14
14
|
playing: boolean;
|
|
15
15
|
get efContext(): ControllableInterface | null;
|
|
16
16
|
connectedCallback(): void;
|
|
17
17
|
disconnectedCallback(): void;
|
|
18
|
-
render():
|
|
18
|
+
render(): lit_html14.TemplateResult<1>;
|
|
19
19
|
togglePlay: () => void;
|
|
20
20
|
}
|
|
21
21
|
declare global {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ContextMixinInterface } from "./ContextMixin.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as lit12 from "lit";
|
|
3
3
|
import { LitElement, PropertyValueMap } from "lit";
|
|
4
|
-
import * as
|
|
4
|
+
import * as lit_html12 from "lit-html";
|
|
5
5
|
import * as lit_html_directives_ref_js2 from "lit-html/directives/ref.js";
|
|
6
6
|
|
|
7
7
|
//#region src/gui/EFWorkbench.d.ts
|
|
8
8
|
declare const EFWorkbench_base: (new (...args: any[]) => ContextMixinInterface) & typeof LitElement;
|
|
9
9
|
declare class EFWorkbench extends EFWorkbench_base {
|
|
10
|
-
static styles:
|
|
10
|
+
static styles: lit12.CSSResult[];
|
|
11
11
|
rendering: boolean;
|
|
12
12
|
focusOverlay: lit_html_directives_ref_js2.Ref<HTMLDivElement>;
|
|
13
13
|
handleStageWheel(event: WheelEvent): void;
|
|
@@ -15,7 +15,7 @@ declare class EFWorkbench extends EFWorkbench_base {
|
|
|
15
15
|
disconnectedCallback(): void;
|
|
16
16
|
update(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
17
17
|
drawOverlays: () => void;
|
|
18
|
-
render():
|
|
18
|
+
render(): lit_html12.TemplateResult<1>;
|
|
19
19
|
}
|
|
20
20
|
declare global {
|
|
21
21
|
interface HTMLElementTagNameMap {
|
package/dist/gui/EFWorkbench.js
CHANGED
|
@@ -33,6 +33,18 @@ let EFWorkbench = class EFWorkbench$1 extends ContextMixin(TWMixin(LitElement))
|
|
|
33
33
|
display: block;
|
|
34
34
|
width: 100%;
|
|
35
35
|
height: 100%;
|
|
36
|
+
|
|
37
|
+
/* Light mode colors */
|
|
38
|
+
--workbench-bg: rgb(30 41 59); /* slate-800 */
|
|
39
|
+
--workbench-overlay-border: rgb(59 130 246); /* blue-500 */
|
|
40
|
+
--workbench-overlay-bg: rgb(191 219 254); /* blue-200 */
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
:host(.dark), :host-context(.dark) {
|
|
44
|
+
/* Dark mode colors */
|
|
45
|
+
--workbench-bg: rgb(2 6 23); /* slate-950 */
|
|
46
|
+
--workbench-overlay-border: rgb(96 165 250); /* blue-400 */
|
|
47
|
+
--workbench-overlay-bg: rgb(30 58 138); /* blue-900 */
|
|
36
48
|
}
|
|
37
49
|
`];
|
|
38
50
|
}
|
|
@@ -63,8 +75,8 @@ let EFWorkbench = class EFWorkbench$1 extends ContextMixin(TWMixin(LitElement))
|
|
|
63
75
|
`;
|
|
64
76
|
return html`
|
|
65
77
|
<div
|
|
66
|
-
class="grid h-full w-full
|
|
67
|
-
style="grid-template-rows: 1fr 300px; grid-template-columns: 100%;"
|
|
78
|
+
class="grid h-full w-full"
|
|
79
|
+
style="grid-template-rows: 1fr 300px; grid-template-columns: 100%; background-color: var(--workbench-bg);"
|
|
68
80
|
>
|
|
69
81
|
<div
|
|
70
82
|
class="relative h-full w-full overflow-hidden"
|
|
@@ -74,7 +86,8 @@ let EFWorkbench = class EFWorkbench$1 extends ContextMixin(TWMixin(LitElement))
|
|
|
74
86
|
<slot name="canvas" class="contents"></slot>
|
|
75
87
|
</ef-fit-scale>
|
|
76
88
|
<div
|
|
77
|
-
class="border
|
|
89
|
+
class="border bg-opacity-20 absolute"
|
|
90
|
+
style="border-color: var(--workbench-overlay-border); background-color: var(--workbench-overlay-bg);"
|
|
78
91
|
${ref(this.focusOverlay)}
|
|
79
92
|
></div>
|
|
80
93
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EFWorkbench.js","names":["EFWorkbench"],"sources":["../../src/gui/EFWorkbench.ts"],"sourcesContent":["import { css, html, LitElement, type PropertyValueMap } from \"lit\";\nimport { customElement, eventOptions, property } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\n\nimport { ContextMixin } from \"./ContextMixin.js\";\nimport { TWMixin } from \"./TWMixin.js\";\n\n@customElement(\"ef-workbench\")\nexport class EFWorkbench extends ContextMixin(TWMixin(LitElement)) {\n static styles = [\n css`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n }\n `,\n ];\n\n @property({ type: Boolean })\n rendering = false;\n\n focusOverlay = createRef<HTMLDivElement>();\n\n @eventOptions({ passive: false, capture: true })\n handleStageWheel(event: WheelEvent) {\n event.preventDefault();\n }\n\n connectedCallback(): void {\n document.body.style.width = \"100%\";\n document.body.style.height = \"100%\";\n document.documentElement.style.width = \"100%\";\n document.documentElement.style.height = \"100%\";\n super.connectedCallback();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.body.style.width = \"\";\n document.body.style.height = \"\";\n document.documentElement.style.width = \"\";\n document.documentElement.style.height = \"\";\n }\n\n update(\n changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,\n ): void {\n super.update(changedProperties);\n\n if (changedProperties.has(\"focusedElement\")) {\n this.drawOverlays();\n }\n }\n\n drawOverlays = () => {\n const focusOverlay = this.focusOverlay.value;\n if (focusOverlay) {\n if (this.focusedElement) {\n focusOverlay.style.display = \"block\";\n const rect = this.focusedElement.getBoundingClientRect();\n Object.assign(focusOverlay.style, {\n position: \"fixed\",\n top: `${rect.top}px`,\n left: `${rect.left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n requestAnimationFrame(this.drawOverlays);\n } else {\n focusOverlay.style.display = \"none\";\n }\n }\n };\n\n render() {\n // TODO: this.rendering is not correctly set when using the framegen bridge\n // so to hack we're checking for the existence of EF_RENDERING on the window\n if (\n this.rendering ||\n (typeof window !== \"undefined\" && window.EF_RENDERING?.() === true)\n ) {\n return html`\n <slot class=\"fixed inset-0 h-full w-full\" name=\"canvas\"></slot>\n `;\n }\n return html`\n <div\n class=\"grid h-full w-full
|
|
1
|
+
{"version":3,"file":"EFWorkbench.js","names":["EFWorkbench"],"sources":["../../src/gui/EFWorkbench.ts"],"sourcesContent":["import { css, html, LitElement, type PropertyValueMap } from \"lit\";\nimport { customElement, eventOptions, property } from \"lit/decorators.js\";\nimport { createRef, ref } from \"lit/directives/ref.js\";\n\nimport { ContextMixin } from \"./ContextMixin.js\";\nimport { TWMixin } from \"./TWMixin.js\";\n\n@customElement(\"ef-workbench\")\nexport class EFWorkbench extends ContextMixin(TWMixin(LitElement)) {\n static styles = [\n css`\n :host {\n display: block;\n width: 100%;\n height: 100%;\n \n /* Light mode colors */\n --workbench-bg: rgb(30 41 59); /* slate-800 */\n --workbench-overlay-border: rgb(59 130 246); /* blue-500 */\n --workbench-overlay-bg: rgb(191 219 254); /* blue-200 */\n }\n \n :host(.dark), :host-context(.dark) {\n /* Dark mode colors */\n --workbench-bg: rgb(2 6 23); /* slate-950 */\n --workbench-overlay-border: rgb(96 165 250); /* blue-400 */\n --workbench-overlay-bg: rgb(30 58 138); /* blue-900 */\n }\n `,\n ];\n\n @property({ type: Boolean })\n rendering = false;\n\n focusOverlay = createRef<HTMLDivElement>();\n\n @eventOptions({ passive: false, capture: true })\n handleStageWheel(event: WheelEvent) {\n event.preventDefault();\n }\n\n connectedCallback(): void {\n document.body.style.width = \"100%\";\n document.body.style.height = \"100%\";\n document.documentElement.style.width = \"100%\";\n document.documentElement.style.height = \"100%\";\n super.connectedCallback();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.body.style.width = \"\";\n document.body.style.height = \"\";\n document.documentElement.style.width = \"\";\n document.documentElement.style.height = \"\";\n }\n\n update(\n changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,\n ): void {\n super.update(changedProperties);\n\n if (changedProperties.has(\"focusedElement\")) {\n this.drawOverlays();\n }\n }\n\n drawOverlays = () => {\n const focusOverlay = this.focusOverlay.value;\n if (focusOverlay) {\n if (this.focusedElement) {\n focusOverlay.style.display = \"block\";\n const rect = this.focusedElement.getBoundingClientRect();\n Object.assign(focusOverlay.style, {\n position: \"fixed\",\n top: `${rect.top}px`,\n left: `${rect.left}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n requestAnimationFrame(this.drawOverlays);\n } else {\n focusOverlay.style.display = \"none\";\n }\n }\n };\n\n render() {\n // TODO: this.rendering is not correctly set when using the framegen bridge\n // so to hack we're checking for the existence of EF_RENDERING on the window\n if (\n this.rendering ||\n (typeof window !== \"undefined\" && window.EF_RENDERING?.() === true)\n ) {\n return html`\n <slot class=\"fixed inset-0 h-full w-full\" name=\"canvas\"></slot>\n `;\n }\n return html`\n <div\n class=\"grid h-full w-full\"\n style=\"grid-template-rows: 1fr 300px; grid-template-columns: 100%; background-color: var(--workbench-bg);\"\n >\n <div\n class=\"relative h-full w-full overflow-hidden\"\n @wheel=${this.handleStageWheel}\n >\n <ef-fit-scale class=\"h-full grid place-content-center\">\n <slot name=\"canvas\" class=\"contents\"></slot>\n </ef-fit-scale>\n <div\n class=\"border bg-opacity-20 absolute\"\n style=\"border-color: var(--workbench-overlay-border); background-color: var(--workbench-overlay-bg);\"\n ${ref(this.focusOverlay)}\n ></div>\n </div>\n\n <slot class=\"overflow inline-block\" name=\"timeline\"></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ef-workbench\": EFWorkbench;\n }\n}\n"],"mappings":";;;;;;;;AAQO,wBAAMA,sBAAoB,aAAa,QAAQ,WAAW,CAAC,CAAC;;;mBAwBrD;sBAEG,WAA2B;4BAiCrB;GACnB,MAAM,eAAe,KAAK,aAAa;AACvC,OAAI,aACF,KAAI,KAAK,gBAAgB;AACvB,iBAAa,MAAM,UAAU;IAC7B,MAAM,OAAO,KAAK,eAAe,uBAAuB;AACxD,WAAO,OAAO,aAAa,OAAO;KAChC,UAAU;KACV,KAAK,GAAG,KAAK,IAAI;KACjB,MAAM,GAAG,KAAK,KAAK;KACnB,OAAO,GAAG,KAAK,MAAM;KACrB,QAAQ,GAAG,KAAK,OAAO;KACxB,CAAC;AACF,0BAAsB,KAAK,aAAa;SAExC,cAAa,MAAM,UAAU;;;;gBAzEnB,CACd,GAAG;;;;;;;;;;;;;;;;;;MAmBJ;;CAOD,AACA,iBAAiB,OAAmB;AAClC,QAAM,gBAAgB;;CAGxB,oBAA0B;AACxB,WAAS,KAAK,MAAM,QAAQ;AAC5B,WAAS,KAAK,MAAM,SAAS;AAC7B,WAAS,gBAAgB,MAAM,QAAQ;AACvC,WAAS,gBAAgB,MAAM,SAAS;AACxC,QAAM,mBAAmB;;CAG3B,uBAA6B;AAC3B,QAAM,sBAAsB;AAC5B,WAAS,KAAK,MAAM,QAAQ;AAC5B,WAAS,KAAK,MAAM,SAAS;AAC7B,WAAS,gBAAgB,MAAM,QAAQ;AACvC,WAAS,gBAAgB,MAAM,SAAS;;CAG1C,OACE,mBACM;AACN,QAAM,OAAO,kBAAkB;AAE/B,MAAI,kBAAkB,IAAI,iBAAiB,CACzC,MAAK,cAAc;;CAwBvB,SAAS;AAGP,MACE,KAAK,aACJ,OAAO,WAAW,eAAe,OAAO,gBAAgB,KAAK,KAE9D,QAAO,IAAI;;;AAIb,SAAO,IAAI;;;;;;;mBAOI,KAAK,iBAAiB;;;;;;;;cAQ3B,IAAI,KAAK,aAAa,CAAC;;;;;;;;;YAlFlC,SAAS,EAAE,MAAM,SAAS,CAAC;YAK3B,aAAa;CAAE,SAAS;CAAO,SAAS;CAAM,CAAC;0BA7BjD,cAAc,eAAe"}
|