@meonode/canvas 1.0.0-beta.3 → 1.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +1 -1
- package/dist/cjs/canvas/canvas.helper.d.ts +9 -11
- package/dist/cjs/canvas/canvas.helper.d.ts.map +1 -1
- package/dist/cjs/canvas/canvas.helper.js +47 -48
- package/dist/cjs/canvas/canvas.helper.js.map +1 -1
- package/dist/cjs/canvas/canvas.type.d.ts +31 -31
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.d.ts +4 -4
- package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.js +21 -4
- package/dist/cjs/canvas/grid.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/image.canvas.util.d.ts +0 -1
- package/dist/cjs/canvas/image.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/image.canvas.util.js +72 -72
- package/dist/cjs/canvas/image.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/layout.canvas.util.d.ts +16 -17
- package/dist/cjs/canvas/layout.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/layout.canvas.util.js +17 -24
- package/dist/cjs/canvas/layout.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/root.canvas.util.d.ts +4 -2
- package/dist/cjs/canvas/root.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/root.canvas.util.js +7 -3
- package/dist/cjs/canvas/root.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.d.ts +20 -27
- package/dist/cjs/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.js +27 -45
- package/dist/cjs/canvas/text.canvas.util.js.map +1 -1
- package/dist/esm/canvas/canvas.helper.d.ts +9 -11
- package/dist/esm/canvas/canvas.helper.d.ts.map +1 -1
- package/dist/esm/canvas/canvas.helper.js +47 -48
- package/dist/esm/canvas/canvas.type.d.ts +31 -31
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.d.ts +4 -4
- package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.js +21 -4
- package/dist/esm/canvas/image.canvas.util.d.ts +0 -1
- package/dist/esm/canvas/image.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/image.canvas.util.js +72 -72
- package/dist/esm/canvas/layout.canvas.util.d.ts +16 -17
- package/dist/esm/canvas/layout.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/layout.canvas.util.js +17 -24
- package/dist/esm/canvas/root.canvas.util.d.ts +4 -2
- package/dist/esm/canvas/root.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/root.canvas.util.js +7 -3
- package/dist/esm/canvas/text.canvas.util.d.ts +20 -27
- package/dist/esm/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/text.canvas.util.js +27 -45
- package/package.json +16 -9
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var layout_canvas_util = require('./layout.canvas.util.js');
|
|
4
4
|
var common_const = require('../constant/common.const.js');
|
|
5
5
|
|
|
6
|
+
// TODO: Add comprehensive unit tests for this file.
|
|
6
7
|
/**
|
|
7
8
|
* Grid layout node that arranges children in a configurable number of columns or rows.
|
|
8
9
|
* Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.
|
|
@@ -15,7 +16,7 @@ class GridNode extends layout_canvas_util.RowNode {
|
|
|
15
16
|
isVertical; // True if the main axis is vertical (flexDirection: column or column-reverse)
|
|
16
17
|
/**
|
|
17
18
|
* Creates a new grid layout node
|
|
18
|
-
* @param props
|
|
19
|
+
* @param props Grid configuration properties
|
|
19
20
|
*/
|
|
20
21
|
constructor(props) {
|
|
21
22
|
const columns = Math.max(1, props.columns || 1);
|
|
@@ -60,17 +61,33 @@ class GridNode extends layout_canvas_util.RowNode {
|
|
|
60
61
|
...props,
|
|
61
62
|
// Explicitly remove the 'direction' prop passed to super, as it's handled by flexDirection
|
|
62
63
|
direction: undefined,
|
|
64
|
+
// Pass undefined for gap to prevent BoxNode from trying to parse it
|
|
65
|
+
gap: undefined,
|
|
63
66
|
});
|
|
64
67
|
this.columns = columns;
|
|
65
68
|
this.columnGapValue = columnGap;
|
|
66
69
|
this.rowGapValue = rowGap;
|
|
67
70
|
this.isVertical = isVertical;
|
|
71
|
+
// Explicitly set gaps on this.node after super() call
|
|
72
|
+
// These will be updated again in updateLayoutBasedOnComputedSize, but this ensures initial setup
|
|
73
|
+
if (typeof columnGap === 'number') {
|
|
74
|
+
this.node.setGap(common_const.Style.Gutter.Column, columnGap);
|
|
75
|
+
}
|
|
76
|
+
else if (typeof columnGap === 'string' && columnGap.endsWith('%')) {
|
|
77
|
+
this.node.setGapPercent(common_const.Style.Gutter.Column, parseFloat(columnGap));
|
|
78
|
+
}
|
|
79
|
+
if (typeof rowGap === 'number') {
|
|
80
|
+
this.node.setGap(common_const.Style.Gutter.Row, rowGap);
|
|
81
|
+
}
|
|
82
|
+
else if (typeof rowGap === 'string' && rowGap.endsWith('%')) {
|
|
83
|
+
this.node.setGapPercent(common_const.Style.Gutter.Row, parseFloat(rowGap));
|
|
84
|
+
}
|
|
68
85
|
}
|
|
69
86
|
/**
|
|
70
87
|
* Appends a child node to this grid.
|
|
71
88
|
* Overridden primarily for documentation/clarity, functionality is inherited.
|
|
72
|
-
* @param child
|
|
73
|
-
* @param index
|
|
89
|
+
* @param child Child node to append
|
|
90
|
+
* @param index Index at which to insert the child
|
|
74
91
|
*/
|
|
75
92
|
appendChild(child, index) {
|
|
76
93
|
super.appendChild(child, index);
|
|
@@ -253,7 +270,7 @@ class GridNode extends layout_canvas_util.RowNode {
|
|
|
253
270
|
}
|
|
254
271
|
/**
|
|
255
272
|
* Factory function to create a new GridNode instance.
|
|
256
|
-
* @param props
|
|
273
|
+
* @param props Grid configuration properties.
|
|
257
274
|
* @returns A new GridNode instance.
|
|
258
275
|
*/
|
|
259
276
|
const Grid = (props) => new GridNode(props);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid.canvas.util.js","sources":["../../../../src/canvas/grid.canvas.util.ts"],"sourcesContent":["import type { GridProps } from '@/canvas/canvas.type.js'\nimport { BoxNode, RowNode } from '@/canvas/layout.canvas.util.js'\nimport { Style, FlexDirection } from '@/constant/common.const.js'\n\n/**\n * Grid layout node that arranges children in a configurable number of columns or rows.\n * Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.\n * @extends RowNode\n */\nexport class GridNode extends RowNode {\n private readonly columns: number\n private readonly columnGapValue: number | `${number}%`\n private readonly rowGapValue: number | `${number}%`\n private readonly isVertical: boolean // True if the main axis is vertical (flexDirection: column or column-reverse)\n\n /**\n * Creates a new grid layout node\n * @param props - Grid configuration properties\n */\n constructor(props: GridProps) {\n const columns = Math.max(1, props.columns || 1)\n const direction = props.direction || 'row' // Default to horizontal row\n const isVertical = direction === 'column' || direction === 'column-reverse'\n\n // Map direction string to Yoga FlexDirection\n let flexDirection: FlexDirection\n switch (direction) {\n case 'row':\n flexDirection = Style.FlexDirection.Row\n break\n case 'column':\n flexDirection = Style.FlexDirection.Column\n break\n case 'row-reverse':\n flexDirection = Style.FlexDirection.RowReverse\n break\n case 'column-reverse':\n flexDirection = Style.FlexDirection.ColumnReverse\n break\n default:\n console.warn(`[GridNode] Invalid direction \"${direction}\". Defaulting to \"row\".`)\n flexDirection = Style.FlexDirection.Row\n }\n\n // Determine the column and row gap values from props\n let columnGap: number | `${number}%` = 0\n let rowGap: number | `${number}%` = 0\n\n if (typeof props.gap === 'number' || (typeof props.gap === 'string' && props.gap.trim() !== '')) {\n // Single value applies to both row and column gaps\n columnGap = props.gap\n rowGap = props.gap\n } else if (props.gap && typeof props.gap === 'object') {\n // Object format: prioritize a specific direction (Column/Row), then All\n columnGap = props.gap.Column ?? props.gap.All ?? 0\n rowGap = props.gap.Row ?? props.gap.All ?? 0\n }\n\n super({\n name: 'Grid',\n flexWrap: Style.Wrap.Wrap, // Essential for grid behavior\n flexDirection,\n ...props,\n // Explicitly remove the 'direction' prop passed to super, as it's handled by flexDirection\n direction: undefined,\n })\n\n this.columns = columns\n this.columnGapValue = columnGap\n this.rowGapValue = rowGap\n this.isVertical = isVertical\n }\n\n /**\n * Appends a child node to this grid.\n * Overridden primarily for documentation/clarity, functionality is inherited.\n * @param child - Child node to append\n * @param index - Index at which to insert the child\n */\n protected override appendChild(child: BoxNode, index: number) {\n super.appendChild(child, index)\n }\n\n /**\n * Update layout calculations after the initial layout is computed.\n * This method calculates the appropriate flex-basis for children based on the\n * number of columns and gaps, respecting the container's padding,\n * and applies the gaps using Yoga's built-in properties.\n */\n protected override updateLayoutBasedOnComputedSize() {\n // Step 1: Early return if the grid is empty or invalid\n if (this.columns <= 0 || this.children.length === 0) {\n return\n }\n\n // Step 2: Get container dimensions and padding after the initial layout\n const width = this.node.getComputedWidth()\n const height = this.node.getComputedHeight()\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n\n // Calculate content box dimensions\n const contentWidth = Math.max(0, width - paddingLeft - paddingRight)\n const contentHeight = Math.max(0, height - paddingTop - paddingBottom)\n\n // Step 3: Validate dimensions needed for calculations\n if (!this.isVertical && contentWidth <= 0 && width > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content width (${contentWidth}) is zero or negative after accounting for padding (${paddingLeft}+${paddingRight}) on total width ${width}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n if (this.isVertical && contentHeight <= 0 && height > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content height (${contentHeight}) is zero or negative after accounting for padding (${paddingTop}+${paddingBottom}) on total height ${height}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n\n // Step 4: Calculate Gap Values in Pixels\n let columnGapPixels = 0\n if (typeof this.columnGapValue === 'number') {\n columnGapPixels = this.columnGapValue\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.columnGapValue)\n if (!isNaN(percent) && contentWidth > 0) {\n columnGapPixels = (percent / 100) * contentWidth\n } else if (isNaN(percent)) {\n console.warn(\n `[GridNode ${this.props.key}] Invalid percentage column gap format: \"${this.columnGapValue}\". Using 0px.`,\n )\n } else if (contentWidth <= 0) {\n console.warn(\n `[GridNode ${this.props.key}] Cannot calculate percentage column gap (${this.columnGapValue}) because content width is zero. Using 0px.`,\n )\n }\n } catch (e) {\n console.warn(\n `[GridNode ${this.props.key}] Error parsing percentage column gap: \"${this.columnGapValue}\". Using 0px.`,\n e,\n )\n }\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string column gap format: \"${this.columnGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n let rowGapPixels = 0\n if (typeof this.rowGapValue === 'number') {\n rowGapPixels = this.rowGapValue\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.rowGapValue)\n if (!isNaN(percent) && contentHeight > 0) {\n rowGapPixels = (percent / 100) * contentHeight\n } else if (isNaN(percent)) {\n console.warn(\n `[GridNode ${this.props.key}] Invalid percentage row gap format: \"${this.rowGapValue}\". Using 0px.`,\n )\n } else if (contentHeight <= 0) {\n console.warn(\n `[GridNode ${this.props.key}] Cannot calculate percentage row gap (${this.rowGapValue}) because content height is zero. Using 0px.`,\n )\n }\n } catch (e) {\n console.warn(\n `[GridNode ${this.props.key}] Error parsing percentage row gap: \"${this.rowGapValue}\". Using 0px.`,\n e,\n )\n }\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string row gap format: \"${this.rowGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n // Ensure gaps are not negative\n columnGapPixels = Math.max(0, columnGapPixels)\n rowGapPixels = Math.max(0, rowGapPixels)\n\n // Step 5: Calculate flex-basis percentage for children\n const mainAxisGapPixels = this.isVertical ? rowGapPixels : columnGapPixels\n const mainAxisContentSize = this.isVertical ? contentHeight : contentWidth\n let childWidth = 0\n\n if (mainAxisContentSize > 0 && this.columns > 0) {\n // Total space taken up by gaps on the main axis\n const totalGapSpaceOnMainAxis = this.columns > 1 ? mainAxisGapPixels * (this.columns - 1) : 0\n\n // Calculate the space available *only* for the items themselves\n const availableSpaceOnMainAxis = Math.max(0, mainAxisContentSize - totalGapSpaceOnMainAxis)\n\n // Calculate the exact pixel of the total content size that each item should occupy\n const exactItemWidth = availableSpaceOnMainAxis / this.columns\n\n // Ensure it's not negative (shouldn't happen, but safety)\n childWidth = Math.max(0, exactItemWidth - 0.5) // Slightly reduce to avoid rounding issues\n } else if (this.columns === 1) {\n // If only one column, it takes up the full basis (gaps don't apply)\n childWidth = mainAxisContentSize\n }\n\n // Clamp basis percentage between 0 and 100 (mostly redundant after floor/max(0) but safe)\n childWidth = Math.max(0, Math.min(mainAxisContentSize, childWidth))\n\n // Step 6: Apply layout properties to children\n let childrenNeedRecalculation = false\n for (const child of this.children) {\n let childChanged = false\n const currentLayoutWidth = child.node.getWidth()\n const currentWidthValue = currentLayoutWidth.value\n const currentWidthUnit = currentLayoutWidth.unit\n\n let widthNeedsUpdate = false\n if (currentWidthUnit === Style.Unit.Point) {\n // If current width is in points, check if the value is significantly different\n if (Math.abs(currentWidthValue - childWidth) > 0.01) {\n widthNeedsUpdate = true\n }\n } else {\n // If current width is not in points (e.g., Auto, Percent, Undefined), it needs to be set to points\n widthNeedsUpdate = true\n }\n\n if (widthNeedsUpdate) {\n child.node.setWidth(childWidth)\n childChanged = true\n }\n\n // Ensure grow/shrink are set correctly for grid items\n if (child.node.getFlexGrow() !== 0) {\n child.node.setFlexGrow(0)\n childChanged = true\n }\n if (child.node.getFlexShrink() !== 1) {\n child.node.setFlexShrink(1) // Allow shrinking\n childChanged = true\n }\n\n // Remove margins that might interfere with gap property\n if (child.node.getMargin(Style.Edge.Bottom).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Bottom, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Right).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Right, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Top).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Top, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Left).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Left, undefined)\n childChanged = true\n }\n\n if (childChanged && !child.node.isDirty()) {\n child.node.markDirty()\n childrenNeedRecalculation = true\n }\n }\n\n // Step 7: Apply gaps using Yoga's built-in gap properties\n const currentColumnGap = this.node.getGap(Style.Gutter.Column).value\n const currentRowGap = this.node.getGap(Style.Gutter.Row).value\n let gapsChanged = false\n\n // Use a small tolerance for comparing gap pixels\n if (Math.abs(currentColumnGap - columnGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Column, columnGapPixels)\n gapsChanged = true\n }\n if (Math.abs(currentRowGap - rowGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Row, rowGapPixels)\n gapsChanged = true\n }\n\n // Step 8: Mark the grid node itself as dirty if gaps changed or children changed\n if ((gapsChanged || childrenNeedRecalculation) && !this.node.isDirty()) {\n this.node.markDirty()\n }\n }\n}\n\n/**\n * Factory function to create a new GridNode instance.\n * @param props - Grid configuration properties.\n * @returns A new GridNode instance.\n */\nexport const Grid = (props: GridProps) => new GridNode(props)\n"],"names":["RowNode","Style"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"grid.canvas.util.js","sources":["../../../../src/canvas/grid.canvas.util.ts"],"sourcesContent":["// TODO: Add comprehensive unit tests for this file.\n\nimport type { GridProps } from '@/canvas/canvas.type.js'\nimport { BoxNode, RowNode } from '@/canvas/layout.canvas.util.js'\nimport { Style, FlexDirection } from '@/constant/common.const.js'\n\n/**\n * Grid layout node that arranges children in a configurable number of columns or rows.\n * Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.\n * @extends RowNode\n */\nexport class GridNode extends RowNode {\n private readonly columns: number\n private readonly columnGapValue: number | `${number}%`\n private readonly rowGapValue: number | `${number}%`\n private readonly isVertical: boolean // True if the main axis is vertical (flexDirection: column or column-reverse)\n\n /**\n * Creates a new grid layout node\n * @param props Grid configuration properties\n */\n constructor(props: GridProps) {\n const columns = Math.max(1, props.columns || 1)\n const direction = props.direction || 'row' // Default to horizontal row\n const isVertical = direction === 'column' || direction === 'column-reverse'\n\n // Map direction string to Yoga FlexDirection\n let flexDirection: FlexDirection\n switch (direction) {\n case 'row':\n flexDirection = Style.FlexDirection.Row\n break\n case 'column':\n flexDirection = Style.FlexDirection.Column\n break\n case 'row-reverse':\n flexDirection = Style.FlexDirection.RowReverse\n break\n case 'column-reverse':\n flexDirection = Style.FlexDirection.ColumnReverse\n break\n default:\n console.warn(`[GridNode] Invalid direction \"${direction}\". Defaulting to \"row\".`)\n flexDirection = Style.FlexDirection.Row\n }\n\n // Determine the column and row gap values from props\n let columnGap: number | `${number}%` = 0\n let rowGap: number | `${number}%` = 0\n\n if (typeof props.gap === 'number' || (typeof props.gap === 'string' && props.gap.trim() !== '')) {\n // Single value applies to both row and column gaps\n columnGap = props.gap\n rowGap = props.gap\n } else if (props.gap && typeof props.gap === 'object') {\n // Object format: prioritize a specific direction (Column/Row), then All\n columnGap = props.gap.Column ?? props.gap.All ?? 0\n rowGap = props.gap.Row ?? props.gap.All ?? 0\n }\n\n super({\n name: 'Grid',\n flexWrap: Style.Wrap.Wrap, // Essential for grid behavior\n flexDirection,\n ...props,\n // Explicitly remove the 'direction' prop passed to super, as it's handled by flexDirection\n direction: undefined,\n // Pass undefined for gap to prevent BoxNode from trying to parse it\n gap: undefined,\n })\n\n this.columns = columns\n this.columnGapValue = columnGap\n this.rowGapValue = rowGap\n this.isVertical = isVertical\n\n // Explicitly set gaps on this.node after super() call\n // These will be updated again in updateLayoutBasedOnComputedSize, but this ensures initial setup\n if (typeof columnGap === 'number') {\n this.node.setGap(Style.Gutter.Column, columnGap)\n } else if (typeof columnGap === 'string' && columnGap.endsWith('%')) {\n this.node.setGapPercent(Style.Gutter.Column, parseFloat(columnGap))\n }\n if (typeof rowGap === 'number') {\n this.node.setGap(Style.Gutter.Row, rowGap)\n } else if (typeof rowGap === 'string' && rowGap.endsWith('%')) {\n this.node.setGapPercent(Style.Gutter.Row, parseFloat(rowGap))\n }\n }\n\n /**\n * Appends a child node to this grid.\n * Overridden primarily for documentation/clarity, functionality is inherited.\n * @param child Child node to append\n * @param index Index at which to insert the child\n */\n protected override appendChild(child: BoxNode, index: number) {\n super.appendChild(child, index)\n }\n\n /**\n * Update layout calculations after the initial layout is computed.\n * This method calculates the appropriate flex-basis for children based on the\n * number of columns and gaps, respecting the container's padding,\n * and applies the gaps using Yoga's built-in properties.\n */\n protected override updateLayoutBasedOnComputedSize() {\n // Step 1: Early return if the grid is empty or invalid\n if (this.columns <= 0 || this.children.length === 0) {\n return\n }\n\n // Step 2: Get container dimensions and padding after the initial layout\n const width = this.node.getComputedWidth()\n const height = this.node.getComputedHeight()\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n\n // Calculate content box dimensions\n const contentWidth = Math.max(0, width - paddingLeft - paddingRight)\n const contentHeight = Math.max(0, height - paddingTop - paddingBottom)\n\n // Step 3: Validate dimensions needed for calculations\n if (!this.isVertical && contentWidth <= 0 && width > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content width (${contentWidth}) is zero or negative after accounting for padding (${paddingLeft}+${paddingRight}) on total width ${width}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n if (this.isVertical && contentHeight <= 0 && height > 0) {\n console.warn(\n `[GridNode ${this.props.key} - Finalize] Grid content height (${contentHeight}) is zero or negative after accounting for padding (${paddingTop}+${paddingBottom}) on total height ${height}. Cannot calculate basis.`,\n )\n if (this.columns > 1) return\n }\n\n // Step 4: Calculate Gap Values in Pixels\n let columnGapPixels = 0\n if (typeof this.columnGapValue === 'number') {\n columnGapPixels = this.columnGapValue\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.columnGapValue)\n if (!isNaN(percent) && contentWidth > 0) {\n columnGapPixels = (percent / 100) * contentWidth\n } else if (isNaN(percent)) {\n console.warn(`[GridNode ${this.props.key}] Invalid percentage column gap format: \"${this.columnGapValue}\". Using 0px.`)\n } else if (contentWidth <= 0) {\n console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage column gap (${this.columnGapValue}) because content width is zero. Using 0px.`)\n }\n } catch (e) {\n console.warn(`[GridNode ${this.props.key}] Error parsing percentage column gap: \"${this.columnGapValue}\". Using 0px.`, e)\n }\n } else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string column gap format: \"${this.columnGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n let rowGapPixels = 0\n if (typeof this.rowGapValue === 'number') {\n rowGapPixels = this.rowGapValue\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim().endsWith('%')) {\n try {\n const percent = parseFloat(this.rowGapValue)\n if (!isNaN(percent) && contentHeight > 0) {\n rowGapPixels = (percent / 100) * contentHeight\n } else if (isNaN(percent)) {\n console.warn(`[GridNode ${this.props.key}] Invalid percentage row gap format: \"${this.rowGapValue}\". Using 0px.`)\n } else if (contentHeight <= 0) {\n console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage row gap (${this.rowGapValue}) because content height is zero. Using 0px.`)\n }\n } catch (e) {\n console.warn(`[GridNode ${this.props.key}] Error parsing percentage row gap: \"${this.rowGapValue}\". Using 0px.`, e)\n }\n } else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim() !== '') {\n console.warn(\n `[GridNode ${this.props.key}] Unsupported string row gap format: \"${this.rowGapValue}\". Using 0px. Only numbers and percentages ('%') are supported.`,\n )\n }\n\n // Ensure gaps are not negative\n columnGapPixels = Math.max(0, columnGapPixels)\n rowGapPixels = Math.max(0, rowGapPixels)\n\n // Step 5: Calculate flex-basis percentage for children\n const mainAxisGapPixels = this.isVertical ? rowGapPixels : columnGapPixels\n const mainAxisContentSize = this.isVertical ? contentHeight : contentWidth\n let childWidth = 0\n\n if (mainAxisContentSize > 0 && this.columns > 0) {\n // Total space taken up by gaps on the main axis\n const totalGapSpaceOnMainAxis = this.columns > 1 ? mainAxisGapPixels * (this.columns - 1) : 0\n\n // Calculate the space available *only* for the items themselves\n const availableSpaceOnMainAxis = Math.max(0, mainAxisContentSize - totalGapSpaceOnMainAxis)\n\n // Calculate the exact pixel of the total content size that each item should occupy\n const exactItemWidth = availableSpaceOnMainAxis / this.columns\n\n // Ensure it's not negative (shouldn't happen, but safety)\n childWidth = Math.max(0, exactItemWidth - 0.5) // Slightly reduce to avoid rounding issues\n } else if (this.columns === 1) {\n // If only one column, it takes up the full basis (gaps don't apply)\n childWidth = mainAxisContentSize\n }\n\n // Clamp basis percentage between 0 and 100 (mostly redundant after floor/max(0) but safe)\n childWidth = Math.max(0, Math.min(mainAxisContentSize, childWidth))\n\n // Step 6: Apply layout properties to children\n let childrenNeedRecalculation = false\n for (const child of this.children) {\n let childChanged = false\n const currentLayoutWidth = child.node.getWidth()\n const currentWidthValue = currentLayoutWidth.value\n const currentWidthUnit = currentLayoutWidth.unit\n\n let widthNeedsUpdate = false\n if (currentWidthUnit === Style.Unit.Point) {\n // If current width is in points, check if the value is significantly different\n if (Math.abs(currentWidthValue - childWidth) > 0.01) {\n widthNeedsUpdate = true\n }\n } else {\n // If current width is not in points (e.g., Auto, Percent, Undefined), it needs to be set to points\n widthNeedsUpdate = true\n }\n\n if (widthNeedsUpdate) {\n child.node.setWidth(childWidth)\n childChanged = true\n }\n\n // Ensure grow/shrink are set correctly for grid items\n if (child.node.getFlexGrow() !== 0) {\n child.node.setFlexGrow(0)\n childChanged = true\n }\n if (child.node.getFlexShrink() !== 1) {\n child.node.setFlexShrink(1) // Allow shrinking\n childChanged = true\n }\n\n // Remove margins that might interfere with gap property\n if (child.node.getMargin(Style.Edge.Bottom).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Bottom, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Right).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Right, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Top).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Top, undefined)\n childChanged = true\n }\n if (child.node.getMargin(Style.Edge.Left).unit !== Style.Unit.Undefined) {\n child.node.setMargin(Style.Edge.Left, undefined)\n childChanged = true\n }\n\n if (childChanged && !child.node.isDirty()) {\n child.node.markDirty()\n childrenNeedRecalculation = true\n }\n }\n\n // Step 7: Apply gaps using Yoga's built-in gap properties\n const currentColumnGap = this.node.getGap(Style.Gutter.Column).value\n const currentRowGap = this.node.getGap(Style.Gutter.Row).value\n let gapsChanged = false\n\n // Use a small tolerance for comparing gap pixels\n if (Math.abs(currentColumnGap - columnGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Column, columnGapPixels)\n gapsChanged = true\n }\n if (Math.abs(currentRowGap - rowGapPixels) > 0.001) {\n this.node.setGap(Style.Gutter.Row, rowGapPixels)\n gapsChanged = true\n }\n\n // Step 8: Mark the grid node itself as dirty if gaps changed or children changed\n if ((gapsChanged || childrenNeedRecalculation) && !this.node.isDirty()) {\n this.node.markDirty()\n }\n }\n}\n\n/**\n * Factory function to create a new GridNode instance.\n * @param props Grid configuration properties.\n * @returns A new GridNode instance.\n */\nexport const Grid = (props: GridProps) => new GridNode(props)\n"],"names":["RowNode","Style"],"mappings":"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"}
|
|
@@ -15,7 +15,6 @@ export declare class ImageNode extends BoxNode {
|
|
|
15
15
|
/**
|
|
16
16
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
17
17
|
* Handles SVG color modifications and sets natural dimensions with an aspect ratio.
|
|
18
|
-
*
|
|
19
18
|
* @returns Promise that resolves when image loading completes
|
|
20
19
|
* @throws Error if image loading fails
|
|
21
20
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,KAAK,wBAAwB,EAAmC,MAAM,aAAa,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAsBxD;;;GAGG;AACH,qBAAa,SAAU,SAAQ,OAAO;IAC5B,KAAK,EAAE,UAAU,GAAG,SAAS,CAAA;IACrC,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;gBAEhD,KAAK,EAAE,UAAU;IAc7B;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IA8GX,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;;OAGG;cACgB,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAoJrH;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,cAAyB,CAAA"}
|
|
@@ -6,6 +6,7 @@ var canvas_helper = require('./canvas.helper.js');
|
|
|
6
6
|
var fs = require('fs');
|
|
7
7
|
var common_const = require('../constant/common.const.js');
|
|
8
8
|
|
|
9
|
+
// TODO: Add comprehensive unit tests for this file.
|
|
9
10
|
/**
|
|
10
11
|
* Calculates pixel offset for image positioning based on percentage or pixel values.
|
|
11
12
|
* This handles centering, edge alignment, and percentage-based positioning.
|
|
@@ -45,7 +46,6 @@ class ImageNode extends layout_canvas_util.BoxNode {
|
|
|
45
46
|
/**
|
|
46
47
|
* Loads and processes an image from various sources (URL, file path, or Buffer).
|
|
47
48
|
* Handles SVG color modifications and sets natural dimensions with an aspect ratio.
|
|
48
|
-
*
|
|
49
49
|
* @returns Promise that resolves when image loading completes
|
|
50
50
|
* @throws Error if image loading fails
|
|
51
51
|
*/
|
|
@@ -61,92 +61,92 @@ class ImageNode extends layout_canvas_util.BoxNode {
|
|
|
61
61
|
this.naturalHeight = 0;
|
|
62
62
|
return Promise.resolve();
|
|
63
63
|
}
|
|
64
|
-
return new Promise(
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (this.props.src
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
isSvg = detectedMime === 'image/svg+xml';
|
|
83
|
-
if ((!detectedMime || detectedMime === 'application/xml') &&
|
|
84
|
-
contentBuffer.toString('utf-8').includes('<svg')) {
|
|
85
|
-
isSvg = true;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
finalSource = this.props.src;
|
|
90
|
-
const filePath = this.props.src;
|
|
91
|
-
try {
|
|
92
|
-
const fileTypeResult = await fileTypeFromFile(filePath);
|
|
64
|
+
return new Promise(resolve => {
|
|
65
|
+
const load = async () => {
|
|
66
|
+
const { fileTypeFromBuffer, fileTypeFromFile } = await import('file-type');
|
|
67
|
+
let finalSource = this.props.src;
|
|
68
|
+
let isSvg = false;
|
|
69
|
+
let contentBuffer = null;
|
|
70
|
+
let detectedMime;
|
|
71
|
+
try {
|
|
72
|
+
if (typeof this.props.src === 'string') {
|
|
73
|
+
if (this.props.src.startsWith('http')) {
|
|
74
|
+
const response = await fetch(this.props.src);
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
throw new Error(`HTTP error ${response.status} fetching image: ${this.props.src}`);
|
|
77
|
+
}
|
|
78
|
+
const imageArrayBuffer = await response.arrayBuffer();
|
|
79
|
+
contentBuffer = Buffer.from(imageArrayBuffer);
|
|
80
|
+
finalSource = contentBuffer;
|
|
81
|
+
const fileTypeResult = await fileTypeFromBuffer(contentBuffer);
|
|
93
82
|
detectedMime = fileTypeResult?.mime;
|
|
94
83
|
isSvg = detectedMime === 'image/svg+xml';
|
|
95
|
-
if ((!detectedMime || detectedMime === 'application/xml') &&
|
|
84
|
+
if ((!detectedMime || detectedMime === 'application/xml') && contentBuffer.toString('utf-8').includes('<svg')) {
|
|
96
85
|
isSvg = true;
|
|
97
86
|
}
|
|
98
87
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (isSvg && this.props.color) {
|
|
88
|
+
else {
|
|
89
|
+
finalSource = this.props.src;
|
|
90
|
+
const filePath = this.props.src;
|
|
103
91
|
try {
|
|
104
|
-
|
|
92
|
+
const fileTypeResult = await fileTypeFromFile(filePath);
|
|
93
|
+
detectedMime = fileTypeResult?.mime;
|
|
94
|
+
isSvg = detectedMime === 'image/svg+xml';
|
|
95
|
+
if ((!detectedMime || detectedMime === 'application/xml') && filePath.toLowerCase().endsWith('.svg')) {
|
|
96
|
+
isSvg = true;
|
|
97
|
+
}
|
|
105
98
|
}
|
|
106
99
|
catch {
|
|
107
|
-
isSvg =
|
|
108
|
-
|
|
100
|
+
isSvg = filePath.toLowerCase().endsWith('.svg');
|
|
101
|
+
}
|
|
102
|
+
if (isSvg && this.props.color) {
|
|
103
|
+
try {
|
|
104
|
+
contentBuffer = await fs.promises.readFile(filePath);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
isSvg = false;
|
|
108
|
+
contentBuffer = null;
|
|
109
|
+
}
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
contentBuffer = this.props.src;
|
|
115
|
-
finalSource = contentBuffer;
|
|
116
|
-
const fileTypeResult = await fileTypeFromBuffer(contentBuffer);
|
|
117
|
-
detectedMime = fileTypeResult?.mime;
|
|
118
|
-
isSvg = detectedMime === 'image/svg+xml';
|
|
119
|
-
}
|
|
120
|
-
if (isSvg && this.props.color && contentBuffer) {
|
|
121
|
-
const svgString = contentBuffer.toString('utf-8');
|
|
122
|
-
const modifiedSvgString = svgString.replace(/fill="[^"]*"/g, `fill="${this.props.color}"`);
|
|
123
|
-
if (modifiedSvgString !== svgString) {
|
|
124
|
-
finalSource = Buffer.from(modifiedSvgString);
|
|
125
|
-
}
|
|
126
113
|
else {
|
|
114
|
+
contentBuffer = this.props.src;
|
|
127
115
|
finalSource = contentBuffer;
|
|
116
|
+
const fileTypeResult = await fileTypeFromBuffer(contentBuffer);
|
|
117
|
+
detectedMime = fileTypeResult?.mime;
|
|
118
|
+
isSvg = detectedMime === 'image/svg+xml';
|
|
128
119
|
}
|
|
120
|
+
if (isSvg && this.props.color && contentBuffer) {
|
|
121
|
+
const svgString = contentBuffer.toString('utf-8');
|
|
122
|
+
const modifiedSvgString = svgString.replace(/fill="[^"]*"/g, `fill="${this.props.color}"`);
|
|
123
|
+
if (modifiedSvgString !== svgString) {
|
|
124
|
+
finalSource = Buffer.from(modifiedSvgString);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
finalSource = contentBuffer;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const img = await skiaCanvas.loadImage(finalSource);
|
|
131
|
+
this.loadedImage = img;
|
|
132
|
+
this.naturalWidth = img.width;
|
|
133
|
+
this.naturalHeight = img.height;
|
|
134
|
+
const calculatedAspectRatio = this.naturalWidth > 0 && this.naturalHeight > 0 ? this.naturalWidth / this.naturalHeight : undefined;
|
|
135
|
+
const finalAspectRatio = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : calculatedAspectRatio;
|
|
136
|
+
this.node.setAspectRatio(finalAspectRatio);
|
|
137
|
+
this.props.onLoad?.();
|
|
138
|
+
resolve();
|
|
129
139
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
resolve();
|
|
141
|
-
}
|
|
142
|
-
catch (error) {
|
|
143
|
-
this.naturalWidth = 0;
|
|
144
|
-
this.naturalHeight = 0;
|
|
145
|
-
const finalAspectRatioOnError = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined;
|
|
146
|
-
this.node.setAspectRatio(finalAspectRatioOnError);
|
|
147
|
-
this.props.onError?.(error);
|
|
148
|
-
resolve();
|
|
149
|
-
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
this.naturalWidth = 0;
|
|
142
|
+
this.naturalHeight = 0;
|
|
143
|
+
const finalAspectRatioOnError = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined;
|
|
144
|
+
this.node.setAspectRatio(finalAspectRatioOnError);
|
|
145
|
+
this.props.onError?.(error);
|
|
146
|
+
resolve();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
load();
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
getLoadingPromise() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.canvas.util.js","sources":["../../../../src/canvas/image.canvas.util.ts"],"sourcesContent":["import type { BaseProps, ImageProps } from '@/canvas/canvas.type.js'\nimport { type CanvasRenderingContext2D, Image as CanvasImage, loadImage } from 'skia-canvas'\nimport { BoxNode } from '@/canvas/layout.canvas.util.js'\nimport { drawRoundedRectPath, parseBorderRadius } from '@/canvas/canvas.helper.js'\nimport { promises as fs } from 'fs'\nimport { Style } from '@/constant/common.const.js'\n\n/**\n * Calculates pixel offset for image positioning based on percentage or pixel values.\n * This handles centering, edge alignment, and percentage-based positioning.\n */\nfunction calculateOffsetFromValue(positionValue: number | `${number}%` | undefined, availableSpace: number): number {\n const value = positionValue ?? '50%'\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string' && value.endsWith('%')) {\n const percentage = parseFloat(value) / 100\n return availableSpace * percentage\n }\n console.warn(`[ImageNode] Invalid objectPosition value format: ${value}. Defaulting to 50%.`)\n return availableSpace * 0.5\n}\n\n/**\n * Renders images with configurable sizing, positioning, and effects.\n * Supports object-fit modes, positioning, border radius, and saturation filters.\n */\nexport class ImageNode extends BoxNode {\n declare props: ImageProps & BaseProps\n private loadedImage: CanvasImage | null = null\n private naturalWidth = 0\n private naturalHeight = 0\n private readonly loadingPromise: Promise<void> | null = null\n\n constructor(props: ImageProps) {\n super({ name: 'Image', ...props, children: undefined })\n\n this.props = {\n objectFit: 'fill',\n overflow: Style.Overflow.Hidden,\n saturate: 1,\n objectPosition: { Left: '50%', Top: '50%' },\n ...props,\n }\n\n this.loadingPromise = this._loadImage()\n }\n\n /**\n * Loads and processes an image from various sources (URL, file path, or Buffer).\n * Handles SVG color modifications and sets natural dimensions with an aspect ratio.\n *\n * @returns Promise that resolves when image loading completes\n * @throws Error if image loading fails\n */\n private _loadImage(): Promise<void> {\n if (this.loadingPromise) return this.loadingPromise\n if (this.loadedImage) return Promise.resolve()\n\n if (!this.props.src) {\n const aspectRatioFromProps =\n typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(aspectRatioFromProps)\n this.naturalWidth = 0\n this.naturalHeight = 0\n\n return Promise.resolve()\n }\n\n return new Promise(async resolve => {\n const { fileTypeFromBuffer, fileTypeFromFile } = await import('file-type')\n let finalSource: string | Buffer = this.props.src\n let isSvg = false\n let contentBuffer: Buffer | null = null\n let detectedMime: string | undefined\n\n try {\n if (typeof this.props.src === 'string') {\n if (this.props.src.startsWith('http')) {\n const response = await fetch(this.props.src)\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status} fetching image: ${this.props.src}`)\n }\n const imageArrayBuffer = await response.arrayBuffer()\n contentBuffer = Buffer.from(imageArrayBuffer)\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if (\n (!detectedMime || detectedMime === 'application/xml') &&\n contentBuffer.toString('utf-8').includes('<svg')\n ) {\n isSvg = true\n }\n } else {\n finalSource = this.props.src\n const filePath = this.props.src\n\n try {\n const fileTypeResult = await fileTypeFromFile(filePath)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && filePath.toLowerCase().endsWith('.svg')) {\n isSvg = true\n }\n } catch {\n isSvg = filePath.toLowerCase().endsWith('.svg')\n }\n\n if (isSvg && this.props.color) {\n try {\n contentBuffer = await fs.readFile(filePath)\n } catch {\n isSvg = false\n contentBuffer = null\n }\n }\n }\n } else {\n contentBuffer = this.props.src\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n }\n\n if (isSvg && this.props.color && contentBuffer) {\n const svgString = contentBuffer.toString('utf-8')\n const modifiedSvgString = svgString.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`)\n\n if (modifiedSvgString !== svgString) {\n finalSource = Buffer.from(modifiedSvgString)\n } else {\n finalSource = contentBuffer\n }\n }\n\n const img = await loadImage(finalSource as never)\n this.loadedImage = img\n this.naturalWidth = img.width\n this.naturalHeight = img.height\n\n const calculatedAspectRatio =\n this.naturalWidth > 0 && this.naturalHeight > 0 ? this.naturalWidth / this.naturalHeight : undefined\n\n const finalAspectRatio =\n typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0\n ? this.props.aspectRatio\n : calculatedAspectRatio\n\n this.node.setAspectRatio(finalAspectRatio)\n\n this.props.onLoad?.()\n resolve()\n } catch (error: any) {\n this.naturalWidth = 0\n this.naturalHeight = 0\n const finalAspectRatioOnError =\n typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(finalAspectRatioOnError)\n this.props.onError?.(error)\n resolve()\n }\n })\n }\n\n public getLoadingPromise(): Promise<void> {\n return this.loadingPromise ?? Promise.resolve()\n }\n\n /**\n * Renders the image with correct sizing, clipping, and positioning.\n * Handles object-fit, object-position, and visual effects like saturation.\n */\n protected override _renderContent(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n ) {\n super._renderContent(ctx, x, y, width, height)\n\n if (!this.loadedImage || width <= 0 || height <= 0) return\n const img = this.loadedImage\n const imgW = this.naturalWidth\n const imgH = this.naturalHeight\n if (imgW <= 0 || imgH <= 0) return\n\n // Calculate content box accounting for padding and borders\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n const borderLeft = this.node.getComputedBorder(Style.Edge.Left)\n const borderTop = this.node.getComputedBorder(Style.Edge.Top)\n const borderRight = this.node.getComputedBorder(Style.Edge.Right)\n const borderBottom = this.node.getComputedBorder(Style.Edge.Bottom)\n const contentX = x + borderLeft + paddingLeft\n const contentY = y + borderTop + paddingTop\n const contentWidth = Math.max(0, width - borderLeft - paddingLeft - borderRight - paddingRight)\n const contentHeight = Math.max(0, height - borderTop - paddingTop - borderBottom - paddingBottom)\n\n if (contentWidth <= 0 || contentHeight <= 0) return\n\n // Apply clipping for border radius\n ctx.save()\n const outerRadii = parseBorderRadius(this.props.borderRadius)\n const innerBorderRadii = {\n TopLeft: Math.max(0, outerRadii.TopLeft - borderTop),\n TopRight: Math.max(0, outerRadii.TopRight - borderTop),\n BottomRight: Math.max(0, outerRadii.BottomRight - borderBottom),\n BottomLeft: Math.max(0, outerRadii.BottomLeft - borderBottom),\n }\n const contentRadii = {\n TopLeft: Math.max(0, innerBorderRadii.TopLeft - Math.max(paddingLeft, paddingTop)),\n TopRight: Math.max(0, innerBorderRadii.TopRight - Math.max(paddingRight, paddingTop)),\n BottomRight: Math.max(0, innerBorderRadii.BottomRight - Math.max(paddingRight, paddingBottom)),\n BottomLeft: Math.max(0, innerBorderRadii.BottomLeft - Math.max(paddingLeft, paddingBottom)),\n }\n drawRoundedRectPath(ctx, contentX, contentY, contentWidth, contentHeight, contentRadii)\n ctx.clip()\n\n // Calculate image dimensions based on object-fit\n const nodeRatio = contentWidth / contentHeight\n const imgRatio = imgW / imgH\n const objectFit = this.props.objectFit\n let dw = contentWidth\n let dh = contentHeight\n\n if (objectFit === 'contain') {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n } else if (objectFit === 'cover') {\n if (imgRatio > nodeRatio) {\n dh = contentHeight\n dw = contentHeight * imgRatio\n } else {\n dw = contentWidth\n dh = contentWidth / imgRatio\n }\n } else if (objectFit === 'none') {\n dw = imgW\n dh = imgH\n } else if (objectFit === 'scale-down') {\n if (imgW <= contentWidth && imgH <= contentHeight) {\n dw = imgW\n dh = imgH\n } else {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n }\n }\n\n // Calculate image position based on object-position\n const sx = 0\n const sy = 0\n const sw = imgW\n const sh = imgH\n\n const availableWidth = contentWidth - dw\n const availableHeight = contentHeight - dh\n const posProps = this.props.objectPosition || {}\n const horizontalValue =\n posProps.Left !== undefined ? posProps.Left : posProps.Right !== undefined ? posProps.Right : '50%'\n const verticalValue =\n posProps.Top !== undefined ? posProps.Top : posProps.Bottom !== undefined ? posProps.Bottom : '50%'\n\n let offsetX = calculateOffsetFromValue(horizontalValue, availableWidth)\n let offsetY = calculateOffsetFromValue(verticalValue, availableHeight)\n\n if (posProps.Left === undefined && posProps.Right !== undefined) {\n offsetX = availableWidth - offsetX\n }\n if (posProps.Top === undefined && posProps.Bottom !== undefined) {\n offsetY = availableHeight - offsetY\n }\n\n const dx = contentX + offsetX\n const dy = contentY + offsetY\n\n // Draw image with filters\n ctx.save()\n try {\n if (this.props.dropShadow) {\n const shadow = this.props.dropShadow\n const shadowBlur = Math.max(shadow.offsetX ?? 0, shadow.offsetY ?? 0)\n ctx.shadowOffsetX = shadow.offsetX ?? 0\n ctx.shadowOffsetY = shadow.offsetY ?? 0\n ctx.shadowBlur = Math.max(0, shadow.blur ?? shadowBlur)\n ctx.shadowColor = shadow.color ?? 'black'\n }\n\n const saturateValue = this.props.saturate ?? 1\n let filterString = ''\n if (saturateValue !== 1) {\n filterString += `saturate(${saturateValue * 100}%) `\n }\n\n if (filterString) {\n const currentFilter = ctx.filter && ctx.filter !== 'none' ? ctx.filter + ' ' : ''\n ctx.filter = currentFilter + filterString.trim()\n }\n\n const finalDX = Math.floor(dx)\n const finalDY = Math.floor(dy)\n const finalDW = Math.ceil(dw + (dx - finalDX))\n const finalDH = Math.ceil(dh + (dy - finalDY))\n\n if (finalDW > 0 && finalDH > 0) {\n ctx.drawImage(img, sx, sy, sw, sh, finalDX, finalDY, finalDW, finalDH)\n }\n } catch (drawError) {\n console.error('[ImageNode] Error drawing image:', drawError)\n } finally {\n ctx.restore()\n }\n\n ctx.restore()\n }\n}\n\n/**\n * Factory function to create ImageNode instances\n */\nexport const Image = (props: ImageProps) => new ImageNode(props)\n"],"names":["BoxNode","Style","fs","loadImage","parseBorderRadius","drawRoundedRectPath"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"image.canvas.util.js","sources":["../../../../src/canvas/image.canvas.util.ts"],"sourcesContent":["// TODO: Add comprehensive unit tests for this file.\n\nimport type { BaseProps, ImageProps } from '@/canvas/canvas.type.js'\nimport { type CanvasRenderingContext2D, Image as CanvasImage, loadImage } from 'skia-canvas'\nimport { BoxNode } from '@/canvas/layout.canvas.util.js'\nimport { drawRoundedRectPath, parseBorderRadius } from '@/canvas/canvas.helper.js'\nimport { promises as fs } from 'fs'\nimport { Style } from '@/constant/common.const.js'\n\n/**\n * Calculates pixel offset for image positioning based on percentage or pixel values.\n * This handles centering, edge alignment, and percentage-based positioning.\n */\nfunction calculateOffsetFromValue(positionValue: number | `${number}%` | undefined, availableSpace: number): number {\n const value = positionValue ?? '50%'\n if (typeof value === 'number') {\n return value\n }\n if (typeof value === 'string' && value.endsWith('%')) {\n const percentage = parseFloat(value) / 100\n return availableSpace * percentage\n }\n console.warn(`[ImageNode] Invalid objectPosition value format: ${value}. Defaulting to 50%.`)\n return availableSpace * 0.5\n}\n\n/**\n * Renders images with configurable sizing, positioning, and effects.\n * Supports object-fit modes, positioning, border radius, and saturation filters.\n */\nexport class ImageNode extends BoxNode {\n declare props: ImageProps & BaseProps\n private loadedImage: CanvasImage | null = null\n private naturalWidth = 0\n private naturalHeight = 0\n private readonly loadingPromise: Promise<void> | null = null\n\n constructor(props: ImageProps) {\n super({ name: 'Image', ...props, children: undefined })\n\n this.props = {\n objectFit: 'fill',\n overflow: Style.Overflow.Hidden,\n saturate: 1,\n objectPosition: { Left: '50%', Top: '50%' },\n ...props,\n }\n\n this.loadingPromise = this._loadImage()\n }\n\n /**\n * Loads and processes an image from various sources (URL, file path, or Buffer).\n * Handles SVG color modifications and sets natural dimensions with an aspect ratio.\n * @returns Promise that resolves when image loading completes\n * @throws Error if image loading fails\n */\n private _loadImage(): Promise<void> {\n if (this.loadingPromise) return this.loadingPromise\n if (this.loadedImage) return Promise.resolve()\n\n if (!this.props.src) {\n const aspectRatioFromProps = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(aspectRatioFromProps)\n this.naturalWidth = 0\n this.naturalHeight = 0\n\n return Promise.resolve()\n }\n\n return new Promise(resolve => {\n const load = async () => {\n const { fileTypeFromBuffer, fileTypeFromFile } = await import('file-type')\n let finalSource: string | Buffer = this.props.src\n let isSvg = false\n let contentBuffer: Buffer | null = null\n let detectedMime: string | undefined\n\n try {\n if (typeof this.props.src === 'string') {\n if (this.props.src.startsWith('http')) {\n const response = await fetch(this.props.src)\n if (!response.ok) {\n throw new Error(`HTTP error ${response.status} fetching image: ${this.props.src}`)\n }\n const imageArrayBuffer = await response.arrayBuffer()\n contentBuffer = Buffer.from(imageArrayBuffer)\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && contentBuffer.toString('utf-8').includes('<svg')) {\n isSvg = true\n }\n } else {\n finalSource = this.props.src\n const filePath = this.props.src\n\n try {\n const fileTypeResult = await fileTypeFromFile(filePath)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n\n if ((!detectedMime || detectedMime === 'application/xml') && filePath.toLowerCase().endsWith('.svg')) {\n isSvg = true\n }\n } catch {\n isSvg = filePath.toLowerCase().endsWith('.svg')\n }\n\n if (isSvg && this.props.color) {\n try {\n contentBuffer = await fs.readFile(filePath)\n } catch {\n isSvg = false\n contentBuffer = null\n }\n }\n }\n } else {\n contentBuffer = this.props.src\n finalSource = contentBuffer\n\n const fileTypeResult = await fileTypeFromBuffer(contentBuffer)\n detectedMime = fileTypeResult?.mime\n isSvg = detectedMime === 'image/svg+xml'\n }\n\n if (isSvg && this.props.color && contentBuffer) {\n const svgString = contentBuffer.toString('utf-8')\n const modifiedSvgString = svgString.replace(/fill=\"[^\"]*\"/g, `fill=\"${this.props.color}\"`)\n\n if (modifiedSvgString !== svgString) {\n finalSource = Buffer.from(modifiedSvgString)\n } else {\n finalSource = contentBuffer\n }\n }\n\n const img = await loadImage(finalSource as never)\n this.loadedImage = img\n this.naturalWidth = img.width\n this.naturalHeight = img.height\n\n const calculatedAspectRatio = this.naturalWidth > 0 && this.naturalHeight > 0 ? this.naturalWidth / this.naturalHeight : undefined\n\n const finalAspectRatio = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : calculatedAspectRatio\n\n this.node.setAspectRatio(finalAspectRatio)\n\n this.props.onLoad?.()\n resolve()\n } catch (error: any) {\n this.naturalWidth = 0\n this.naturalHeight = 0\n const finalAspectRatioOnError = typeof this.props.aspectRatio === 'number' && this.props.aspectRatio > 0 ? this.props.aspectRatio : undefined\n this.node.setAspectRatio(finalAspectRatioOnError)\n this.props.onError?.(error)\n resolve()\n }\n }\n load()\n })\n }\n\n public getLoadingPromise(): Promise<void> {\n return this.loadingPromise ?? Promise.resolve()\n }\n\n /**\n * Renders the image with correct sizing, clipping, and positioning.\n * Handles object-fit, object-position, and visual effects like saturation.\n */\n protected override _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {\n super._renderContent(ctx, x, y, width, height)\n\n if (!this.loadedImage || width <= 0 || height <= 0) return\n const img = this.loadedImage\n const imgW = this.naturalWidth\n const imgH = this.naturalHeight\n if (imgW <= 0 || imgH <= 0) return\n\n // Calculate content box accounting for padding and borders\n const paddingLeft = this.node.getComputedPadding(Style.Edge.Left)\n const paddingTop = this.node.getComputedPadding(Style.Edge.Top)\n const paddingRight = this.node.getComputedPadding(Style.Edge.Right)\n const paddingBottom = this.node.getComputedPadding(Style.Edge.Bottom)\n const borderLeft = this.node.getComputedBorder(Style.Edge.Left)\n const borderTop = this.node.getComputedBorder(Style.Edge.Top)\n const borderRight = this.node.getComputedBorder(Style.Edge.Right)\n const borderBottom = this.node.getComputedBorder(Style.Edge.Bottom)\n const contentX = x + borderLeft + paddingLeft\n const contentY = y + borderTop + paddingTop\n const contentWidth = Math.max(0, width - borderLeft - paddingLeft - borderRight - paddingRight)\n const contentHeight = Math.max(0, height - borderTop - paddingTop - borderBottom - paddingBottom)\n\n if (contentWidth <= 0 || contentHeight <= 0) return\n\n // Apply clipping for border radius\n ctx.save()\n const outerRadii = parseBorderRadius(this.props.borderRadius)\n const innerBorderRadii = {\n TopLeft: Math.max(0, outerRadii.TopLeft - borderTop),\n TopRight: Math.max(0, outerRadii.TopRight - borderTop),\n BottomRight: Math.max(0, outerRadii.BottomRight - borderBottom),\n BottomLeft: Math.max(0, outerRadii.BottomLeft - borderBottom),\n }\n const contentRadii = {\n TopLeft: Math.max(0, innerBorderRadii.TopLeft - Math.max(paddingLeft, paddingTop)),\n TopRight: Math.max(0, innerBorderRadii.TopRight - Math.max(paddingRight, paddingTop)),\n BottomRight: Math.max(0, innerBorderRadii.BottomRight - Math.max(paddingRight, paddingBottom)),\n BottomLeft: Math.max(0, innerBorderRadii.BottomLeft - Math.max(paddingLeft, paddingBottom)),\n }\n drawRoundedRectPath(ctx, contentX, contentY, contentWidth, contentHeight, contentRadii)\n ctx.clip()\n\n // Calculate image dimensions based on object-fit\n const nodeRatio = contentWidth / contentHeight\n const imgRatio = imgW / imgH\n const objectFit = this.props.objectFit\n let dw = contentWidth\n let dh = contentHeight\n\n if (objectFit === 'contain') {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n } else if (objectFit === 'cover') {\n if (imgRatio > nodeRatio) {\n dh = contentHeight\n dw = contentHeight * imgRatio\n } else {\n dw = contentWidth\n dh = contentWidth / imgRatio\n }\n } else if (objectFit === 'none') {\n dw = imgW\n dh = imgH\n } else if (objectFit === 'scale-down') {\n if (imgW <= contentWidth && imgH <= contentHeight) {\n dw = imgW\n dh = imgH\n } else {\n if (imgRatio > nodeRatio) {\n dw = contentWidth\n dh = contentWidth / imgRatio\n } else {\n dh = contentHeight\n dw = contentHeight * imgRatio\n }\n }\n }\n\n // Calculate image position based on object-position\n const sx = 0\n const sy = 0\n const sw = imgW\n const sh = imgH\n\n const availableWidth = contentWidth - dw\n const availableHeight = contentHeight - dh\n const posProps = this.props.objectPosition || {}\n const horizontalValue = posProps.Left !== undefined ? posProps.Left : posProps.Right !== undefined ? posProps.Right : '50%'\n const verticalValue = posProps.Top !== undefined ? posProps.Top : posProps.Bottom !== undefined ? posProps.Bottom : '50%'\n\n let offsetX = calculateOffsetFromValue(horizontalValue, availableWidth)\n let offsetY = calculateOffsetFromValue(verticalValue, availableHeight)\n\n if (posProps.Left === undefined && posProps.Right !== undefined) {\n offsetX = availableWidth - offsetX\n }\n if (posProps.Top === undefined && posProps.Bottom !== undefined) {\n offsetY = availableHeight - offsetY\n }\n\n const dx = contentX + offsetX\n const dy = contentY + offsetY\n\n // Draw image with filters\n ctx.save()\n try {\n if (this.props.dropShadow) {\n const shadow = this.props.dropShadow\n const shadowBlur = Math.max(shadow.offsetX ?? 0, shadow.offsetY ?? 0)\n ctx.shadowOffsetX = shadow.offsetX ?? 0\n ctx.shadowOffsetY = shadow.offsetY ?? 0\n ctx.shadowBlur = Math.max(0, shadow.blur ?? shadowBlur)\n ctx.shadowColor = shadow.color ?? 'black'\n }\n\n const saturateValue = this.props.saturate ?? 1\n let filterString = ''\n if (saturateValue !== 1) {\n filterString += `saturate(${saturateValue * 100}%) `\n }\n\n if (filterString) {\n const currentFilter = ctx.filter && ctx.filter !== 'none' ? ctx.filter + ' ' : ''\n ctx.filter = currentFilter + filterString.trim()\n }\n\n const finalDX = Math.floor(dx)\n const finalDY = Math.floor(dy)\n const finalDW = Math.ceil(dw + (dx - finalDX))\n const finalDH = Math.ceil(dh + (dy - finalDY))\n\n if (finalDW > 0 && finalDH > 0) {\n ctx.drawImage(img, sx, sy, sw, sh, finalDX, finalDY, finalDW, finalDH)\n }\n } catch (drawError) {\n console.error('[ImageNode] Error drawing image:', drawError)\n } finally {\n ctx.restore()\n }\n\n ctx.restore()\n }\n}\n\n/**\n * Factory function to create ImageNode instances\n */\nexport const Image = (props: ImageProps) => new ImageNode(props)\n"],"names":["BoxNode","Style","fs","loadImage","parseBorderRadius","drawRoundedRectPath"],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@ export declare class BoxNode {
|
|
|
33
33
|
key?: string;
|
|
34
34
|
/**
|
|
35
35
|
* Creates a new BoxNode instance
|
|
36
|
-
* @param props
|
|
36
|
+
* @param props Initial box properties and styling
|
|
37
37
|
*/
|
|
38
38
|
constructor(props?: BoxProps & BaseProps);
|
|
39
39
|
/**
|
|
@@ -42,7 +42,7 @@ export declare class BoxNode {
|
|
|
42
42
|
processInitialChildren(): void;
|
|
43
43
|
/**
|
|
44
44
|
* Inherits styles from the parent node.
|
|
45
|
-
* @param {BoxProps & BaseProps} parentProps
|
|
45
|
+
* @param {BoxProps & BaseProps} parentProps Parent node properties to inherit from.
|
|
46
46
|
*/
|
|
47
47
|
protected resolveInheritedStyles(parentProps: BoxProps & BaseProps): void;
|
|
48
48
|
/**
|
|
@@ -51,8 +51,8 @@ export declare class BoxNode {
|
|
|
51
51
|
protected applyDefaults(): void;
|
|
52
52
|
/**
|
|
53
53
|
* Appends a child node at the specified index.
|
|
54
|
-
* @param {BoxNode} child
|
|
55
|
-
* @param index
|
|
54
|
+
* @param {BoxNode} child Child node to append.
|
|
55
|
+
* @param index Index to insert child at
|
|
56
56
|
*/
|
|
57
57
|
protected appendChild(child: BoxNode, index: number): void;
|
|
58
58
|
/**
|
|
@@ -66,31 +66,30 @@ export declare class BoxNode {
|
|
|
66
66
|
protected updateLayoutBasedOnComputedSize(): void;
|
|
67
67
|
/**
|
|
68
68
|
* Applies layout properties to the Yoga node.
|
|
69
|
-
* @param props
|
|
69
|
+
* @param props Box properties containing layout values
|
|
70
70
|
*/
|
|
71
71
|
protected setLayout(props: BoxProps): void;
|
|
72
72
|
/**
|
|
73
73
|
* Renders the node and its children to the canvas.
|
|
74
|
-
* @param {CanvasRenderingContext2D} ctx
|
|
75
|
-
* @param {number} offsetX
|
|
76
|
-
* @param {number} offsetY
|
|
74
|
+
* @param {CanvasRenderingContext2D} ctx Canvas rendering context (from skia-canvas).
|
|
75
|
+
* @param {number} offsetX X offset for rendering.
|
|
76
|
+
* @param {number} offsetY Y offset for rendering.
|
|
77
77
|
*/
|
|
78
78
|
render(ctx: CanvasRenderingContext2D, offsetX?: number, offsetY?: number): void;
|
|
79
79
|
/**
|
|
80
80
|
* Renders the node's visual content including background fills, shadows, and borders.
|
|
81
81
|
* This is an internal method used by the render() pipeline.
|
|
82
|
-
*
|
|
83
|
-
* @param
|
|
84
|
-
* @param
|
|
85
|
-
* @param
|
|
86
|
-
* @param
|
|
87
|
-
* @param height - The height of the content area to render
|
|
82
|
+
* @param ctx The skia-canvas 2D rendering context to draw into
|
|
83
|
+
* @param x The absolute x-coordinate where drawing should begin
|
|
84
|
+
* @param y The absolute y-coordinate where drawing should begin
|
|
85
|
+
* @param width The width of the content area to render
|
|
86
|
+
* @param height The height of the content area to render
|
|
88
87
|
*/
|
|
89
88
|
protected _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number): void;
|
|
90
89
|
}
|
|
91
90
|
/**
|
|
92
91
|
* Creates a new BoxNode instance.
|
|
93
|
-
* @param {BoxProps} props
|
|
92
|
+
* @param {BoxProps} props Box properties and configuration.
|
|
94
93
|
* @returns {BoxNode} New BoxNode instance.
|
|
95
94
|
*/
|
|
96
95
|
export declare const Box: (props: BoxProps) => BoxNode;
|
|
@@ -103,7 +102,7 @@ export declare class ColumnNode extends BoxNode {
|
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Creates a new ColumnNode instance.
|
|
106
|
-
* @param {BoxProps} props
|
|
105
|
+
* @param {BoxProps} props Column properties and configuration.
|
|
107
106
|
* @returns {ColumnNode} New ColumnNode instance.
|
|
108
107
|
*/
|
|
109
108
|
export declare const Column: (props: BoxProps) => ColumnNode;
|
|
@@ -116,7 +115,7 @@ export declare class RowNode extends BoxNode {
|
|
|
116
115
|
}
|
|
117
116
|
/**
|
|
118
117
|
* Creates a new RowNode instance.
|
|
119
|
-
* @param {BoxProps} props
|
|
118
|
+
* @param {BoxProps} props Row properties and configuration.
|
|
120
119
|
* @returns {RowNode} New RowNode instance.
|
|
121
120
|
*/
|
|
122
121
|
export declare const Row: (props: BoxProps) => RowNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/layout.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,yBAAyB,CAAA;AAGlF,OAAa,EAAS,IAAI,EAAE,MAAM,4BAA4B,CAAA;AAE9D;;;;GAIG;AACH,qBAAa,OAAO;IAClB;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"layout.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/layout.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,yBAAyB,CAAA;AAGlF,OAAa,EAAS,IAAI,EAAE,MAAM,4BAA4B,CAAA;AAE9D;;;;GAIG;AACH,qBAAa,OAAO;IAClB;;OAEG;IACH,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IAE/B;;OAEG;IACH,IAAI,EAAE,IAAI,CAAA;IAEV;;OAEG;IACH,QAAQ,EAAE,OAAO,EAAE,CAAA;IAEnB;;OAEG;IACH,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAA;IAE3B;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ;;;OAGG;gBACS,KAAK,GAAE,QAAQ,GAAG,SAAc;IAqB5C;;OAEG;IACI,sBAAsB;IAW7B;;;OAGG;IACH,SAAS,CAAC,sBAAsB,CAAC,WAAW,EAAE,QAAQ,GAAG,SAAS;IAkClE;;OAEG;IACH,SAAS,CAAC,aAAa,IAAI,IAAI;IAI/B;;;;OAIG;IACH,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;IAanD;;;OAGG;IACI,cAAc,IAAI,OAAO;IAiBhC;;OAEG;IACH,SAAS,CAAC,+BAA+B;IAIzC;;;OAGG;IACH,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ;IAqInC;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,wBAAwB,EAAE,OAAO,GAAE,MAAU,EAAE,OAAO,GAAE,MAAU;IA+J9E;;;;;;;;OAQG;IACH,SAAS,CAAC,cAAc,CAAC,GAAG,EAAE,wBAAwB,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAoR5G;AAED;;;;GAIG;AACH,eAAO,MAAM,GAAG,GAAI,OAAO,QAAQ,KAAG,OAA6B,CAAA;AAEnE;;;GAGG;AACH,qBAAa,UAAW,SAAQ,OAAO;gBACzB,KAAK,GAAE,QAAQ,GAAG,SAAc;CAS7C;AAED;;;;GAIG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,QAAQ,KAAG,UAAmC,CAAA;AAE5E;;;GAGG;AACH,qBAAa,OAAQ,SAAQ,OAAO;gBACtB,KAAK,GAAE,QAAQ,GAAG,SAAc;CAS7C;AAED;;;;GAIG;AACH,eAAO,MAAM,GAAG,GAAI,OAAO,QAAQ,KAAG,OAA6B,CAAA"}
|