@blinkorb/rcx 0.0.0 → 0.0.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 (201) hide show
  1. package/components/canvas/context.d.ts +11 -0
  2. package/components/canvas/context.js +4 -0
  3. package/components/canvas/context.js.map +1 -0
  4. package/components/canvas/index.d.ts +7 -0
  5. package/components/canvas/index.js +62 -0
  6. package/components/canvas/index.js.map +1 -0
  7. package/components/index.js +6 -0
  8. package/components/index.js.map +1 -0
  9. package/components/paths/arc-to.d.ts +12 -0
  10. package/components/paths/arc-to.js +24 -0
  11. package/components/paths/arc-to.js.map +1 -0
  12. package/components/paths/clip.d.ts +6 -0
  13. package/components/paths/clip.js +19 -0
  14. package/components/paths/clip.js.map +1 -0
  15. package/components/paths/index.js +6 -0
  16. package/components/paths/index.js.map +1 -0
  17. package/components/paths/line.d.ts +11 -0
  18. package/components/paths/line.js +25 -0
  19. package/components/paths/line.js.map +1 -0
  20. package/components/paths/path.d.ts +8 -0
  21. package/components/paths/path.js +33 -0
  22. package/components/paths/path.js.map +1 -0
  23. package/components/paths/point.d.ts +7 -0
  24. package/components/paths/point.js +15 -0
  25. package/components/paths/point.js.map +1 -0
  26. package/components/shapes/circle.d.ts +14 -0
  27. package/components/shapes/circle.js +8 -0
  28. package/components/shapes/circle.js.map +1 -0
  29. package/components/shapes/ellipse.d.ts +15 -0
  30. package/components/shapes/ellipse.js +24 -0
  31. package/components/shapes/ellipse.js.map +1 -0
  32. package/components/shapes/index.js +4 -0
  33. package/components/shapes/index.js.map +1 -0
  34. package/components/shapes/rectangle.d.ts +10 -0
  35. package/components/shapes/rectangle.js +20 -0
  36. package/components/shapes/rectangle.js.map +1 -0
  37. package/components/text/index.js +2 -0
  38. package/components/text/index.js.map +1 -0
  39. package/components/text/text.d.ts +13 -0
  40. package/components/text/text.js +78 -0
  41. package/components/text/text.js.map +1 -0
  42. package/components/transform/index.js +4 -0
  43. package/components/transform/index.js.map +1 -0
  44. package/components/transform/rotate.d.ts +5 -0
  45. package/components/transform/rotate.js +14 -0
  46. package/components/transform/rotate.js.map +1 -0
  47. package/components/transform/scale.d.ts +11 -0
  48. package/components/transform/scale.js +14 -0
  49. package/components/transform/scale.js.map +1 -0
  50. package/components/transform/translate.d.ts +6 -0
  51. package/components/transform/translate.js +14 -0
  52. package/components/transform/translate.js.map +1 -0
  53. package/context/create-context.d.ts +9 -0
  54. package/context/create-context.js +29 -0
  55. package/context/create-context.js.map +1 -0
  56. package/context/index.js +2 -0
  57. package/context/index.js.map +1 -0
  58. package/hooks/index.js +9 -0
  59. package/hooks/index.js.map +1 -0
  60. package/hooks/use-canvas-context.d.ts +1 -0
  61. package/hooks/use-canvas-context.js +9 -0
  62. package/hooks/use-canvas-context.js.map +1 -0
  63. package/hooks/use-linear-gradient.d.ts +9 -0
  64. package/hooks/use-linear-gradient.js +13 -0
  65. package/hooks/use-linear-gradient.js.map +1 -0
  66. package/hooks/use-loop.d.ts +1 -0
  67. package/hooks/use-loop.js +9 -0
  68. package/hooks/use-loop.js.map +1 -0
  69. package/hooks/use-on.d.ts +2 -0
  70. package/hooks/use-on.js +16 -0
  71. package/hooks/use-on.js.map +1 -0
  72. package/hooks/use-radial-gradient.d.ts +11 -0
  73. package/hooks/use-radial-gradient.js +13 -0
  74. package/hooks/use-radial-gradient.js.map +1 -0
  75. package/hooks/use-render.d.ts +3 -0
  76. package/hooks/use-render.js +8 -0
  77. package/hooks/use-render.js.map +1 -0
  78. package/hooks/use-state.d.ts +3 -0
  79. package/hooks/use-state.js +5 -0
  80. package/hooks/use-state.js.map +1 -0
  81. package/hooks/use-window-size.d.ts +4 -0
  82. package/hooks/use-window-size.js +20 -0
  83. package/hooks/use-window-size.js.map +1 -0
  84. package/index.js +7 -0
  85. package/index.js.map +1 -0
  86. package/internal/emitter.d.ts +15 -0
  87. package/internal/emitter.js +19 -0
  88. package/internal/emitter.js.map +1 -0
  89. package/internal/global.d.ts +2 -0
  90. package/internal/global.js +4 -0
  91. package/internal/global.js.map +1 -0
  92. package/internal/hooks.d.ts +2 -0
  93. package/internal/hooks.js +17 -0
  94. package/internal/hooks.js.map +1 -0
  95. package/internal/reactive.d.ts +2 -0
  96. package/internal/reactive.js +16 -0
  97. package/internal/reactive.js.map +1 -0
  98. package/jsx-runtime.d.ts +4 -0
  99. package/jsx-runtime.js +8 -0
  100. package/jsx-runtime.js.map +1 -0
  101. package/package.json +11 -23
  102. package/render.d.ts +4 -0
  103. package/render.js +198 -0
  104. package/render.js.map +1 -0
  105. package/types.d.ts +108 -0
  106. package/types.js +1 -0
  107. package/types.js.map +1 -0
  108. package/utils/apply-fill-and-stroke-style.d.ts +2 -0
  109. package/utils/apply-fill-and-stroke-style.js +24 -0
  110. package/utils/apply-fill-and-stroke-style.js.map +1 -0
  111. package/utils/get-recommended-pixel-ratio.d.ts +1 -0
  112. package/utils/get-recommended-pixel-ratio.js +2 -0
  113. package/utils/get-recommended-pixel-ratio.js.map +1 -0
  114. package/utils/index.js +9 -0
  115. package/utils/index.js.map +1 -0
  116. package/utils/is-own-property-of.d.ts +2 -0
  117. package/utils/is-own-property-of.js +2 -0
  118. package/utils/is-own-property-of.js.map +1 -0
  119. package/utils/is-valid-fill-or-stroke-style.d.ts +1 -0
  120. package/utils/is-valid-fill-or-stroke-style.js +3 -0
  121. package/utils/is-valid-fill-or-stroke-style.js.map +1 -0
  122. package/utils/is-valid-stroke-cap.d.ts +1 -0
  123. package/utils/is-valid-stroke-cap.js +8 -0
  124. package/utils/is-valid-stroke-cap.js.map +1 -0
  125. package/utils/is-valid-stroke-join.d.ts +1 -0
  126. package/utils/is-valid-stroke-join.js +8 -0
  127. package/utils/is-valid-stroke-join.js.map +1 -0
  128. package/utils/resolve-styles.d.ts +2 -0
  129. package/utils/resolve-styles.js +16 -0
  130. package/utils/resolve-styles.js.map +1 -0
  131. package/utils/type-guards.d.ts +2 -0
  132. package/utils/type-guards.js +2 -0
  133. package/utils/type-guards.js.map +1 -0
  134. package/utils/with-px.d.ts +1 -0
  135. package/utils/with-px.js +2 -0
  136. package/utils/with-px.js.map +1 -0
  137. package/.eslintignore +0 -4
  138. package/.eslintrc.json +0 -286
  139. package/.gitattributes +0 -2
  140. package/.github/CODEOWNERS +0 -1
  141. package/.github/workflows/ci.yml +0 -19
  142. package/.nvmrc +0 -1
  143. package/.prettierignore +0 -28
  144. package/.prettierrc.json +0 -4
  145. package/demo/index.html +0 -29
  146. package/demo/index.tsx +0 -316
  147. package/demo/tsconfig.json +0 -12
  148. package/jest.config.ts +0 -21
  149. package/scripts/prep-package.js +0 -29
  150. package/src/components/canvas/context.ts +0 -6
  151. package/src/components/canvas/index.ts +0 -98
  152. package/src/components/paths/arc-to.ts +0 -66
  153. package/src/components/paths/clip.ts +0 -32
  154. package/src/components/paths/line.ts +0 -53
  155. package/src/components/paths/path.ts +0 -59
  156. package/src/components/paths/point.ts +0 -24
  157. package/src/components/shapes/circle.tsx +0 -32
  158. package/src/components/shapes/ellipse.ts +0 -75
  159. package/src/components/shapes/rectangle.ts +0 -45
  160. package/src/components/text/text.ts +0 -137
  161. package/src/components/transform/rotate.ts +0 -26
  162. package/src/components/transform/scale.ts +0 -34
  163. package/src/components/transform/translate.ts +0 -27
  164. package/src/context/create-context.ts +0 -49
  165. package/src/hooks/use-canvas-context.ts +0 -11
  166. package/src/hooks/use-linear-gradient.ts +0 -39
  167. package/src/hooks/use-loop.ts +0 -11
  168. package/src/hooks/use-on.ts +0 -18
  169. package/src/hooks/use-radial-gradient.ts +0 -45
  170. package/src/hooks/use-render.ts +0 -14
  171. package/src/hooks/use-state.ts +0 -9
  172. package/src/hooks/use-window-size.ts +0 -24
  173. package/src/internal/emitter.ts +0 -39
  174. package/src/internal/global.ts +0 -5
  175. package/src/internal/hooks.ts +0 -32
  176. package/src/internal/reactive.test.ts +0 -20
  177. package/src/internal/reactive.ts +0 -20
  178. package/src/jsx-runtime.ts +0 -21
  179. package/src/render.ts +0 -299
  180. package/src/types.ts +0 -151
  181. package/src/utils/apply-fill-and-stroke-style.ts +0 -33
  182. package/src/utils/get-recommended-pixel-ratio.ts +0 -2
  183. package/src/utils/is-own-property-of.ts +0 -6
  184. package/src/utils/is-valid-fill-or-stroke-style.ts +0 -5
  185. package/src/utils/is-valid-stroke-cap.ts +0 -10
  186. package/src/utils/is-valid-stroke-join.ts +0 -10
  187. package/src/utils/resolve-styles.ts +0 -21
  188. package/src/utils/type-guards.ts +0 -4
  189. package/src/utils/with-px.ts +0 -4
  190. package/tsb.config.ts +0 -11
  191. package/tsconfig.dist.json +0 -13
  192. package/tsconfig.json +0 -25
  193. /package/{src/components/index.ts → components/index.d.ts} +0 -0
  194. /package/{src/components/paths/index.ts → components/paths/index.d.ts} +0 -0
  195. /package/{src/components/shapes/index.ts → components/shapes/index.d.ts} +0 -0
  196. /package/{src/components/text/index.ts → components/text/index.d.ts} +0 -0
  197. /package/{src/components/transform/index.ts → components/transform/index.d.ts} +0 -0
  198. /package/{src/context/index.ts → context/index.d.ts} +0 -0
  199. /package/{src/hooks/index.ts → hooks/index.d.ts} +0 -0
  200. /package/{src/index.ts → index.d.ts} +0 -0
  201. /package/{src/utils/index.ts → utils/index.d.ts} +0 -0
package/render.js ADDED
@@ -0,0 +1,198 @@
1
+ import { renderingContext } from "./components/canvas/context.js";
2
+ import { emitter } from "./internal/emitter.js";
3
+ import { cxGlobal } from "./internal/global.js";
4
+ import { isArray } from "./utils/type-guards.js";
5
+ const getCanvasElement = (container) => {
6
+ if (container instanceof HTMLCanvasElement) {
7
+ return container;
8
+ }
9
+ const canvasElement = document.createElement('canvas');
10
+ container.appendChild(canvasElement);
11
+ return canvasElement;
12
+ };
13
+ const unmountNodes = (children) => {
14
+ if (!!children && typeof children === 'object') {
15
+ if (isArray(children)) {
16
+ children.forEach((child) => unmountNodes(child));
17
+ }
18
+ else {
19
+ children.hooks.forEach((hook) => {
20
+ if (hook.type === 'useOnMount') {
21
+ hook.value.onUnmount?.();
22
+ }
23
+ if (hook.type === 'useOnUnmount') {
24
+ hook.value();
25
+ }
26
+ });
27
+ unmountNodes(children.childNodes);
28
+ }
29
+ }
30
+ };
31
+ const updateNode = (element, prevNode) => {
32
+ if (element.type === prevNode?.element.type) {
33
+ const nextPropsCopy = { ...element.props };
34
+ // Delete previous props
35
+ Object.keys(prevNode.element.props).forEach((key) => {
36
+ delete prevNode.element.props[key];
37
+ });
38
+ // Copy in new props
39
+ Object.entries(nextPropsCopy).forEach(([key, value]) => {
40
+ prevNode.element.props[key] = value;
41
+ });
42
+ return prevNode;
43
+ }
44
+ unmountNodes(prevNode);
45
+ return {
46
+ element,
47
+ hooks: [],
48
+ rendered: [],
49
+ childNodes: [],
50
+ context: {},
51
+ };
52
+ };
53
+ const getMatchingChildPrev = (nextChild, nextChildIndex, stillRendered) => {
54
+ if (!!nextChild && typeof nextChild === 'object' && !isArray(nextChild)) {
55
+ if (isArray(stillRendered)) {
56
+ if (typeof nextChild.props.$key !== 'undefined') {
57
+ return stillRendered.find((prev) => !!prev &&
58
+ typeof prev === 'object' &&
59
+ !isArray(prev) &&
60
+ prev.element.type === nextChild.type &&
61
+ prev.element.props.$key === nextChild.props.$key);
62
+ }
63
+ const atIndex = stillRendered[nextChildIndex];
64
+ if (!!atIndex &&
65
+ typeof atIndex === 'object' &&
66
+ !isArray(atIndex) &&
67
+ atIndex.element.type === nextChild.type &&
68
+ typeof atIndex.element.props.$key === 'undefined') {
69
+ return atIndex;
70
+ }
71
+ }
72
+ }
73
+ };
74
+ const getMatchingChildNext = (prevChild, prevChildIndex, nextRendered) => {
75
+ if (!!prevChild && typeof prevChild === 'object' && !isArray(prevChild)) {
76
+ if (isArray(nextRendered)) {
77
+ if (typeof prevChild.element.props.$key !== 'undefined') {
78
+ return nextRendered.find((next) => !!next &&
79
+ typeof next === 'object' &&
80
+ !isArray(next) &&
81
+ next.type === prevChild.element.type &&
82
+ next.props.$key === prevChild.element.props.$key);
83
+ }
84
+ const atIndex = nextRendered[prevChildIndex];
85
+ if (!!atIndex &&
86
+ typeof atIndex === 'object' &&
87
+ !isArray(atIndex) &&
88
+ atIndex.type === prevChild.element.type &&
89
+ typeof atIndex.props.$key === 'undefined') {
90
+ return atIndex;
91
+ }
92
+ }
93
+ }
94
+ };
95
+ const renderElement = (element, renderingContextState, prevNode, parentContext) => {
96
+ const node = updateNode(element, prevNode);
97
+ node.context = {
98
+ ...parentContext,
99
+ };
100
+ cxGlobal.currentNode = node;
101
+ cxGlobal.hookIndex = 0;
102
+ renderingContext.useProvide(renderingContextState);
103
+ node.rendered = element.type(element.props);
104
+ delete cxGlobal.currentNode;
105
+ const traverse = (nextRendered, prevRendered) => {
106
+ if (!!nextRendered && typeof nextRendered === 'object') {
107
+ if (isArray(nextRendered)) {
108
+ let stillRendered;
109
+ if (!isArray(prevRendered)) {
110
+ unmountNodes(prevRendered);
111
+ }
112
+ else {
113
+ stillRendered = prevRendered.filter((prevChild, prevChildIndex) => {
114
+ const match = getMatchingChildNext(prevChild, prevChildIndex, nextRendered);
115
+ if (!match) {
116
+ unmountNodes(prevChild);
117
+ }
118
+ return !!match;
119
+ });
120
+ }
121
+ return nextRendered.map((nextChild, nextChildIndex) => traverse(nextChild, getMatchingChildPrev(nextChild, nextChildIndex, stillRendered)));
122
+ }
123
+ if (!!prevRendered && typeof prevRendered === 'object') {
124
+ if (isArray(prevRendered)) {
125
+ unmountNodes(prevRendered);
126
+ }
127
+ else if (prevRendered.element.type !== nextRendered.type) {
128
+ unmountNodes(prevRendered);
129
+ }
130
+ }
131
+ return renderElement(nextRendered, renderingContextState, !!prevRendered &&
132
+ typeof prevRendered === 'object' &&
133
+ !isArray(prevRendered)
134
+ ? prevRendered
135
+ : undefined, node.context);
136
+ }
137
+ unmountNodes(prevRendered);
138
+ return [];
139
+ };
140
+ node.hooks.forEach((hook) => {
141
+ if (hook.type === 'useOnMount' && element.type !== prevNode?.element.type) {
142
+ hook.value.onMount();
143
+ }
144
+ });
145
+ node.hooks.forEach((hook) => {
146
+ if (hook.type === 'useRenderBeforeChildren') {
147
+ hook.value(renderingContextState);
148
+ }
149
+ });
150
+ node.childNodes = traverse(node.rendered, prevNode?.childNodes);
151
+ node.hooks.forEach((hook) => {
152
+ if (hook.type === 'useRenderAfterChildren') {
153
+ hook.value(renderingContextState);
154
+ }
155
+ });
156
+ return node;
157
+ };
158
+ export const render = (element, container) => {
159
+ const canvas = getCanvasElement(container);
160
+ const ctx2d = canvas.getContext('2d');
161
+ if (!ctx2d) {
162
+ const errorMessage = 'CanvasRenderingContext2D not supported';
163
+ if (window.console && typeof window.console.error === 'function') {
164
+ // eslint-disable-next-line no-console
165
+ console.error(errorMessage);
166
+ }
167
+ return {
168
+ error: errorMessage,
169
+ };
170
+ }
171
+ const renderingContextState = { canvas, ctx2d };
172
+ let raf;
173
+ let rootNode;
174
+ const renderRoot = () => {
175
+ if (typeof raf === 'number') {
176
+ window.cancelAnimationFrame(raf);
177
+ }
178
+ raf = window.requestAnimationFrame(() => {
179
+ // eslint-disable-next-line no-self-assign
180
+ canvas.width = canvas.width;
181
+ rootNode = renderElement(element, renderingContextState, rootNode);
182
+ });
183
+ };
184
+ renderRoot();
185
+ emitter.on('render', renderRoot);
186
+ const unmount = () => {
187
+ if (typeof raf === 'number') {
188
+ window.cancelAnimationFrame(raf);
189
+ }
190
+ // eslint-disable-next-line no-self-assign
191
+ canvas.width = canvas.width;
192
+ if (!(container instanceof HTMLCanvasElement)) {
193
+ container.removeChild(canvas);
194
+ }
195
+ };
196
+ return unmount;
197
+ };
198
+ //# sourceMappingURL=render.js.map
package/render.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAUhD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEjD,MAAM,gBAAgB,GAAG,CAAC,SAAsB,EAAE,EAAE;IAClD,IAAI,SAAS,YAAY,iBAAiB,EAAE,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACvD,SAAS,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IAErC,OAAO,aAAa,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CACnB,QAA0D,EAC1D,EAAE;IACF,IAAI,CAAC,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/C,IAAI,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtB,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;gBAC3B,CAAC;gBAED,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;oBACjC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CACjB,OAAsB,EACtB,QAAgC,EACpB,EAAE;IACd,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;QAE3C,wBAAwB;QACxB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAClD,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YACrD,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEvB,OAAO;QACL,OAAO;QACP,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,SAAsB,EACtB,cAAsB,EACtB,aAAkD,EAClD,EAAE;IACF,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACxE,IAAI,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC3B,IAAI,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAChD,OAAO,aAAa,CAAC,IAAI,CACvB,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,CAAC,IAAI;oBACN,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,OAAO,CAAC,IAAI,CAAC;oBACd,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;oBACpC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,KAAK,CAAC,IAAI,CACnD,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;YAE9C,IACE,CAAC,CAAC,OAAO;gBACT,OAAO,OAAO,KAAK,QAAQ;gBAC3B,CAAC,OAAO,CAAC,OAAO,CAAC;gBACjB,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,IAAI;gBACvC,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EACjD,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,SAAkC,EAClC,cAAsB,EACtB,YAAmC,EACnC,EAAE;IACF,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACxE,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1B,IAAI,OAAO,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACxD,OAAO,YAAY,CAAC,IAAI,CACtB,CAAC,IAAI,EAAE,EAAE,CACP,CAAC,CAAC,IAAI;oBACN,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,OAAO,CAAC,IAAI,CAAC;oBACd,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,IAAI;oBACpC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CACnD,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,GAAG,YAAY,CAAC,cAAc,CAAC,CAAC;YAE7C,IACE,CAAC,CAAC,OAAO;gBACT,OAAO,OAAO,KAAK,QAAQ;gBAC3B,CAAC,OAAO,CAAC,OAAO,CAAC;gBACjB,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,OAAO,CAAC,IAAI;gBACvC,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,EACzC,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CACpB,OAAsB,EACtB,qBAA0C,EAC1C,QAAgC,EAChC,aAAyB,EACb,EAAE;IACd,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAE3C,IAAI,CAAC,OAAO,GAAG;QACb,GAAG,aAAa;KACjB,CAAC;IAEF,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,SAAS,GAAG,CAAC,CAAC;IAEvB,gBAAgB,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAEnD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE5C,OAAO,QAAQ,CAAC,WAAW,CAAC;IAE5B,MAAM,QAAQ,GAAG,CACf,YAAyB,EACzB,YAAiD,EACxB,EAAE;QAC3B,IAAI,CAAC,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACvD,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC1B,IAAI,aAAkD,CAAC;gBAEvD,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC3B,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC7B,CAAC;qBAAM,CAAC;oBACN,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE;wBAChE,MAAM,KAAK,GAAG,oBAAoB,CAChC,SAAS,EACT,cAAc,EACd,YAAY,CACb,CAAC;wBAEF,IAAI,CAAC,KAAK,EAAE,CAAC;4BACX,YAAY,CAAC,SAAS,CAAC,CAAC;wBAC1B,CAAC;wBAED,OAAO,CAAC,CAAC,KAAK,CAAC;oBACjB,CAAC,CAAC,CAAC;gBACL,CAAC;gBAED,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,CACpD,QAAQ,CACN,SAAS,EACT,oBAAoB,CAAC,SAAS,EAAE,cAAc,EAAE,aAAa,CAAC,CAC/D,CACF,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;gBACvD,IAAI,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC1B,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC7B,CAAC;qBAAM,IAAI,YAAY,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,EAAE,CAAC;oBAC3D,YAAY,CAAC,YAAY,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YAED,OAAO,aAAa,CAClB,YAAY,EACZ,qBAAqB,EACrB,CAAC,CAAC,YAAY;gBACZ,OAAO,YAAY,KAAK,QAAQ;gBAChC,CAAC,OAAO,CAAC,YAAY,CAAC;gBACtB,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,SAAS,EACb,IAAI,CAAC,OAAO,CACb,CAAC;QACJ,CAAC;QAED,YAAY,CAAC,YAAY,CAAC,CAAC;QAE3B,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;YAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,yBAAyB,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEhE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,OAAsB,EAAE,SAAsB,EAAE,EAAE;IACvE,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,YAAY,GAAG,wCAAwC,CAAC;QAE9D,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YACjE,sCAAsC;YACtC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;SACpB,CAAC;IACJ,CAAC;IAED,MAAM,qBAAqB,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAEhD,IAAI,GAAuB,CAAC;IAC5B,IAAI,QAAgC,CAAC;IAErC,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,GAAG,GAAG,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE;YACtC,0CAA0C;YAC1C,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;YAC5B,QAAQ,GAAG,aAAa,CAAC,OAAO,EAAE,qBAAqB,EAAE,QAAQ,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,UAAU,EAAE,CAAC;IAEb,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEjC,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QACD,0CAA0C;QAC1C,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAE5B,IAAI,CAAC,CAAC,SAAS,YAAY,iBAAiB,CAAC,EAAE,CAAC;YAC9C,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import { renderingContext } from './components/canvas/context.ts';\nimport { emitter } from './internal/emitter.ts';\nimport { cxGlobal } from './internal/global.ts';\nimport type {\n AnyObject,\n NestedArray,\n RCXChild,\n RCXChildren,\n RCXElementAny,\n RCXNodeAny,\n RCXRenderingContext,\n} from './types.ts';\nimport { isArray } from './utils/type-guards.ts';\n\nconst getCanvasElement = (container: HTMLElement) => {\n if (container instanceof HTMLCanvasElement) {\n return container;\n }\n\n const canvasElement = document.createElement('canvas');\n container.appendChild(canvasElement);\n\n return canvasElement;\n};\n\nconst unmountNodes = (\n children: NestedArray<RCXNodeAny> | RCXNodeAny | undefined\n) => {\n if (!!children && typeof children === 'object') {\n if (isArray(children)) {\n children.forEach((child) => unmountNodes(child));\n } else {\n children.hooks.forEach((hook) => {\n if (hook.type === 'useOnMount') {\n hook.value.onUnmount?.();\n }\n\n if (hook.type === 'useOnUnmount') {\n hook.value();\n }\n });\n\n unmountNodes(children.childNodes);\n }\n }\n};\n\nconst updateNode = (\n element: RCXElementAny,\n prevNode: RCXNodeAny | undefined\n): RCXNodeAny => {\n if (element.type === prevNode?.element.type) {\n const nextPropsCopy = { ...element.props };\n\n // Delete previous props\n Object.keys(prevNode.element.props).forEach((key) => {\n delete prevNode.element.props[key];\n });\n\n // Copy in new props\n Object.entries(nextPropsCopy).forEach(([key, value]) => {\n prevNode.element.props[key] = value;\n });\n\n return prevNode;\n }\n\n unmountNodes(prevNode);\n\n return {\n element,\n hooks: [],\n rendered: [],\n childNodes: [],\n context: {},\n };\n};\n\nconst getMatchingChildPrev = (\n nextChild: RCXChildren,\n nextChildIndex: number,\n stillRendered: NestedArray<RCXNodeAny> | undefined\n) => {\n if (!!nextChild && typeof nextChild === 'object' && !isArray(nextChild)) {\n if (isArray(stillRendered)) {\n if (typeof nextChild.props.$key !== 'undefined') {\n return stillRendered.find(\n (prev) =>\n !!prev &&\n typeof prev === 'object' &&\n !isArray(prev) &&\n prev.element.type === nextChild.type &&\n prev.element.props.$key === nextChild.props.$key\n );\n }\n\n const atIndex = stillRendered[nextChildIndex];\n\n if (\n !!atIndex &&\n typeof atIndex === 'object' &&\n !isArray(atIndex) &&\n atIndex.element.type === nextChild.type &&\n typeof atIndex.element.props.$key === 'undefined'\n ) {\n return atIndex;\n }\n }\n }\n};\n\nconst getMatchingChildNext = (\n prevChild: NestedArray<RCXNodeAny>,\n prevChildIndex: number,\n nextRendered: NestedArray<RCXChild>\n) => {\n if (!!prevChild && typeof prevChild === 'object' && !isArray(prevChild)) {\n if (isArray(nextRendered)) {\n if (typeof prevChild.element.props.$key !== 'undefined') {\n return nextRendered.find(\n (next) =>\n !!next &&\n typeof next === 'object' &&\n !isArray(next) &&\n next.type === prevChild.element.type &&\n next.props.$key === prevChild.element.props.$key\n );\n }\n\n const atIndex = nextRendered[prevChildIndex];\n\n if (\n !!atIndex &&\n typeof atIndex === 'object' &&\n !isArray(atIndex) &&\n atIndex.type === prevChild.element.type &&\n typeof atIndex.props.$key === 'undefined'\n ) {\n return atIndex;\n }\n }\n }\n};\n\nconst renderElement = (\n element: RCXElementAny,\n renderingContextState: RCXRenderingContext,\n prevNode: RCXNodeAny | undefined,\n parentContext?: AnyObject\n): RCXNodeAny => {\n const node = updateNode(element, prevNode);\n\n node.context = {\n ...parentContext,\n };\n\n cxGlobal.currentNode = node;\n cxGlobal.hookIndex = 0;\n\n renderingContext.useProvide(renderingContextState);\n\n node.rendered = element.type(element.props);\n\n delete cxGlobal.currentNode;\n\n const traverse = (\n nextRendered: RCXChildren,\n prevRendered: NestedArray<RCXNodeAny> | undefined\n ): NestedArray<RCXNodeAny> => {\n if (!!nextRendered && typeof nextRendered === 'object') {\n if (isArray(nextRendered)) {\n let stillRendered: NestedArray<RCXNodeAny> | undefined;\n\n if (!isArray(prevRendered)) {\n unmountNodes(prevRendered);\n } else {\n stillRendered = prevRendered.filter((prevChild, prevChildIndex) => {\n const match = getMatchingChildNext(\n prevChild,\n prevChildIndex,\n nextRendered\n );\n\n if (!match) {\n unmountNodes(prevChild);\n }\n\n return !!match;\n });\n }\n\n return nextRendered.map((nextChild, nextChildIndex) =>\n traverse(\n nextChild,\n getMatchingChildPrev(nextChild, nextChildIndex, stillRendered)\n )\n );\n }\n\n if (!!prevRendered && typeof prevRendered === 'object') {\n if (isArray(prevRendered)) {\n unmountNodes(prevRendered);\n } else if (prevRendered.element.type !== nextRendered.type) {\n unmountNodes(prevRendered);\n }\n }\n\n return renderElement(\n nextRendered,\n renderingContextState,\n !!prevRendered &&\n typeof prevRendered === 'object' &&\n !isArray(prevRendered)\n ? prevRendered\n : undefined,\n node.context\n );\n }\n\n unmountNodes(prevRendered);\n\n return [];\n };\n\n node.hooks.forEach((hook) => {\n if (hook.type === 'useOnMount' && element.type !== prevNode?.element.type) {\n hook.value.onMount();\n }\n });\n\n node.hooks.forEach((hook) => {\n if (hook.type === 'useRenderBeforeChildren') {\n hook.value(renderingContextState);\n }\n });\n\n node.childNodes = traverse(node.rendered, prevNode?.childNodes);\n\n node.hooks.forEach((hook) => {\n if (hook.type === 'useRenderAfterChildren') {\n hook.value(renderingContextState);\n }\n });\n\n return node;\n};\n\nexport const render = (element: RCXElementAny, container: HTMLElement) => {\n const canvas = getCanvasElement(container);\n const ctx2d = canvas.getContext('2d');\n\n if (!ctx2d) {\n const errorMessage = 'CanvasRenderingContext2D not supported';\n\n if (window.console && typeof window.console.error === 'function') {\n // eslint-disable-next-line no-console\n console.error(errorMessage);\n }\n\n return {\n error: errorMessage,\n };\n }\n\n const renderingContextState = { canvas, ctx2d };\n\n let raf: number | undefined;\n let rootNode: RCXNodeAny | undefined;\n\n const renderRoot = () => {\n if (typeof raf === 'number') {\n window.cancelAnimationFrame(raf);\n }\n\n raf = window.requestAnimationFrame(() => {\n // eslint-disable-next-line no-self-assign\n canvas.width = canvas.width;\n rootNode = renderElement(element, renderingContextState, rootNode);\n });\n };\n\n renderRoot();\n\n emitter.on('render', renderRoot);\n\n const unmount = () => {\n if (typeof raf === 'number') {\n window.cancelAnimationFrame(raf);\n }\n // eslint-disable-next-line no-self-assign\n canvas.width = canvas.width;\n\n if (!(container instanceof HTMLCanvasElement)) {\n container.removeChild(canvas);\n }\n };\n\n return unmount;\n};\n"]}
package/types.d.ts ADDED
@@ -0,0 +1,108 @@
1
+ import type { CanvasProps } from './components/canvas/index.ts';
2
+ declare global {
3
+ namespace JSX {
4
+ interface IntrinsicAttributes {
5
+ $key?: string | number;
6
+ }
7
+ }
8
+ }
9
+ export type Primitive = string | number | boolean | null | undefined;
10
+ export type AnyObject = Record<PropertyKey, any>;
11
+ export type AnyArray = readonly any[];
12
+ export type AnyFunction = (...args: any[]) => any;
13
+ export type NestedArray<T> = T | readonly NestedArray<T>[];
14
+ export interface RCXElement<C extends RCXComponent<P>, P extends AnyObject> {
15
+ type: C;
16
+ props: P;
17
+ }
18
+ export type RCXElementAny = RCXElement<RCXComponentAny, AnyObject>;
19
+ export type RCXChild = RCXElementAny | Primitive;
20
+ export type RCXChildren = NestedArray<RCXChild>;
21
+ export interface RCXOnMountHook {
22
+ onMount: () => void;
23
+ onUnmount?: () => void;
24
+ }
25
+ export interface RCXHookMap {
26
+ useReactive: AnyObject;
27
+ useUnreactive: AnyObject;
28
+ useRenderBeforeChildren: (renderingContext: RCXRenderingContext) => void;
29
+ useRenderAfterChildren: (renderingContext: RCXRenderingContext) => void;
30
+ useOnMount: RCXOnMountHook;
31
+ useOnUnmount: () => void;
32
+ }
33
+ export type RCXHook = {
34
+ [K in keyof RCXHookMap]: {
35
+ type: K;
36
+ value: RCXHookMap[K];
37
+ };
38
+ }[keyof RCXHookMap];
39
+ export interface RCXNode<C extends RCXComponent<P>, P extends AnyObject> {
40
+ element: RCXElement<C, P>;
41
+ rendered: RCXChildren;
42
+ hooks: RCXHook[];
43
+ childNodes: NestedArray<RCXNodeAny>;
44
+ context: AnyObject;
45
+ }
46
+ export type RCXNodeAny = RCXNode<RCXComponentAny, AnyObject>;
47
+ export interface RCXRenderingContext {
48
+ readonly canvas: HTMLCanvasElement;
49
+ readonly ctx2d: CanvasRenderingContext2D;
50
+ }
51
+ export interface RCXComponentInterface {
52
+ displayName?: string;
53
+ }
54
+ export type RCXComponent<P extends AnyObject = Record<PropertyKey, never>> = ((props: Readonly<P>) => RCXChildren) & RCXComponentInterface;
55
+ export type RCXComponentAny = RCXComponent<AnyObject>;
56
+ export type RCXPropsWithChildren<P extends AnyObject> = Omit<P, 'children'> & {
57
+ children?: RCXChildren;
58
+ };
59
+ export interface RCXCanvasContext {
60
+ readonly props: CanvasProps;
61
+ readonly width: number;
62
+ readonly height: number;
63
+ readonly pixelRatio: number;
64
+ readonly actualWidth: number;
65
+ readonly actualHeight: number;
66
+ readonly canvas: Omit<HTMLCanvasElement, 'width' | 'height'>;
67
+ readonly ctx2d: CanvasRenderingContext2D;
68
+ }
69
+ export interface RCXGlobal {
70
+ currentNode?: RCXNodeAny;
71
+ hookIndex: number;
72
+ }
73
+ export interface RCXFragmentProps {
74
+ children?: RCXChildren;
75
+ }
76
+ export type RCXPoint = [number, number] | {
77
+ x: number;
78
+ y: number;
79
+ };
80
+ export type RCXStyleProp<T extends AnyObject> = NestedArray<false | null | undefined | T>;
81
+ export interface RCXLineStyle {
82
+ stroke?: RCXFillOrStrokeStyle;
83
+ strokeWidth?: number;
84
+ strokeCap?: CanvasLineCap;
85
+ strokeJoin?: CanvasLineJoin;
86
+ }
87
+ export interface RCXShapeStyle extends RCXLineStyle {
88
+ fill?: RCXFillOrStrokeStyle;
89
+ }
90
+ export interface RCXFontStringStyle {
91
+ fontStyle?: RCXCanvasFontStyle;
92
+ fontWeight?: RCXCanvasFontWeight;
93
+ fontSize?: number;
94
+ fontFamily?: string;
95
+ }
96
+ export interface RCXFontStyle extends RCXFontStringStyle {
97
+ fontStretch?: CanvasFontStretch;
98
+ fontVariant?: RCXCanvasFontVariant;
99
+ fontKerning?: CanvasFontKerning;
100
+ }
101
+ export type RCXCanvasFontStyle = 'normal' | 'italic' | 'oblique';
102
+ export type RCXCanvasFontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | number;
103
+ export type RCXCanvasFontVariant = 'normal' | CanvasFontVariantCaps;
104
+ export interface RCXColorStop {
105
+ offset: number;
106
+ color: string;
107
+ }
108
+ export type RCXFillOrStrokeStyle = string | CanvasGradient;
package/types.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
package/types.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { CanvasProps } from './components/canvas/index.ts';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace JSX {\n export interface IntrinsicAttributes {\n $key?: string | number;\n }\n }\n}\n\nexport type Primitive = string | number | boolean | null | undefined;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyObject = Record<PropertyKey, any>;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyArray = readonly any[];\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyFunction = (...args: any[]) => any;\n\nexport type NestedArray<T> = T | readonly NestedArray<T>[];\n\nexport interface RCXElement<C extends RCXComponent<P>, P extends AnyObject> {\n type: C;\n props: P;\n}\n\nexport type RCXElementAny = RCXElement<RCXComponentAny, AnyObject>;\n\nexport type RCXChild = RCXElementAny | Primitive;\n\nexport type RCXChildren = NestedArray<RCXChild>;\n\nexport interface RCXOnMountHook {\n onMount: () => void;\n onUnmount?: () => void;\n}\n\nexport interface RCXHookMap {\n useReactive: AnyObject;\n useUnreactive: AnyObject;\n useRenderBeforeChildren: (renderingContext: RCXRenderingContext) => void;\n useRenderAfterChildren: (renderingContext: RCXRenderingContext) => void;\n useOnMount: RCXOnMountHook;\n useOnUnmount: () => void;\n}\n\nexport type RCXHook = {\n [K in keyof RCXHookMap]: {\n type: K;\n value: RCXHookMap[K];\n };\n}[keyof RCXHookMap];\n\nexport interface RCXNode<C extends RCXComponent<P>, P extends AnyObject> {\n element: RCXElement<C, P>;\n rendered: RCXChildren;\n hooks: RCXHook[];\n childNodes: NestedArray<RCXNodeAny>;\n context: AnyObject;\n}\n\nexport type RCXNodeAny = RCXNode<RCXComponentAny, AnyObject>;\n\nexport interface RCXRenderingContext {\n readonly canvas: HTMLCanvasElement;\n readonly ctx2d: CanvasRenderingContext2D;\n}\n\nexport interface RCXComponentInterface {\n displayName?: string;\n}\n\nexport type RCXComponent<P extends AnyObject = Record<PropertyKey, never>> = ((\n props: Readonly<P>\n) => RCXChildren) &\n RCXComponentInterface;\n\nexport type RCXComponentAny = RCXComponent<AnyObject>;\n\nexport type RCXPropsWithChildren<P extends AnyObject> = Omit<P, 'children'> & {\n children?: RCXChildren;\n};\n\nexport interface RCXCanvasContext {\n readonly props: CanvasProps;\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n readonly actualWidth: number;\n readonly actualHeight: number;\n readonly canvas: Omit<HTMLCanvasElement, 'width' | 'height'>;\n readonly ctx2d: CanvasRenderingContext2D;\n}\n\nexport interface RCXGlobal {\n currentNode?: RCXNodeAny;\n hookIndex: number;\n}\n\nexport interface RCXFragmentProps {\n children?: RCXChildren;\n}\n\nexport type RCXPoint = [number, number] | { x: number; y: number };\n\nexport type RCXStyleProp<T extends AnyObject> = NestedArray<\n false | null | undefined | T\n>;\n\nexport interface RCXLineStyle {\n stroke?: RCXFillOrStrokeStyle;\n strokeWidth?: number;\n strokeCap?: CanvasLineCap;\n strokeJoin?: CanvasLineJoin;\n}\n\nexport interface RCXShapeStyle extends RCXLineStyle {\n fill?: RCXFillOrStrokeStyle;\n}\n\nexport interface RCXFontStringStyle {\n // font string\n fontStyle?: RCXCanvasFontStyle;\n fontWeight?: RCXCanvasFontWeight;\n fontSize?: number;\n fontFamily?: string;\n}\n\nexport interface RCXFontStyle extends RCXFontStringStyle {\n // other ctx2d properties\n fontStretch?: CanvasFontStretch;\n fontVariant?: RCXCanvasFontVariant;\n fontKerning?: CanvasFontKerning;\n}\n\nexport type RCXCanvasFontStyle = 'normal' | 'italic' | 'oblique';\nexport type RCXCanvasFontWeight =\n | 'normal'\n | 'bold'\n | 'bolder'\n | 'lighter'\n | number;\nexport type RCXCanvasFontVariant = 'normal' | CanvasFontVariantCaps;\n\nexport interface RCXColorStop {\n offset: number;\n color: string;\n}\n\nexport type RCXFillOrStrokeStyle = string | CanvasGradient;\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AnyObject, RCXRenderingContext } from '../types.ts';
2
+ export declare const applyFillAndStrokeStyles: (renderingContext: RCXRenderingContext, style: Partial<AnyObject>) => void;
@@ -0,0 +1,24 @@
1
+ import { isValidFillOrStrokeStyle } from "./is-valid-fill-or-stroke-style.js";
2
+ import { isValidStrokeCap } from "./is-valid-stroke-cap.js";
3
+ import { isValidStrokeJoin } from "./is-valid-stroke-join.js";
4
+ export const applyFillAndStrokeStyles = (renderingContext, style) => {
5
+ const { fill, stroke, strokeWidth, strokeCap, strokeJoin } = style;
6
+ if (isValidFillOrStrokeStyle(fill)) {
7
+ renderingContext.ctx2d.fillStyle = fill;
8
+ renderingContext.ctx2d.fill();
9
+ }
10
+ if (typeof strokeWidth === 'number') {
11
+ renderingContext.ctx2d.lineWidth = strokeWidth;
12
+ }
13
+ if (isValidStrokeCap(strokeCap)) {
14
+ renderingContext.ctx2d.lineCap = strokeCap;
15
+ }
16
+ if (isValidStrokeJoin(strokeJoin)) {
17
+ renderingContext.ctx2d.lineJoin = strokeJoin;
18
+ }
19
+ if (isValidFillOrStrokeStyle(stroke)) {
20
+ renderingContext.ctx2d.strokeStyle = stroke;
21
+ renderingContext.ctx2d.stroke();
22
+ }
23
+ };
24
+ //# sourceMappingURL=apply-fill-and-stroke-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-fill-and-stroke-style.js","sourceRoot":"","sources":["../../src/utils/apply-fill-and-stroke-style.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,gBAAqC,EACrC,KAAyB,EACzB,EAAE;IACF,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC;IAEnE,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;QACxC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpC,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC;IACjD,CAAC;IAED,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,gBAAgB,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS,CAAC;IAC7C,CAAC;IAED,IAAI,iBAAiB,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,GAAG,UAAU,CAAC;IAC/C,CAAC;IAED,IAAI,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC;QACrC,gBAAgB,CAAC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;QAC5C,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IAClC,CAAC;AACH,CAAC,CAAC","sourcesContent":["import type { AnyObject, RCXRenderingContext } from '../types.ts';\nimport { isValidFillOrStrokeStyle } from './is-valid-fill-or-stroke-style.ts';\nimport { isValidStrokeCap } from './is-valid-stroke-cap.ts';\nimport { isValidStrokeJoin } from './is-valid-stroke-join.ts';\n\nexport const applyFillAndStrokeStyles = (\n renderingContext: RCXRenderingContext,\n style: Partial<AnyObject>\n) => {\n const { fill, stroke, strokeWidth, strokeCap, strokeJoin } = style;\n\n if (isValidFillOrStrokeStyle(fill)) {\n renderingContext.ctx2d.fillStyle = fill;\n renderingContext.ctx2d.fill();\n }\n\n if (typeof strokeWidth === 'number') {\n renderingContext.ctx2d.lineWidth = strokeWidth;\n }\n\n if (isValidStrokeCap(strokeCap)) {\n renderingContext.ctx2d.lineCap = strokeCap;\n }\n\n if (isValidStrokeJoin(strokeJoin)) {\n renderingContext.ctx2d.lineJoin = strokeJoin;\n }\n\n if (isValidFillOrStrokeStyle(stroke)) {\n renderingContext.ctx2d.strokeStyle = stroke;\n renderingContext.ctx2d.stroke();\n }\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare const getRecommendedPixelRatio: () => 1 | 2;
@@ -0,0 +1,2 @@
1
+ export const getRecommendedPixelRatio = () => window.devicePixelRatio >= 2 ? 2 : 1;
2
+ //# sourceMappingURL=get-recommended-pixel-ratio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-recommended-pixel-ratio.js","sourceRoot":"","sources":["../../src/utils/get-recommended-pixel-ratio.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE,CAC3C,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["export const getRecommendedPixelRatio = () =>\n window.devicePixelRatio >= 2 ? 2 : 1;\n"]}
package/utils/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./apply-fill-and-stroke-style.js";
2
+ export * from "./get-recommended-pixel-ratio.js";
3
+ export * from "./is-own-property-of.js";
4
+ export * from "./is-valid-stroke-cap.js";
5
+ export * from "./is-valid-stroke-join.js";
6
+ export * from "./resolve-styles.js";
7
+ export * from "./type-guards.js";
8
+ export * from "./is-valid-fill-or-stroke-style.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oCAAoC,CAAC","sourcesContent":["export * from './apply-fill-and-stroke-style.ts';\nexport * from './get-recommended-pixel-ratio.ts';\nexport * from './is-own-property-of.ts';\nexport * from './is-valid-stroke-cap.ts';\nexport * from './is-valid-stroke-join.ts';\nexport * from './resolve-styles.ts';\nexport * from './type-guards.ts';\nexport * from './is-valid-fill-or-stroke-style.ts';\n"]}
@@ -0,0 +1,2 @@
1
+ import { AnyObject } from '../types.ts';
2
+ export declare const isOwnPropertyOf: <T extends AnyObject>(obj: T, key: PropertyKey) => key is keyof T;
@@ -0,0 +1,2 @@
1
+ export const isOwnPropertyOf = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
2
+ //# sourceMappingURL=is-own-property-of.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-own-property-of.js","sourceRoot":"","sources":["../../src/utils/is-own-property-of.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,GAAM,EACN,GAAgB,EACA,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC","sourcesContent":["import { AnyObject } from '../types.ts';\n\nexport const isOwnPropertyOf = <T extends AnyObject>(\n obj: T,\n key: PropertyKey\n): key is keyof T => Object.prototype.hasOwnProperty.call(obj, key);\n"]}
@@ -0,0 +1 @@
1
+ export declare const isValidFillOrStrokeStyle: (fillOrStrokeStyle: unknown) => fillOrStrokeStyle is string | CanvasGradient;
@@ -0,0 +1,3 @@
1
+ export const isValidFillOrStrokeStyle = (fillOrStrokeStyle) => typeof fillOrStrokeStyle === 'string' ||
2
+ fillOrStrokeStyle instanceof CanvasGradient;
3
+ //# sourceMappingURL=is-valid-fill-or-stroke-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-valid-fill-or-stroke-style.js","sourceRoot":"","sources":["../../src/utils/is-valid-fill-or-stroke-style.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,iBAA0B,EACoB,EAAE,CAChD,OAAO,iBAAiB,KAAK,QAAQ;IACrC,iBAAiB,YAAY,cAAc,CAAC","sourcesContent":["export const isValidFillOrStrokeStyle = (\n fillOrStrokeStyle: unknown\n): fillOrStrokeStyle is string | CanvasGradient =>\n typeof fillOrStrokeStyle === 'string' ||\n fillOrStrokeStyle instanceof CanvasGradient;\n"]}
@@ -0,0 +1 @@
1
+ export declare const isValidStrokeCap: (value: unknown) => value is CanvasLineCap;
@@ -0,0 +1,8 @@
1
+ import { isOwnPropertyOf } from "./is-own-property-of.js";
2
+ const STROKE_CAPS = {
3
+ butt: true,
4
+ round: true,
5
+ square: true,
6
+ };
7
+ export const isValidStrokeCap = (value) => typeof value === 'string' && isOwnPropertyOf(STROKE_CAPS, value);
8
+ //# sourceMappingURL=is-valid-stroke-cap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-valid-stroke-cap.js","sourceRoot":"","sources":["../../src/utils/is-valid-stroke-cap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;CACyB,CAAC;AAExC,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAA0B,EAAE,CACzE,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,CAAC,WAAW,EAAE,KAAe,CAAC,CAAC","sourcesContent":["import { isOwnPropertyOf } from './is-own-property-of.ts';\n\nconst STROKE_CAPS = {\n butt: true,\n round: true,\n square: true,\n} satisfies Record<CanvasLineCap, true>;\n\nexport const isValidStrokeCap = (value: unknown): value is CanvasLineCap =>\n typeof value === 'string' && isOwnPropertyOf(STROKE_CAPS, value as string);\n"]}
@@ -0,0 +1 @@
1
+ export declare const isValidStrokeJoin: (value: unknown) => value is CanvasLineJoin;
@@ -0,0 +1,8 @@
1
+ import { isOwnPropertyOf } from "./is-own-property-of.js";
2
+ const STROKE_JOINS = {
3
+ bevel: true,
4
+ round: true,
5
+ miter: true,
6
+ };
7
+ export const isValidStrokeJoin = (value) => typeof value === 'string' && isOwnPropertyOf(STROKE_JOINS, value);
8
+ //# sourceMappingURL=is-valid-stroke-join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-valid-stroke-join.js","sourceRoot":"","sources":["../../src/utils/is-valid-stroke-join.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,YAAY,GAAG;IACnB,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,IAAI;CAC2B,CAAC;AAEzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAA2B,EAAE,CAC3E,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,CAAC,YAAY,EAAE,KAAe,CAAC,CAAC","sourcesContent":["import { isOwnPropertyOf } from './is-own-property-of.ts';\n\nconst STROKE_JOINS = {\n bevel: true,\n round: true,\n miter: true,\n} satisfies Record<CanvasLineJoin, true>;\n\nexport const isValidStrokeJoin = (value: unknown): value is CanvasLineJoin =>\n typeof value === 'string' && isOwnPropertyOf(STROKE_JOINS, value as string);\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AnyObject, NestedArray } from '../types.ts';
2
+ export declare const resolveStyles: <S extends AnyObject>(styles: NestedArray<false | null | undefined | S>) => Partial<S>;
@@ -0,0 +1,16 @@
1
+ import { isArray } from "./type-guards.js";
2
+ export const resolveStyles = (styles) => {
3
+ if (typeof styles === 'object' && !!styles) {
4
+ if (isArray(styles)) {
5
+ return styles.reduce((acc, style) => {
6
+ return {
7
+ ...acc,
8
+ ...resolveStyles(style),
9
+ };
10
+ }, {});
11
+ }
12
+ return styles;
13
+ }
14
+ return {};
15
+ };
16
+ //# sourceMappingURL=resolve-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-styles.js","sourceRoot":"","sources":["../../src/utils/resolve-styles.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAiD,EACrC,EAAE;IACd,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBAClC,OAAO;oBACL,GAAG,GAAG;oBACN,GAAG,aAAa,CAAC,KAAK,CAAC;iBACxB,CAAC;YACJ,CAAC,EAAE,EAAE,CAAC,CAAC;QACT,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC","sourcesContent":["import type { AnyObject, NestedArray } from '../types.ts';\nimport { isArray } from './type-guards.ts';\n\nexport const resolveStyles = <S extends AnyObject>(\n styles: NestedArray<false | null | undefined | S>\n): Partial<S> => {\n if (typeof styles === 'object' && !!styles) {\n if (isArray(styles)) {\n return styles.reduce((acc, style) => {\n return {\n ...acc,\n ...resolveStyles(style),\n };\n }, {});\n }\n\n return styles;\n }\n\n return {};\n};\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AnyArray } from '../types.ts';
2
+ export declare const isArray: <T>(input: T) => input is Extract<T, AnyArray>;
@@ -0,0 +1,2 @@
1
+ export const isArray = (input) => Array.isArray(input);
2
+ //# sourceMappingURL=type-guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.js","sourceRoot":"","sources":["../../src/utils/type-guards.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,KAAQ,EAAiC,EAAE,CACpE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC","sourcesContent":["import type { AnyArray } from '../types.ts';\n\nexport const isArray = <T>(input: T): input is Extract<T, AnyArray> =>\n Array.isArray(input);\n"]}
@@ -0,0 +1 @@
1
+ export declare const withPx: <T extends string | number>(value: T) => T extends number ? `${T}px` : T;
@@ -0,0 +1,2 @@
1
+ export const withPx = (value) => (typeof value === 'number' ? `${value}px` : value);
2
+ //# sourceMappingURL=with-px.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-px.js","sourceRoot":"","sources":["../../src/utils/with-px.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG,CAA4B,KAAQ,EAAE,EAAE,CAC5D,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAE5C,CAAC","sourcesContent":["export const withPx = <T extends string | number>(value: T) =>\n (typeof value === 'number' ? `${value}px` : value) as T extends number\n ? `${T}px`\n : T;\n"]}
package/.eslintignore DELETED
@@ -1,4 +0,0 @@
1
- /node_modules/*
2
- /coverage/*
3
- /build/*
4
- /dist/*