diff --git a/src/jcanvas-handles.ts b/src/jcanvas-handles.ts index a0772f2..03b2346 100644 --- a/src/jcanvas-handles.ts +++ b/src/jcanvas-handles.ts @@ -6,6 +6,13 @@ import "jcanvas"; import $ from "jquery"; +interface JCanvasLayerWithHandles extends JCanvasLayer { + handlePlacement?: "sides" | "corners" | "both"; + aspectRatio?: number | null; + handle?: JCanvasLayer | null; + guide?: JCanvasLayer | null; +} + // Add a 'resizeFromCenter' property for rectangles $.extend($.jCanvas.defaults, { handle: null, @@ -16,10 +23,10 @@ $.extend($.jCanvas.defaults, { handlePlacement: "corners", minWidth: 0, minHeight: 0, -}); +} as Partial); // Determines if the given layer is a rectangular layer -function isRectLayer(layer: JCanvasLayer) { +function isRectLayer(layer: JCanvasLayerWithHandles) { const method = layer._method; return ( method === $.fn.drawRect || @@ -29,7 +36,7 @@ function isRectLayer(layer: JCanvasLayer) { } // Determines if the given layer is a rectangular layer -function isPathLayer(layer: JCanvasLayer) { +function isPathLayer(layer: JCanvasLayerWithHandles) { const method = layer._method; return ( method === $.fn.drawLine || @@ -41,9 +48,9 @@ function isPathLayer(layer: JCanvasLayer) { // Add a single handle to line path function addPathHandle( $canvas: JQuery, - parent: JCanvasLayer, - xProp: string, - yProp: string + parent: JCanvasLayerWithHandles, + xProp: `x${number}` | `cx${number}`, + yProp: `y${number}` | `cy${number}` ) { const handle = $.extend( { @@ -81,7 +88,7 @@ function addPathHandle( dragcancel: function (layer) { $(this).triggerLayerEvent(layer._parent, "handlecancel"); }, - } as Partial + } as Partial ); $canvas.draw(handle); // Add handle to parent layer's list of handles @@ -91,7 +98,7 @@ function addPathHandle( // Add a single handle to rectangle function addRectHandle( $canvas: JQuery, - parent: JCanvasLayer, + parent: JCanvasLayerWithHandles, px: number, py: number ) { @@ -215,7 +222,7 @@ function addRectHandle( const parent = layer._parent; $(this).triggerLayerEvent(parent, "handlecancel"); }, - } as Partial + } as Partial ); $canvas.draw(handle); // Add handle to parent layer's list of handles @@ -225,7 +232,7 @@ function addRectHandle( // Add all handles to rectangle function addRectHandles( $canvas: JQuery, - parent: JCanvasLayer + parent: JCanvasLayerWithHandles ) { const handlePlacement = parent.handlePlacement; const nonNullWidth = parent.width || 0; @@ -255,7 +262,7 @@ function addRectHandles( } // Update handle guides for rectangular layer -function updateRectGuides(parent: JCanvasLayer) { +function updateRectGuides(parent: JCanvasLayerWithHandles) { const guide = parent._guide; if (guide) { guide.x = parent.x; @@ -269,7 +276,7 @@ function updateRectGuides(parent: JCanvasLayer) { // Add handle guides to rectangular layer function addRectGuides( $canvas: JQuery, - parent: JCanvasLayer + parent: JCanvasLayerWithHandles ) { const guideProps = $.extend({}, parent.guide, { layer: true, @@ -287,15 +294,15 @@ function addRectGuides( // Add handles to line path function addPathHandles( $canvas: JQuery, - parent: JCanvasLayer + parent: JCanvasLayerWithHandles ) { for (const key in parent) { if (Object.prototype.hasOwnProperty.call(parent, key)) { // If property is a control point if (key.match(/c?x(\d+)/gi) !== null) { // Get the x and y coordinates for that control point - const xProp = key; - const yProp = key.replace("x", "y"); + const xProp = key as `x${number}` | `cx${number}`; + const yProp = key.replace("x", "y") as `y${number}` | `cy${number}`; // Add handle at control point addPathHandle($canvas, parent, xProp, yProp); } @@ -308,7 +315,7 @@ function addPathHandles( } // Update handle guides for line path -function updatePathGuides(parent: JCanvasLayer) { +function updatePathGuides(parent: JCanvasLayerWithHandles) { let handles = parent._handles; const guides = parent._guides; @@ -343,7 +350,7 @@ function updatePathGuides(parent: JCanvasLayer) { // Add guides to path layer function addPathGuides( $canvas: JQuery, - parent: JCanvasLayer + parent: JCanvasLayerWithHandles ) { const handles = parent._handles; const guideProps = $.extend({}, parent.guide, { @@ -394,7 +401,7 @@ function addPathGuides( // Update position of handles according to // size and dimensions of rectangular layer -function updateRectHandles(parent: JCanvasLayer) { +function updateRectHandles(parent: JCanvasLayerWithHandles) { const nonNullWidth = parent.width || 0; const nonNullHeight = parent.height || 0; if (parent._handles) { @@ -416,7 +423,7 @@ function updateRectHandles(parent: JCanvasLayer) { // Update position of handles according to // coordinates and dimensions of path layer -function updatePathHandles(parent: JCanvasLayer) { +function updatePathHandles(parent: JCanvasLayerWithHandles) { const handles = parent._handles; if (handles) { // Move handles when dragging @@ -430,7 +437,7 @@ function updatePathHandles(parent: JCanvasLayer) { } // Add drag handles to all four corners of rectangle layer -function addHandles(parent: JCanvasLayer) { +function addHandles(parent: JCanvasLayerWithHandles) { const $canvas = $(parent.canvas); // If parent's list of handles doesn't exist @@ -449,7 +456,7 @@ function addHandles(parent: JCanvasLayer) { } // Remove handles if handle property was removed -function removeHandles(layer: JCanvasLayer) { +function removeHandles(layer: JCanvasLayerWithHandles) { const $canvas = $(layer.canvas); if (layer._handles) { // Remove handles from layer @@ -475,7 +482,7 @@ function objectContainsPathCoords(obj: object) { $.extend($.jCanvas.eventHooks, { // If necessary, add handles when layer is added - add: function (layer) { + add: function (layer: JCanvasLayerWithHandles) { if (layer.handle) { addHandles(layer); } @@ -493,7 +500,7 @@ $.extend($.jCanvas.eventHooks, { } }, // Update handle positions when changing parent layer's dimensions - change: function (layer, props: Partial) { + change: function (layer, props: Partial) { if (props.handle || objectContainsPathCoords(props)) { // Add handles if handle property was added removeHandles(layer); diff --git a/src/jcanvas.d.ts b/src/jcanvas.d.ts index f2a9a62..24c7c6a 100644 --- a/src/jcanvas.d.ts +++ b/src/jcanvas.d.ts @@ -332,7 +332,7 @@ interface JCanvasLayer extends JCanvasObject { } interface JCanvasPropHooks { - [key: string]: JQuery.PropHook; + [key: string]: JQuery.PropHook; } type JCanvasNumberParams = { diff --git a/src/jcanvas.ts b/src/jcanvas.ts index 238b2c2..071dba7 100644 --- a/src/jcanvas.ts +++ b/src/jcanvas.ts @@ -674,7 +674,7 @@ function _addLayerEvents( if (Object.prototype.hasOwnProperty.call(jCanvas.events, eventName)) { // If layer has callback function to complement it if ( - layer[eventName as keyof typeof layer] || + layer[eventName as keyof JCanvasLayer] || (layer.cursors && layer.cursors[eventName]) ) { // Bind event to layer @@ -1042,7 +1042,7 @@ $.fn.setLayer = function setLayer(layerId, props) { if (propType === "object" && isPlainObject(propValue)) { // Clone objects layer[propName as any] = extendObject({}, propValue); - _coerceNumericProps(layer[propName as keyof typeof layer]); + _coerceNumericProps(layer[propName as keyof JCanvasLayer]); } else if (propType === "array") { // Clone arrays layer[propName as any] = propValue.slice(0); @@ -1709,7 +1709,7 @@ $.fn.drawLayers = function drawLayers(args) { if (layer && eventType) { // Use mouse event callbacks if no touch event callbacks are given - if (!layer[eventType as keyof typeof layer]) { + if (!layer[eventType as keyof JCanvasLayer]) { eventType = _getMouseEventName(eventType); } @@ -1798,7 +1798,7 @@ function _addLayer( } else if (params.method) { params._method = $.fn[params.method]; } else if (params.type) { - params._method = $.fn[maps.drawings[params.type] as keyof typeof $.fn]; + params._method = $.fn[maps.drawings[params.type] as keyof JQuery]; } } @@ -1909,7 +1909,7 @@ $.fn.addLayer = function addLayer(args) { function _showProps(obj: Partial) { for (let p = 0; p < css.props.length; p += 1) { const cssProp = css.props[p]; - obj[cssProp as keyof typeof obj] = obj[("_" + cssProp) as keyof typeof obj]; + obj[cssProp as keyof typeof obj] = obj[("_" + cssProp) as `_${string}`]; } } function _hideProps(obj: Partial, reset?: boolean) { @@ -1917,8 +1917,7 @@ function _hideProps(obj: Partial, reset?: boolean) { const cssProp = css.props[p]; // Hide property using same name with leading underscore if (obj[cssProp as keyof typeof obj] !== undefined) { - obj[("_" + cssProp) as keyof typeof obj] = - obj[cssProp as keyof typeof obj]; + obj[("_" + cssProp) as `_${string}`] = obj[cssProp as keyof typeof obj]; css.propsObj[cssProp] = true; if (reset) { delete obj[cssProp as keyof typeof obj]; @@ -1949,9 +1948,9 @@ function _parseEndValues( if (Object.prototype.hasOwnProperty.call(propValue, subPropName)) { const subPropValue = propValue[subPropName]; // Store property's start value at top-level of layer - if (layer[propName as keyof typeof layer] !== undefined) { + if (layer[propName as keyof JCanvasLayer] !== undefined) { layer[(propName + "." + subPropName) as any] = - layer[propName as keyof typeof layer][subPropName]; + layer[propName as keyof JCanvasLayer][subPropName]; // Store property's end value at top-level of end values map endValues[propName + "." + subPropName] = subPropValue; } @@ -1970,7 +1969,7 @@ function _removeSubPropAliases(layer: JCanvasLayer) { for (const propName in layer) { if (Object.prototype.hasOwnProperty.call(layer, propName)) { if (propName.indexOf(".") !== -1) { - delete layer[propName as keyof typeof layer]; + delete layer[propName as keyof JCanvasLayer]; } } } @@ -2122,7 +2121,7 @@ $.fn.animateLayer = function animateLayer(...args) { hidden = true; // Unhide property temporarily fx.prop = fx.prop.replace("_", ""); - layer[fx.prop] = layer[("_" + fx.prop) as keyof typeof layer]; + layer[fx.prop] = layer[("_" + fx.prop) as keyof JCanvasLayer]; } // If animating property of sub-object @@ -2130,8 +2129,8 @@ $.fn.animateLayer = function animateLayer(...args) { parts = fx.prop.split("."); propName = parts[0]; subPropName = parts[1]; - if (layer[propName as keyof typeof layer]) { - layer[propName as keyof typeof layer][subPropName] = fx.now; + if (layer[propName as keyof JCanvasLayer]) { + layer[propName as keyof JCanvasLayer][subPropName] = fx.now; } } @@ -2556,7 +2555,7 @@ $.fn.draw = function draw(args) { const params = _getParamsObject(args); // Draw using any other method - const fn = $.fn[maps.drawings[params.type!] as keyof typeof $.fn]; + const fn = $.fn[maps.drawings[params.type!] as keyof JQuery]; if (params.type && maps.drawings[params.type] && isFunction(fn)) { // @ts-expect-error TODO (not sure how to fix this: "This expression is // not callable. Each member of the union type '...' has signatures, but @@ -3304,8 +3303,8 @@ function _drawLine( } while (true) { // Calculate next coordinates - const lx = path[("x" + l) as keyof typeof path]; - const ly = path[("y" + l) as keyof typeof path]; + const lx = path[("x" + l) as `x${number}`]; + const ly = path[("y" + l) as `y${number}`]; // If coordinates are given if (lx !== undefined && ly !== undefined) { // Draw next line @@ -3323,10 +3322,10 @@ function _drawLine( ctx, params, path, - path[("x" + (l - 1)) as keyof typeof path] + params.x, - path[("y" + (l - 1)) as keyof typeof path] + params.y, - path[("x" + l) as keyof typeof path] + params.x, - path[("y" + l) as keyof typeof path] + params.y + path[("x" + (l - 1)) as `x${number}`] + params.x, + path[("y" + (l - 1)) as `y${number}`] + params.y, + path[("x" + l) as `x${number}`] + params.x, + path[("y" + l) as `y${number}`] + params.y ); } @@ -3387,10 +3386,10 @@ function _drawQuadratic( } while (true) { // Calculate next coordinates - const lx = path[("x" + l) as keyof typeof path]; - const ly = path[("y" + l) as keyof typeof path]; - const lcx = path[("cx" + (l - 1)) as keyof typeof path]; - const lcy = path[("cy" + (l - 1)) as keyof typeof path]; + const lx = path[("x" + l) as `x${number}`]; + const ly = path[("y" + l) as `y${number}`]; + const lcx = path[("cx" + (l - 1)) as `cx${number}`]; + const lcy = path[("cy" + (l - 1)) as `cy${number}`]; // If coordinates are given if ( lx !== undefined && @@ -3417,10 +3416,10 @@ function _drawQuadratic( ctx, params, path, - path[("cx" + (l - 1)) as keyof typeof path] + params.x, - path[("cy" + (l - 1)) as keyof typeof path] + params.y, - path[("x" + l) as keyof typeof path] + params.x, - path[("y" + l) as keyof typeof path] + params.y + path[("cx" + (l - 1)) as `cx${number}`] + params.x, + path[("cy" + (l - 1)) as `cy${number}`] + params.y, + path[("x" + l) as `x${number}`] + params.x, + path[("y" + l) as `y${number}`] + params.y ); } @@ -3482,12 +3481,12 @@ function _drawBezier( } while (true) { // Calculate next coordinates - const lx = path[("x" + l) as keyof typeof path]; - const ly = path[("y" + l) as keyof typeof path]; - const lcx1 = path[("cx" + lc) as keyof typeof path]; - const lcy1 = path[("cy" + lc) as keyof typeof path]; - const lcx2 = path[("cx" + (lc + 1)) as keyof typeof path]; - const lcy2 = path[("cy" + (lc + 1)) as keyof typeof path]; + const lx = path[("x" + l) as `x${number}`]; + const ly = path[("y" + l) as `y${number}`]; + const lcx1 = path[("cx" + lc) as `cx${number}`]; + const lcy1 = path[("cy" + lc) as `cy${number}`]; + const lcx2 = path[("cx" + (lc + 1)) as `cx${number}`]; + const lcy2 = path[("cy" + (lc + 1)) as `cy${number}`]; // If next coordinates are given if ( lx !== undefined && @@ -3520,10 +3519,10 @@ function _drawBezier( ctx, params, path, - path[("cx" + (lc + 1)) as keyof typeof path] + params.x, - path[("cy" + (lc + 1)) as keyof typeof path] + params.y, - path[("x" + l) as keyof typeof path] + params.x, - path[("y" + l) as keyof typeof path] + params.y + path[("cx" + (lc + 1)) as `cx${number}`] + params.x, + path[("cy" + (lc + 1)) as `cy${number}`] + params.y, + path[("x" + l) as `x${number}`] + params.x, + path[("y" + l) as `y${number}`] + params.y ); } @@ -3614,8 +3613,8 @@ function _drawVector( ctx.moveTo(x, y); } while (true) { - const angle = path[("a" + l) as keyof typeof path]; - const length = path[("l" + l) as keyof typeof path]; + const angle = path[("a" + l) as `a${number}`]; + const length = path[("l" + l) as `l${number}`]; if (angle !== undefined && length !== undefined) { // Convert the angle to radians with 0 degrees starting at north