@meonode/canvas 1.0.0-beta.1

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.
Files changed (65) hide show
  1. package/CONTRIBUTING.md +75 -0
  2. package/LICENSE +21 -0
  3. package/Readme.md +382 -0
  4. package/dist/cjs/canvas/canvas.helper.d.ts +57 -0
  5. package/dist/cjs/canvas/canvas.helper.d.ts.map +1 -0
  6. package/dist/cjs/canvas/canvas.helper.js +239 -0
  7. package/dist/cjs/canvas/canvas.helper.js.map +1 -0
  8. package/dist/cjs/canvas/canvas.type.d.ts +657 -0
  9. package/dist/cjs/canvas/canvas.type.d.ts.map +1 -0
  10. package/dist/cjs/canvas/grid.canvas.util.d.ts +39 -0
  11. package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -0
  12. package/dist/cjs/canvas/grid.canvas.util.js +263 -0
  13. package/dist/cjs/canvas/grid.canvas.util.js.map +1 -0
  14. package/dist/cjs/canvas/image.canvas.util.d.ts +34 -0
  15. package/dist/cjs/canvas/image.canvas.util.d.ts.map +1 -0
  16. package/dist/cjs/canvas/image.canvas.util.js +310 -0
  17. package/dist/cjs/canvas/image.canvas.util.js.map +1 -0
  18. package/dist/cjs/canvas/layout.canvas.util.d.ts +123 -0
  19. package/dist/cjs/canvas/layout.canvas.util.d.ts.map +1 -0
  20. package/dist/cjs/canvas/layout.canvas.util.js +785 -0
  21. package/dist/cjs/canvas/layout.canvas.util.js.map +1 -0
  22. package/dist/cjs/canvas/root.canvas.util.d.ts +42 -0
  23. package/dist/cjs/canvas/root.canvas.util.d.ts.map +1 -0
  24. package/dist/cjs/canvas/root.canvas.util.js +140 -0
  25. package/dist/cjs/canvas/root.canvas.util.js.map +1 -0
  26. package/dist/cjs/canvas/text.canvas.util.d.ts +148 -0
  27. package/dist/cjs/canvas/text.canvas.util.d.ts.map +1 -0
  28. package/dist/cjs/canvas/text.canvas.util.js +1112 -0
  29. package/dist/cjs/canvas/text.canvas.util.js.map +1 -0
  30. package/dist/cjs/constant/common.const.d.ts +37 -0
  31. package/dist/cjs/constant/common.const.d.ts.map +1 -0
  32. package/dist/cjs/constant/common.const.js +51 -0
  33. package/dist/cjs/constant/common.const.js.map +1 -0
  34. package/dist/cjs/index.d.ts +7 -0
  35. package/dist/cjs/index.d.ts.map +1 -0
  36. package/dist/cjs/index.js +31 -0
  37. package/dist/cjs/index.js.map +1 -0
  38. package/dist/esm/canvas/canvas.helper.d.ts +57 -0
  39. package/dist/esm/canvas/canvas.helper.d.ts.map +1 -0
  40. package/dist/esm/canvas/canvas.helper.js +214 -0
  41. package/dist/esm/canvas/canvas.type.d.ts +657 -0
  42. package/dist/esm/canvas/canvas.type.d.ts.map +1 -0
  43. package/dist/esm/canvas/grid.canvas.util.d.ts +39 -0
  44. package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -0
  45. package/dist/esm/canvas/grid.canvas.util.js +259 -0
  46. package/dist/esm/canvas/image.canvas.util.d.ts +34 -0
  47. package/dist/esm/canvas/image.canvas.util.d.ts.map +1 -0
  48. package/dist/esm/canvas/image.canvas.util.js +306 -0
  49. package/dist/esm/canvas/layout.canvas.util.d.ts +123 -0
  50. package/dist/esm/canvas/layout.canvas.util.d.ts.map +1 -0
  51. package/dist/esm/canvas/layout.canvas.util.js +777 -0
  52. package/dist/esm/canvas/root.canvas.util.d.ts +42 -0
  53. package/dist/esm/canvas/root.canvas.util.d.ts.map +1 -0
  54. package/dist/esm/canvas/root.canvas.util.js +116 -0
  55. package/dist/esm/canvas/text.canvas.util.d.ts +148 -0
  56. package/dist/esm/canvas/text.canvas.util.d.ts.map +1 -0
  57. package/dist/esm/canvas/text.canvas.util.js +1108 -0
  58. package/dist/esm/constant/common.const.d.ts +37 -0
  59. package/dist/esm/constant/common.const.d.ts.map +1 -0
  60. package/dist/esm/constant/common.const.js +23 -0
  61. package/dist/esm/index.d.ts +7 -0
  62. package/dist/esm/index.d.ts.map +1 -0
  63. package/dist/esm/index.js +7 -0
  64. package/dist/meonode-canvas-1.0.0-beta.1.tgz +0 -0
  65. package/package.json +79 -0
@@ -0,0 +1,39 @@
1
+ import type { GridProps } from '../canvas/canvas.type.js';
2
+ import { BoxNode, RowNode } from '../canvas/layout.canvas.util.js';
3
+ /**
4
+ * Grid layout node that arranges children in a configurable number of columns or rows.
5
+ * Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.
6
+ * @extends RowNode
7
+ */
8
+ export declare class GridNode extends RowNode {
9
+ private readonly columns;
10
+ private readonly columnGapValue;
11
+ private readonly rowGapValue;
12
+ private readonly isVertical;
13
+ /**
14
+ * Creates a new grid layout node
15
+ * @param props - Grid configuration properties
16
+ */
17
+ constructor(props: GridProps);
18
+ /**
19
+ * Appends a child node to this grid.
20
+ * Overridden primarily for documentation/clarity, functionality is inherited.
21
+ * @param child - Child node to append
22
+ * @param index - Index at which to insert the child
23
+ */
24
+ protected appendChild(child: BoxNode, index: number): void;
25
+ /**
26
+ * Update layout calculations after the initial layout is computed.
27
+ * This method calculates the appropriate flex-basis for children based on the
28
+ * number of columns and gaps, respecting the container's padding,
29
+ * and applies the gaps using Yoga's built-in properties.
30
+ */
31
+ protected updateLayoutBasedOnComputedSize(): void;
32
+ }
33
+ /**
34
+ * Factory function to create a new GridNode instance.
35
+ * @param props - Grid configuration properties.
36
+ * @returns A new GridNode instance.
37
+ */
38
+ export declare const Grid: (props: GridProps) => GridNode;
39
+ //# sourceMappingURL=grid.canvas.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/grid.canvas.util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAGjE;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC;;;OAGG;gBACS,KAAK,EAAE,SAAS;IAsD5B;;;;;OAKG;cACgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM;IAI5D;;;;;OAKG;cACgB,+BAA+B;CAsMnD;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,SAAS,aAAwB,CAAA"}
@@ -0,0 +1,263 @@
1
+ 'use strict';
2
+
3
+ var layout_canvas_util = require('./layout.canvas.util.js');
4
+ var common_const = require('../constant/common.const.js');
5
+
6
+ /**
7
+ * Grid layout node that arranges children in a configurable number of columns or rows.
8
+ * Uses Yoga's flexbox capabilities with wrapping and gap properties to simulate a grid.
9
+ * @extends RowNode
10
+ */
11
+ class GridNode extends layout_canvas_util.RowNode {
12
+ columns;
13
+ columnGapValue;
14
+ rowGapValue;
15
+ isVertical; // True if the main axis is vertical (flexDirection: column or column-reverse)
16
+ /**
17
+ * Creates a new grid layout node
18
+ * @param props - Grid configuration properties
19
+ */
20
+ constructor(props) {
21
+ const columns = Math.max(1, props.columns || 1);
22
+ const direction = props.direction || 'row'; // Default to horizontal row
23
+ const isVertical = direction === 'column' || direction === 'column-reverse';
24
+ // Map direction string to Yoga FlexDirection
25
+ let flexDirection;
26
+ switch (direction) {
27
+ case 'row':
28
+ flexDirection = common_const.Style.FlexDirection.Row;
29
+ break;
30
+ case 'column':
31
+ flexDirection = common_const.Style.FlexDirection.Column;
32
+ break;
33
+ case 'row-reverse':
34
+ flexDirection = common_const.Style.FlexDirection.RowReverse;
35
+ break;
36
+ case 'column-reverse':
37
+ flexDirection = common_const.Style.FlexDirection.ColumnReverse;
38
+ break;
39
+ default:
40
+ console.warn(`[GridNode] Invalid direction "${direction}". Defaulting to "row".`);
41
+ flexDirection = common_const.Style.FlexDirection.Row;
42
+ }
43
+ // Determine the column and row gap values from props
44
+ let columnGap = 0;
45
+ let rowGap = 0;
46
+ if (typeof props.gap === 'number' || (typeof props.gap === 'string' && props.gap.trim() !== '')) {
47
+ // Single value applies to both row and column gaps
48
+ columnGap = props.gap;
49
+ rowGap = props.gap;
50
+ }
51
+ else if (props.gap && typeof props.gap === 'object') {
52
+ // Object format: prioritize a specific direction (Column/Row), then All
53
+ columnGap = props.gap.Column ?? props.gap.All ?? 0;
54
+ rowGap = props.gap.Row ?? props.gap.All ?? 0;
55
+ }
56
+ super({
57
+ name: 'Grid',
58
+ flexWrap: common_const.Style.Wrap.Wrap, // Essential for grid behavior
59
+ flexDirection,
60
+ ...props,
61
+ // Explicitly remove the 'direction' prop passed to super, as it's handled by flexDirection
62
+ direction: undefined,
63
+ });
64
+ this.columns = columns;
65
+ this.columnGapValue = columnGap;
66
+ this.rowGapValue = rowGap;
67
+ this.isVertical = isVertical;
68
+ }
69
+ /**
70
+ * Appends a child node to this grid.
71
+ * Overridden primarily for documentation/clarity, functionality is inherited.
72
+ * @param child - Child node to append
73
+ * @param index - Index at which to insert the child
74
+ */
75
+ appendChild(child, index) {
76
+ super.appendChild(child, index);
77
+ }
78
+ /**
79
+ * Update layout calculations after the initial layout is computed.
80
+ * This method calculates the appropriate flex-basis for children based on the
81
+ * number of columns and gaps, respecting the container's padding,
82
+ * and applies the gaps using Yoga's built-in properties.
83
+ */
84
+ updateLayoutBasedOnComputedSize() {
85
+ // Step 1: Early return if the grid is empty or invalid
86
+ if (this.columns <= 0 || this.children.length === 0) {
87
+ return;
88
+ }
89
+ // Step 2: Get container dimensions and padding after the initial layout
90
+ const width = this.node.getComputedWidth();
91
+ const height = this.node.getComputedHeight();
92
+ const paddingLeft = this.node.getComputedPadding(common_const.Style.Edge.Left);
93
+ const paddingRight = this.node.getComputedPadding(common_const.Style.Edge.Right);
94
+ const paddingTop = this.node.getComputedPadding(common_const.Style.Edge.Top);
95
+ const paddingBottom = this.node.getComputedPadding(common_const.Style.Edge.Bottom);
96
+ // Calculate content box dimensions
97
+ const contentWidth = Math.max(0, width - paddingLeft - paddingRight);
98
+ const contentHeight = Math.max(0, height - paddingTop - paddingBottom);
99
+ // Step 3: Validate dimensions needed for calculations
100
+ if (!this.isVertical && contentWidth <= 0 && width > 0) {
101
+ console.warn(`[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.`);
102
+ if (this.columns > 1)
103
+ return;
104
+ }
105
+ if (this.isVertical && contentHeight <= 0 && height > 0) {
106
+ console.warn(`[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.`);
107
+ if (this.columns > 1)
108
+ return;
109
+ }
110
+ // Step 4: Calculate Gap Values in Pixels
111
+ let columnGapPixels = 0;
112
+ if (typeof this.columnGapValue === 'number') {
113
+ columnGapPixels = this.columnGapValue;
114
+ }
115
+ else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim().endsWith('%')) {
116
+ try {
117
+ const percent = parseFloat(this.columnGapValue);
118
+ if (!isNaN(percent) && contentWidth > 0) {
119
+ columnGapPixels = (percent / 100) * contentWidth;
120
+ }
121
+ else if (isNaN(percent)) {
122
+ console.warn(`[GridNode ${this.props.key}] Invalid percentage column gap format: "${this.columnGapValue}". Using 0px.`);
123
+ }
124
+ else if (contentWidth <= 0) {
125
+ console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage column gap (${this.columnGapValue}) because content width is zero. Using 0px.`);
126
+ }
127
+ }
128
+ catch (e) {
129
+ console.warn(`[GridNode ${this.props.key}] Error parsing percentage column gap: "${this.columnGapValue}". Using 0px.`, e);
130
+ }
131
+ }
132
+ else if (typeof this.columnGapValue === 'string' && this.columnGapValue.trim() !== '') {
133
+ console.warn(`[GridNode ${this.props.key}] Unsupported string column gap format: "${this.columnGapValue}". Using 0px. Only numbers and percentages ('%') are supported.`);
134
+ }
135
+ let rowGapPixels = 0;
136
+ if (typeof this.rowGapValue === 'number') {
137
+ rowGapPixels = this.rowGapValue;
138
+ }
139
+ else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim().endsWith('%')) {
140
+ try {
141
+ const percent = parseFloat(this.rowGapValue);
142
+ if (!isNaN(percent) && contentHeight > 0) {
143
+ rowGapPixels = (percent / 100) * contentHeight;
144
+ }
145
+ else if (isNaN(percent)) {
146
+ console.warn(`[GridNode ${this.props.key}] Invalid percentage row gap format: "${this.rowGapValue}". Using 0px.`);
147
+ }
148
+ else if (contentHeight <= 0) {
149
+ console.warn(`[GridNode ${this.props.key}] Cannot calculate percentage row gap (${this.rowGapValue}) because content height is zero. Using 0px.`);
150
+ }
151
+ }
152
+ catch (e) {
153
+ console.warn(`[GridNode ${this.props.key}] Error parsing percentage row gap: "${this.rowGapValue}". Using 0px.`, e);
154
+ }
155
+ }
156
+ else if (typeof this.rowGapValue === 'string' && this.rowGapValue.trim() !== '') {
157
+ console.warn(`[GridNode ${this.props.key}] Unsupported string row gap format: "${this.rowGapValue}". Using 0px. Only numbers and percentages ('%') are supported.`);
158
+ }
159
+ // Ensure gaps are not negative
160
+ columnGapPixels = Math.max(0, columnGapPixels);
161
+ rowGapPixels = Math.max(0, rowGapPixels);
162
+ // Step 5: Calculate flex-basis percentage for children
163
+ const mainAxisGapPixels = this.isVertical ? rowGapPixels : columnGapPixels;
164
+ const mainAxisContentSize = this.isVertical ? contentHeight : contentWidth;
165
+ let childWidth = 0;
166
+ if (mainAxisContentSize > 0 && this.columns > 0) {
167
+ // Total space taken up by gaps on the main axis
168
+ const totalGapSpaceOnMainAxis = this.columns > 1 ? mainAxisGapPixels * (this.columns - 1) : 0;
169
+ // Calculate the space available *only* for the items themselves
170
+ const availableSpaceOnMainAxis = Math.max(0, mainAxisContentSize - totalGapSpaceOnMainAxis);
171
+ // Calculate the exact pixel of the total content size that each item should occupy
172
+ const exactItemWidth = availableSpaceOnMainAxis / this.columns;
173
+ // Ensure it's not negative (shouldn't happen, but safety)
174
+ childWidth = Math.max(0, exactItemWidth - 0.5); // Slightly reduce to avoid rounding issues
175
+ }
176
+ else if (this.columns === 1) {
177
+ // If only one column, it takes up the full basis (gaps don't apply)
178
+ childWidth = mainAxisContentSize;
179
+ }
180
+ // Clamp basis percentage between 0 and 100 (mostly redundant after floor/max(0) but safe)
181
+ childWidth = Math.max(0, Math.min(mainAxisContentSize, childWidth));
182
+ // Step 6: Apply layout properties to children
183
+ let childrenNeedRecalculation = false;
184
+ for (const child of this.children) {
185
+ let childChanged = false;
186
+ const currentLayoutWidth = child.node.getWidth();
187
+ const currentWidthValue = currentLayoutWidth.value;
188
+ const currentWidthUnit = currentLayoutWidth.unit;
189
+ let widthNeedsUpdate = false;
190
+ if (currentWidthUnit === common_const.Style.Unit.Point) {
191
+ // If current width is in points, check if the value is significantly different
192
+ if (Math.abs(currentWidthValue - childWidth) > 0.01) {
193
+ widthNeedsUpdate = true;
194
+ }
195
+ }
196
+ else {
197
+ // If current width is not in points (e.g., Auto, Percent, Undefined), it needs to be set to points
198
+ widthNeedsUpdate = true;
199
+ }
200
+ if (widthNeedsUpdate) {
201
+ child.node.setWidth(childWidth);
202
+ childChanged = true;
203
+ }
204
+ // Ensure grow/shrink are set correctly for grid items
205
+ if (child.node.getFlexGrow() !== 0) {
206
+ child.node.setFlexGrow(0);
207
+ childChanged = true;
208
+ }
209
+ if (child.node.getFlexShrink() !== 1) {
210
+ child.node.setFlexShrink(1); // Allow shrinking
211
+ childChanged = true;
212
+ }
213
+ // Remove margins that might interfere with gap property
214
+ if (child.node.getMargin(common_const.Style.Edge.Bottom).unit !== common_const.Style.Unit.Undefined) {
215
+ child.node.setMargin(common_const.Style.Edge.Bottom, undefined);
216
+ childChanged = true;
217
+ }
218
+ if (child.node.getMargin(common_const.Style.Edge.Right).unit !== common_const.Style.Unit.Undefined) {
219
+ child.node.setMargin(common_const.Style.Edge.Right, undefined);
220
+ childChanged = true;
221
+ }
222
+ if (child.node.getMargin(common_const.Style.Edge.Top).unit !== common_const.Style.Unit.Undefined) {
223
+ child.node.setMargin(common_const.Style.Edge.Top, undefined);
224
+ childChanged = true;
225
+ }
226
+ if (child.node.getMargin(common_const.Style.Edge.Left).unit !== common_const.Style.Unit.Undefined) {
227
+ child.node.setMargin(common_const.Style.Edge.Left, undefined);
228
+ childChanged = true;
229
+ }
230
+ if (childChanged && !child.node.isDirty()) {
231
+ child.node.markDirty();
232
+ childrenNeedRecalculation = true;
233
+ }
234
+ }
235
+ // Step 7: Apply gaps using Yoga's built-in gap properties
236
+ const currentColumnGap = this.node.getGap(common_const.Style.Gutter.Column).value;
237
+ const currentRowGap = this.node.getGap(common_const.Style.Gutter.Row).value;
238
+ let gapsChanged = false;
239
+ // Use a small tolerance for comparing gap pixels
240
+ if (Math.abs(currentColumnGap - columnGapPixels) > 0.001) {
241
+ this.node.setGap(common_const.Style.Gutter.Column, columnGapPixels);
242
+ gapsChanged = true;
243
+ }
244
+ if (Math.abs(currentRowGap - rowGapPixels) > 0.001) {
245
+ this.node.setGap(common_const.Style.Gutter.Row, rowGapPixels);
246
+ gapsChanged = true;
247
+ }
248
+ // Step 8: Mark the grid node itself as dirty if gaps changed or children changed
249
+ if ((gapsChanged || childrenNeedRecalculation) && !this.node.isDirty()) {
250
+ this.node.markDirty();
251
+ }
252
+ }
253
+ }
254
+ /**
255
+ * Factory function to create a new GridNode instance.
256
+ * @param props - Grid configuration properties.
257
+ * @returns A new GridNode instance.
258
+ */
259
+ const Grid = (props) => new GridNode(props);
260
+
261
+ exports.Grid = Grid;
262
+ exports.GridNode = GridNode;
263
+ //# sourceMappingURL=grid.canvas.util.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,34 @@
1
+ import type { BaseProps, ImageProps } from '../canvas/canvas.type.js';
2
+ import { type CanvasRenderingContext2D } from 'skia-canvas';
3
+ import { BoxNode } from '../canvas/layout.canvas.util.js';
4
+ /**
5
+ * Renders images with configurable sizing, positioning, and effects.
6
+ * Supports object-fit modes, positioning, border radius, and saturation filters.
7
+ */
8
+ export declare class ImageNode extends BoxNode {
9
+ props: ImageProps & BaseProps;
10
+ private loadedImage;
11
+ private naturalWidth;
12
+ private naturalHeight;
13
+ private readonly loadingPromise;
14
+ constructor(props: ImageProps);
15
+ /**
16
+ * Loads and processes an image from various sources (URL, file path, or Buffer).
17
+ * Handles SVG color modifications and sets natural dimensions with an aspect ratio.
18
+ *
19
+ * @returns Promise that resolves when image loading completes
20
+ * @throws Error if image loading fails
21
+ */
22
+ private _loadImage;
23
+ getLoadingPromise(): Promise<void>;
24
+ /**
25
+ * Renders the image with correct sizing, clipping, and positioning.
26
+ * Handles object-fit, object-position, and visual effects like saturation.
27
+ */
28
+ protected _renderContent(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number): void;
29
+ }
30
+ /**
31
+ * Factory function to create ImageNode instances
32
+ */
33
+ export declare const Image: (props: ImageProps) => ImageNode;
34
+ //# sourceMappingURL=image.canvas.util.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.canvas.util.d.ts","sourceRoot":"","sources":["../../../src/canvas/image.canvas.util.ts"],"names":[],"mappings":"AAAA,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;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAoHX,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzC;;;OAGG;cACgB,cAAc,CAC/B,GAAG,EAAE,wBAAwB,EAC7B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAuJjB;AAED;;GAEG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,UAAU,cAAyB,CAAA"}