@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.
- package/components/canvas/context.d.ts +11 -0
- package/components/canvas/context.js +4 -0
- package/components/canvas/context.js.map +1 -0
- package/components/canvas/index.d.ts +7 -0
- package/components/canvas/index.js +62 -0
- package/components/canvas/index.js.map +1 -0
- package/components/index.js +6 -0
- package/components/index.js.map +1 -0
- package/components/paths/arc-to.d.ts +12 -0
- package/components/paths/arc-to.js +24 -0
- package/components/paths/arc-to.js.map +1 -0
- package/components/paths/clip.d.ts +6 -0
- package/components/paths/clip.js +19 -0
- package/components/paths/clip.js.map +1 -0
- package/components/paths/index.js +6 -0
- package/components/paths/index.js.map +1 -0
- package/components/paths/line.d.ts +11 -0
- package/components/paths/line.js +25 -0
- package/components/paths/line.js.map +1 -0
- package/components/paths/path.d.ts +8 -0
- package/components/paths/path.js +33 -0
- package/components/paths/path.js.map +1 -0
- package/components/paths/point.d.ts +7 -0
- package/components/paths/point.js +15 -0
- package/components/paths/point.js.map +1 -0
- package/components/shapes/circle.d.ts +14 -0
- package/components/shapes/circle.js +8 -0
- package/components/shapes/circle.js.map +1 -0
- package/components/shapes/ellipse.d.ts +15 -0
- package/components/shapes/ellipse.js +24 -0
- package/components/shapes/ellipse.js.map +1 -0
- package/components/shapes/index.js +4 -0
- package/components/shapes/index.js.map +1 -0
- package/components/shapes/rectangle.d.ts +10 -0
- package/components/shapes/rectangle.js +20 -0
- package/components/shapes/rectangle.js.map +1 -0
- package/components/text/index.js +2 -0
- package/components/text/index.js.map +1 -0
- package/components/text/text.d.ts +13 -0
- package/components/text/text.js +78 -0
- package/components/text/text.js.map +1 -0
- package/components/transform/index.js +4 -0
- package/components/transform/index.js.map +1 -0
- package/components/transform/rotate.d.ts +5 -0
- package/components/transform/rotate.js +14 -0
- package/components/transform/rotate.js.map +1 -0
- package/components/transform/scale.d.ts +11 -0
- package/components/transform/scale.js +14 -0
- package/components/transform/scale.js.map +1 -0
- package/components/transform/translate.d.ts +6 -0
- package/components/transform/translate.js +14 -0
- package/components/transform/translate.js.map +1 -0
- package/context/create-context.d.ts +9 -0
- package/context/create-context.js +29 -0
- package/context/create-context.js.map +1 -0
- package/context/index.js +2 -0
- package/context/index.js.map +1 -0
- package/hooks/index.js +9 -0
- package/hooks/index.js.map +1 -0
- package/hooks/use-canvas-context.d.ts +1 -0
- package/hooks/use-canvas-context.js +9 -0
- package/hooks/use-canvas-context.js.map +1 -0
- package/hooks/use-linear-gradient.d.ts +9 -0
- package/hooks/use-linear-gradient.js +13 -0
- package/hooks/use-linear-gradient.js.map +1 -0
- package/hooks/use-loop.d.ts +1 -0
- package/hooks/use-loop.js +9 -0
- package/hooks/use-loop.js.map +1 -0
- package/hooks/use-on.d.ts +2 -0
- package/hooks/use-on.js +16 -0
- package/hooks/use-on.js.map +1 -0
- package/hooks/use-radial-gradient.d.ts +11 -0
- package/hooks/use-radial-gradient.js +13 -0
- package/hooks/use-radial-gradient.js.map +1 -0
- package/hooks/use-render.d.ts +3 -0
- package/hooks/use-render.js +8 -0
- package/hooks/use-render.js.map +1 -0
- package/hooks/use-state.d.ts +3 -0
- package/hooks/use-state.js +5 -0
- package/hooks/use-state.js.map +1 -0
- package/hooks/use-window-size.d.ts +4 -0
- package/hooks/use-window-size.js +20 -0
- package/hooks/use-window-size.js.map +1 -0
- package/index.js +7 -0
- package/index.js.map +1 -0
- package/internal/emitter.d.ts +15 -0
- package/internal/emitter.js +19 -0
- package/internal/emitter.js.map +1 -0
- package/internal/global.d.ts +2 -0
- package/internal/global.js +4 -0
- package/internal/global.js.map +1 -0
- package/internal/hooks.d.ts +2 -0
- package/internal/hooks.js +17 -0
- package/internal/hooks.js.map +1 -0
- package/internal/reactive.d.ts +2 -0
- package/internal/reactive.js +16 -0
- package/internal/reactive.js.map +1 -0
- package/jsx-runtime.d.ts +4 -0
- package/jsx-runtime.js +8 -0
- package/jsx-runtime.js.map +1 -0
- package/package.json +11 -23
- package/render.d.ts +4 -0
- package/render.js +198 -0
- package/render.js.map +1 -0
- package/types.d.ts +108 -0
- package/types.js +1 -0
- package/types.js.map +1 -0
- package/utils/apply-fill-and-stroke-style.d.ts +2 -0
- package/utils/apply-fill-and-stroke-style.js +24 -0
- package/utils/apply-fill-and-stroke-style.js.map +1 -0
- package/utils/get-recommended-pixel-ratio.d.ts +1 -0
- package/utils/get-recommended-pixel-ratio.js +2 -0
- package/utils/get-recommended-pixel-ratio.js.map +1 -0
- package/utils/index.js +9 -0
- package/utils/index.js.map +1 -0
- package/utils/is-own-property-of.d.ts +2 -0
- package/utils/is-own-property-of.js +2 -0
- package/utils/is-own-property-of.js.map +1 -0
- package/utils/is-valid-fill-or-stroke-style.d.ts +1 -0
- package/utils/is-valid-fill-or-stroke-style.js +3 -0
- package/utils/is-valid-fill-or-stroke-style.js.map +1 -0
- package/utils/is-valid-stroke-cap.d.ts +1 -0
- package/utils/is-valid-stroke-cap.js +8 -0
- package/utils/is-valid-stroke-cap.js.map +1 -0
- package/utils/is-valid-stroke-join.d.ts +1 -0
- package/utils/is-valid-stroke-join.js +8 -0
- package/utils/is-valid-stroke-join.js.map +1 -0
- package/utils/resolve-styles.d.ts +2 -0
- package/utils/resolve-styles.js +16 -0
- package/utils/resolve-styles.js.map +1 -0
- package/utils/type-guards.d.ts +2 -0
- package/utils/type-guards.js +2 -0
- package/utils/type-guards.js.map +1 -0
- package/utils/with-px.d.ts +1 -0
- package/utils/with-px.js +2 -0
- package/utils/with-px.js.map +1 -0
- package/.eslintignore +0 -4
- package/.eslintrc.json +0 -286
- package/.gitattributes +0 -2
- package/.github/CODEOWNERS +0 -1
- package/.github/workflows/ci.yml +0 -19
- package/.nvmrc +0 -1
- package/.prettierignore +0 -28
- package/.prettierrc.json +0 -4
- package/demo/index.html +0 -29
- package/demo/index.tsx +0 -316
- package/demo/tsconfig.json +0 -12
- package/jest.config.ts +0 -21
- package/scripts/prep-package.js +0 -29
- package/src/components/canvas/context.ts +0 -6
- package/src/components/canvas/index.ts +0 -98
- package/src/components/paths/arc-to.ts +0 -66
- package/src/components/paths/clip.ts +0 -32
- package/src/components/paths/line.ts +0 -53
- package/src/components/paths/path.ts +0 -59
- package/src/components/paths/point.ts +0 -24
- package/src/components/shapes/circle.tsx +0 -32
- package/src/components/shapes/ellipse.ts +0 -75
- package/src/components/shapes/rectangle.ts +0 -45
- package/src/components/text/text.ts +0 -137
- package/src/components/transform/rotate.ts +0 -26
- package/src/components/transform/scale.ts +0 -34
- package/src/components/transform/translate.ts +0 -27
- package/src/context/create-context.ts +0 -49
- package/src/hooks/use-canvas-context.ts +0 -11
- package/src/hooks/use-linear-gradient.ts +0 -39
- package/src/hooks/use-loop.ts +0 -11
- package/src/hooks/use-on.ts +0 -18
- package/src/hooks/use-radial-gradient.ts +0 -45
- package/src/hooks/use-render.ts +0 -14
- package/src/hooks/use-state.ts +0 -9
- package/src/hooks/use-window-size.ts +0 -24
- package/src/internal/emitter.ts +0 -39
- package/src/internal/global.ts +0 -5
- package/src/internal/hooks.ts +0 -32
- package/src/internal/reactive.test.ts +0 -20
- package/src/internal/reactive.ts +0 -20
- package/src/jsx-runtime.ts +0 -21
- package/src/render.ts +0 -299
- package/src/types.ts +0 -151
- package/src/utils/apply-fill-and-stroke-style.ts +0 -33
- package/src/utils/get-recommended-pixel-ratio.ts +0 -2
- package/src/utils/is-own-property-of.ts +0 -6
- package/src/utils/is-valid-fill-or-stroke-style.ts +0 -5
- package/src/utils/is-valid-stroke-cap.ts +0 -10
- package/src/utils/is-valid-stroke-join.ts +0 -10
- package/src/utils/resolve-styles.ts +0 -21
- package/src/utils/type-guards.ts +0 -4
- package/src/utils/with-px.ts +0 -4
- package/tsb.config.ts +0 -11
- package/tsconfig.dist.json +0 -13
- package/tsconfig.json +0 -25
- /package/{src/components/index.ts → components/index.d.ts} +0 -0
- /package/{src/components/paths/index.ts → components/paths/index.d.ts} +0 -0
- /package/{src/components/shapes/index.ts → components/shapes/index.d.ts} +0 -0
- /package/{src/components/text/index.ts → components/text/index.d.ts} +0 -0
- /package/{src/components/transform/index.ts → components/transform/index.d.ts} +0 -0
- /package/{src/context/index.ts → context/index.d.ts} +0 -0
- /package/{src/hooks/index.ts → hooks/index.d.ts} +0 -0
- /package/{src/index.ts → index.d.ts} +0 -0
- /package/{src/utils/index.ts → utils/index.d.ts} +0 -0
package/jest.config.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { Config } from 'jest';
|
|
2
|
-
|
|
3
|
-
const config = {
|
|
4
|
-
preset: 'ts-jest/presets/default-esm',
|
|
5
|
-
testMatch: ['<rootDir>/src/**/*.(spec|test).{js,jsx,ts,tsx}'],
|
|
6
|
-
collectCoverageFrom: ['src/**/*.(js|jsx|ts|tsx)'],
|
|
7
|
-
// coverageThreshold: {
|
|
8
|
-
// global: {
|
|
9
|
-
// branches: 100,
|
|
10
|
-
// functions: 100,
|
|
11
|
-
// lines: 100,
|
|
12
|
-
// statements: 100,
|
|
13
|
-
// },
|
|
14
|
-
// },
|
|
15
|
-
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
|
16
|
-
moduleNameMapper: {
|
|
17
|
-
'(.+)\\.js$': '$1',
|
|
18
|
-
},
|
|
19
|
-
} satisfies Config;
|
|
20
|
-
|
|
21
|
-
export default config;
|
package/scripts/prep-package.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, resolve } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
|
|
5
|
-
import packageJson from '../package.json' with { type: 'json' };
|
|
6
|
-
|
|
7
|
-
const cwd = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
|
|
9
|
-
const modifiedJson = {
|
|
10
|
-
...packageJson,
|
|
11
|
-
main: packageJson.main.replace('src/', '').replace('.ts', '.js'),
|
|
12
|
-
exports: Object.fromEntries(
|
|
13
|
-
Object.entries(packageJson.exports).map(([key, imports]) => [
|
|
14
|
-
key,
|
|
15
|
-
Object.fromEntries(
|
|
16
|
-
Object.entries(imports).map(([path, actual]) => [
|
|
17
|
-
path,
|
|
18
|
-
actual.replace('src/', '').replace('.ts', '.js'),
|
|
19
|
-
])
|
|
20
|
-
),
|
|
21
|
-
])
|
|
22
|
-
),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
writeFileSync(
|
|
26
|
-
resolve(cwd, '../dist/package.json'),
|
|
27
|
-
JSON.stringify(modifiedJson, null, 2),
|
|
28
|
-
'utf-8'
|
|
29
|
-
);
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { createContext } from '../../context/create-context.ts';
|
|
2
|
-
import type { RCXCanvasContext, RCXRenderingContext } from '../../types.ts';
|
|
3
|
-
|
|
4
|
-
export const canvasContext = createContext<RCXCanvasContext>();
|
|
5
|
-
|
|
6
|
-
export const renderingContext = createContext<RCXRenderingContext>();
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { useOnMount } from '../../hooks/use-on.ts';
|
|
2
|
-
import { useRenderBeforeChildren } from '../../hooks/use-render.ts';
|
|
3
|
-
import { useReactive, useUnreactive } from '../../hooks/use-state.ts';
|
|
4
|
-
import type { RCXComponent, RCXPropsWithChildren } from '../../types.ts';
|
|
5
|
-
import { getRecommendedPixelRatio } from '../../utils/get-recommended-pixel-ratio.ts';
|
|
6
|
-
import { canvasContext, renderingContext } from './context.ts';
|
|
7
|
-
|
|
8
|
-
export type CanvasProps = RCXPropsWithChildren<{
|
|
9
|
-
width?: number | 'auto';
|
|
10
|
-
height?: number | 'auto';
|
|
11
|
-
pixelRatio?: number | 'auto';
|
|
12
|
-
}>;
|
|
13
|
-
|
|
14
|
-
const getValueOrAuto = (
|
|
15
|
-
value: undefined | number | 'auto',
|
|
16
|
-
autoValue: number
|
|
17
|
-
) => {
|
|
18
|
-
if (typeof value === 'number') {
|
|
19
|
-
return value;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return autoValue;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const Canvas: RCXComponent<CanvasProps> = (props) => {
|
|
26
|
-
const renderingContextStateRoot = renderingContext.useInject();
|
|
27
|
-
|
|
28
|
-
if (!renderingContextStateRoot) {
|
|
29
|
-
throw new Error('Canvas was rendered outside of an application');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const initialCanvasSize =
|
|
33
|
-
renderingContextStateRoot.canvas.getBoundingClientRect();
|
|
34
|
-
const canvasSize = useReactive({
|
|
35
|
-
width: initialCanvasSize.width,
|
|
36
|
-
height: initialCanvasSize.height,
|
|
37
|
-
});
|
|
38
|
-
const resizeObserver = useUnreactive(
|
|
39
|
-
new ResizeObserver((entries) => {
|
|
40
|
-
const canvasEntry = entries[0];
|
|
41
|
-
if (typeof canvasEntry === 'undefined') {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const rect = canvasEntry.target.getBoundingClientRect();
|
|
46
|
-
canvasSize.width = rect.width;
|
|
47
|
-
canvasSize.height = rect.height;
|
|
48
|
-
})
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
useOnMount(() => {
|
|
52
|
-
resizeObserver.observe(renderingContextStateRoot.canvas);
|
|
53
|
-
|
|
54
|
-
return () => {
|
|
55
|
-
resizeObserver.disconnect();
|
|
56
|
-
};
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
useRenderBeforeChildren((renderingContextState) => {
|
|
60
|
-
const pixelRatio = getValueOrAuto(
|
|
61
|
-
props.pixelRatio,
|
|
62
|
-
getRecommendedPixelRatio()
|
|
63
|
-
);
|
|
64
|
-
const rect = renderingContextState.canvas.getBoundingClientRect();
|
|
65
|
-
const width =
|
|
66
|
-
getValueOrAuto(props.width, rect.width * pixelRatio) / pixelRatio;
|
|
67
|
-
const height =
|
|
68
|
-
getValueOrAuto(props.height, rect.height * pixelRatio) / pixelRatio;
|
|
69
|
-
|
|
70
|
-
renderingContextState.canvas.width = width * pixelRatio;
|
|
71
|
-
renderingContextState.canvas.height = height * pixelRatio;
|
|
72
|
-
renderingContextState.ctx2d.scale(pixelRatio, pixelRatio);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
const pixelRatio = getValueOrAuto(
|
|
76
|
-
props.pixelRatio,
|
|
77
|
-
getRecommendedPixelRatio()
|
|
78
|
-
);
|
|
79
|
-
const rect = renderingContextStateRoot.canvas.getBoundingClientRect();
|
|
80
|
-
const width =
|
|
81
|
-
getValueOrAuto(props.width, rect.width * pixelRatio) / pixelRatio;
|
|
82
|
-
const height =
|
|
83
|
-
getValueOrAuto(props.height, rect.height * pixelRatio) / pixelRatio;
|
|
84
|
-
|
|
85
|
-
canvasContext.useProvide({
|
|
86
|
-
...renderingContextStateRoot,
|
|
87
|
-
props,
|
|
88
|
-
width,
|
|
89
|
-
height,
|
|
90
|
-
pixelRatio,
|
|
91
|
-
actualWidth: width * pixelRatio,
|
|
92
|
-
actualHeight: height * pixelRatio,
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
return props.children;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
Canvas.displayName = 'Canvas';
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type {
|
|
6
|
-
RCXComponent,
|
|
7
|
-
RCXPropsWithChildren,
|
|
8
|
-
RCXShapeStyle,
|
|
9
|
-
RCXStyleProp,
|
|
10
|
-
} from '../../types.ts';
|
|
11
|
-
import { applyFillAndStrokeStyles } from '../../utils/apply-fill-and-stroke-style.ts';
|
|
12
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
13
|
-
|
|
14
|
-
export type ArcToProps = RCXPropsWithChildren<{
|
|
15
|
-
startControlX: number;
|
|
16
|
-
startControlY: number;
|
|
17
|
-
endControlX: number;
|
|
18
|
-
endControlY: number;
|
|
19
|
-
radius: number;
|
|
20
|
-
style?: RCXStyleProp<RCXShapeStyle>;
|
|
21
|
-
beginPath?: boolean;
|
|
22
|
-
closePath?: boolean;
|
|
23
|
-
}>;
|
|
24
|
-
|
|
25
|
-
export const ArcTo: RCXComponent<ArcToProps> = (props) => {
|
|
26
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
27
|
-
const {
|
|
28
|
-
startControlX,
|
|
29
|
-
startControlY,
|
|
30
|
-
endControlX,
|
|
31
|
-
endControlY,
|
|
32
|
-
radius,
|
|
33
|
-
beginPath = false,
|
|
34
|
-
} = props;
|
|
35
|
-
|
|
36
|
-
renderingContext.ctx2d.save();
|
|
37
|
-
|
|
38
|
-
if (beginPath) {
|
|
39
|
-
renderingContext.ctx2d.beginPath();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
renderingContext.ctx2d.arcTo(
|
|
43
|
-
startControlX,
|
|
44
|
-
startControlY,
|
|
45
|
-
endControlX,
|
|
46
|
-
endControlY,
|
|
47
|
-
radius
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
useRenderAfterChildren((renderingContext) => {
|
|
52
|
-
const { closePath = false } = props;
|
|
53
|
-
|
|
54
|
-
if (closePath) {
|
|
55
|
-
renderingContext.ctx2d.closePath();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
applyFillAndStrokeStyles(renderingContext, resolveStyles(props.style));
|
|
59
|
-
|
|
60
|
-
renderingContext.ctx2d.restore();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
return props.children;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
ArcTo.displayName = 'ArcTo';
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type { RCXComponent, RCXPropsWithChildren } from '../../types.ts';
|
|
6
|
-
|
|
7
|
-
export type ClipProps = RCXPropsWithChildren<{
|
|
8
|
-
path?: Path2D;
|
|
9
|
-
fillRule?: CanvasFillRule;
|
|
10
|
-
}>;
|
|
11
|
-
|
|
12
|
-
export const Clip: RCXComponent<ClipProps> = (props) => {
|
|
13
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
14
|
-
const { path, fillRule } = props;
|
|
15
|
-
|
|
16
|
-
renderingContext.ctx2d.save();
|
|
17
|
-
|
|
18
|
-
if (typeof path === 'undefined') {
|
|
19
|
-
renderingContext.ctx2d.clip(fillRule);
|
|
20
|
-
} else {
|
|
21
|
-
renderingContext.ctx2d.clip(path, fillRule);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
useRenderAfterChildren((renderingContext) => {
|
|
26
|
-
renderingContext.ctx2d.restore();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
return props.children;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
Clip.displayName = 'Clip';
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type {
|
|
6
|
-
RCXComponent,
|
|
7
|
-
RCXLineStyle,
|
|
8
|
-
RCXPropsWithChildren,
|
|
9
|
-
RCXStyleProp,
|
|
10
|
-
} from '../../types.ts';
|
|
11
|
-
import { applyFillAndStrokeStyles } from '../../utils/apply-fill-and-stroke-style.ts';
|
|
12
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
13
|
-
|
|
14
|
-
export type LineProps = RCXPropsWithChildren<{
|
|
15
|
-
startX: number;
|
|
16
|
-
startY: number;
|
|
17
|
-
endX: number;
|
|
18
|
-
endY: number;
|
|
19
|
-
beginPath?: boolean;
|
|
20
|
-
closePath?: boolean;
|
|
21
|
-
style?: RCXStyleProp<RCXLineStyle>;
|
|
22
|
-
}>;
|
|
23
|
-
|
|
24
|
-
export const Line: RCXComponent<LineProps> = (props) => {
|
|
25
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
26
|
-
const { startX, startY, endX, endY, beginPath = true } = props;
|
|
27
|
-
|
|
28
|
-
renderingContext.ctx2d.save();
|
|
29
|
-
|
|
30
|
-
if (beginPath) {
|
|
31
|
-
renderingContext.ctx2d.beginPath();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
renderingContext.ctx2d.moveTo(startX, startY);
|
|
35
|
-
renderingContext.ctx2d.lineTo(endX, endY);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
useRenderAfterChildren((renderingContext) => {
|
|
39
|
-
const { closePath = false } = props;
|
|
40
|
-
|
|
41
|
-
if (closePath) {
|
|
42
|
-
renderingContext.ctx2d.closePath();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
applyFillAndStrokeStyles(renderingContext, resolveStyles(props.style));
|
|
46
|
-
|
|
47
|
-
renderingContext.ctx2d.restore();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return props.children;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
Line.displayName = 'Line';
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type {
|
|
6
|
-
RCXComponent,
|
|
7
|
-
RCXPoint,
|
|
8
|
-
RCXPropsWithChildren,
|
|
9
|
-
RCXShapeStyle,
|
|
10
|
-
RCXStyleProp,
|
|
11
|
-
} from '../../types.ts';
|
|
12
|
-
import { applyFillAndStrokeStyles } from '../../utils/apply-fill-and-stroke-style.ts';
|
|
13
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
14
|
-
import { isArray } from '../../utils/type-guards.ts';
|
|
15
|
-
|
|
16
|
-
export type PathProps = RCXPropsWithChildren<{
|
|
17
|
-
points?: readonly RCXPoint[];
|
|
18
|
-
beginPath?: boolean;
|
|
19
|
-
closePath?: boolean;
|
|
20
|
-
style?: RCXStyleProp<RCXShapeStyle>;
|
|
21
|
-
}>;
|
|
22
|
-
|
|
23
|
-
export const Path: RCXComponent<PathProps> = (props) => {
|
|
24
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
25
|
-
const { points, beginPath = true } = props;
|
|
26
|
-
|
|
27
|
-
renderingContext.ctx2d.save();
|
|
28
|
-
|
|
29
|
-
if (beginPath) {
|
|
30
|
-
renderingContext.ctx2d.beginPath();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
points?.forEach((point, index) => {
|
|
34
|
-
const [x, y] = isArray(point) ? point : [point.x, point.y];
|
|
35
|
-
|
|
36
|
-
if (index === 0) {
|
|
37
|
-
renderingContext.ctx2d.moveTo(x, y);
|
|
38
|
-
} else {
|
|
39
|
-
renderingContext.ctx2d.lineTo(x, y);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
useRenderAfterChildren((renderingContext) => {
|
|
45
|
-
const { closePath = false } = props;
|
|
46
|
-
|
|
47
|
-
if (closePath) {
|
|
48
|
-
renderingContext.ctx2d.closePath();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
applyFillAndStrokeStyles(renderingContext, resolveStyles(props.style));
|
|
52
|
-
|
|
53
|
-
renderingContext.ctx2d.restore();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return props.children;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
Path.displayName = 'Path';
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { useRenderBeforeChildren } from '../../hooks/use-render.ts';
|
|
2
|
-
import type { RCXComponent, RCXPropsWithChildren } from '../../types.ts';
|
|
3
|
-
|
|
4
|
-
export type PointProps = RCXPropsWithChildren<{
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
lineTo?: boolean;
|
|
8
|
-
}>;
|
|
9
|
-
|
|
10
|
-
export const Point: RCXComponent<PointProps> = (props) => {
|
|
11
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
12
|
-
const { x, y, lineTo = true } = props;
|
|
13
|
-
|
|
14
|
-
if (lineTo) {
|
|
15
|
-
renderingContext.ctx2d.lineTo(x, y);
|
|
16
|
-
} else {
|
|
17
|
-
renderingContext.ctx2d.moveTo(x, y);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
return props.children;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
Point.displayName = 'Point';
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RCXComponent,
|
|
3
|
-
RCXPropsWithChildren,
|
|
4
|
-
RCXShapeStyle,
|
|
5
|
-
RCXStyleProp,
|
|
6
|
-
} from '../../types.ts';
|
|
7
|
-
import { Ellipse } from './ellipse.ts';
|
|
8
|
-
|
|
9
|
-
export type CircleProps = RCXPropsWithChildren<{
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
radius: number;
|
|
13
|
-
rotation?: number;
|
|
14
|
-
startAngle?: number;
|
|
15
|
-
endAngle?: number;
|
|
16
|
-
counterClockwise?: boolean;
|
|
17
|
-
beginPath?: boolean;
|
|
18
|
-
closePath?: boolean;
|
|
19
|
-
style?: RCXStyleProp<RCXShapeStyle>;
|
|
20
|
-
}>;
|
|
21
|
-
|
|
22
|
-
export const Circle: RCXComponent<CircleProps> = (props) => {
|
|
23
|
-
const { radius, ...rest } = props;
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<Ellipse {...rest} radiusX={radius} radiusY={radius}>
|
|
27
|
-
{props.children}
|
|
28
|
-
</Ellipse>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
Circle.displayName = 'Circle';
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type {
|
|
6
|
-
RCXComponent,
|
|
7
|
-
RCXPropsWithChildren,
|
|
8
|
-
RCXShapeStyle,
|
|
9
|
-
RCXStyleProp,
|
|
10
|
-
} from '../../types.ts';
|
|
11
|
-
import { applyFillAndStrokeStyles } from '../../utils/apply-fill-and-stroke-style.ts';
|
|
12
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
13
|
-
|
|
14
|
-
export type EllipseProps = RCXPropsWithChildren<{
|
|
15
|
-
x: number;
|
|
16
|
-
y: number;
|
|
17
|
-
radiusX: number;
|
|
18
|
-
radiusY: number;
|
|
19
|
-
rotation?: number;
|
|
20
|
-
startAngle?: number;
|
|
21
|
-
endAngle?: number;
|
|
22
|
-
counterClockwise?: boolean;
|
|
23
|
-
beginPath?: boolean;
|
|
24
|
-
closePath?: boolean;
|
|
25
|
-
style?: RCXStyleProp<RCXShapeStyle>;
|
|
26
|
-
}>;
|
|
27
|
-
|
|
28
|
-
export const Ellipse: RCXComponent<EllipseProps> = (props) => {
|
|
29
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
30
|
-
const {
|
|
31
|
-
x,
|
|
32
|
-
y,
|
|
33
|
-
radiusX,
|
|
34
|
-
radiusY,
|
|
35
|
-
rotation = 0,
|
|
36
|
-
startAngle = 0,
|
|
37
|
-
endAngle = Math.PI * 2,
|
|
38
|
-
counterClockwise = false,
|
|
39
|
-
beginPath = true,
|
|
40
|
-
} = props;
|
|
41
|
-
|
|
42
|
-
renderingContext.ctx2d.save();
|
|
43
|
-
|
|
44
|
-
if (beginPath) {
|
|
45
|
-
renderingContext.ctx2d.beginPath();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
renderingContext.ctx2d.ellipse(
|
|
49
|
-
x,
|
|
50
|
-
y,
|
|
51
|
-
radiusX,
|
|
52
|
-
radiusY,
|
|
53
|
-
rotation,
|
|
54
|
-
startAngle,
|
|
55
|
-
endAngle,
|
|
56
|
-
counterClockwise
|
|
57
|
-
);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
useRenderAfterChildren((renderingContext) => {
|
|
61
|
-
const { closePath = true } = props;
|
|
62
|
-
|
|
63
|
-
if (closePath) {
|
|
64
|
-
renderingContext.ctx2d.closePath();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
applyFillAndStrokeStyles(renderingContext, resolveStyles(props.style));
|
|
68
|
-
|
|
69
|
-
renderingContext.ctx2d.restore();
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return props.children;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
Ellipse.displayName = 'Ellipse';
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useRenderAfterChildren,
|
|
3
|
-
useRenderBeforeChildren,
|
|
4
|
-
} from '../../hooks/use-render.ts';
|
|
5
|
-
import type {
|
|
6
|
-
RCXComponent,
|
|
7
|
-
RCXPropsWithChildren,
|
|
8
|
-
RCXShapeStyle,
|
|
9
|
-
RCXStyleProp,
|
|
10
|
-
} from '../../types.ts';
|
|
11
|
-
import { applyFillAndStrokeStyles } from '../../utils/apply-fill-and-stroke-style.ts';
|
|
12
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
13
|
-
|
|
14
|
-
export type RectangleProps = RCXPropsWithChildren<{
|
|
15
|
-
x: number;
|
|
16
|
-
y: number;
|
|
17
|
-
width: number;
|
|
18
|
-
height: number;
|
|
19
|
-
beginPath?: boolean;
|
|
20
|
-
style?: RCXStyleProp<RCXShapeStyle>;
|
|
21
|
-
}>;
|
|
22
|
-
|
|
23
|
-
export const Rectangle: RCXComponent<RectangleProps> = (props) => {
|
|
24
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
25
|
-
const { x, y, width, height, beginPath = true } = props;
|
|
26
|
-
|
|
27
|
-
renderingContext.ctx2d.save();
|
|
28
|
-
|
|
29
|
-
if (beginPath) {
|
|
30
|
-
renderingContext.ctx2d.beginPath();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
renderingContext.ctx2d.rect(x, y, width, height);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
useRenderAfterChildren((renderingContext) => {
|
|
37
|
-
applyFillAndStrokeStyles(renderingContext, resolveStyles(props.style));
|
|
38
|
-
|
|
39
|
-
renderingContext.ctx2d.restore();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return props.children;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
Rectangle.displayName = 'Rectangle';
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { useRenderBeforeChildren } from '../../hooks/use-render.ts';
|
|
2
|
-
import type {
|
|
3
|
-
RCXChildren,
|
|
4
|
-
RCXComponent,
|
|
5
|
-
RCXFontStyle,
|
|
6
|
-
RCXPropsWithChildren,
|
|
7
|
-
RCXShapeStyle,
|
|
8
|
-
RCXStyleProp,
|
|
9
|
-
} from '../../types.ts';
|
|
10
|
-
import { isValidFillOrStrokeStyle } from '../../utils/is-valid-fill-or-stroke-style.ts';
|
|
11
|
-
import { isValidStrokeCap } from '../../utils/is-valid-stroke-cap.ts';
|
|
12
|
-
import { isValidStrokeJoin } from '../../utils/is-valid-stroke-join.ts';
|
|
13
|
-
import { resolveStyles } from '../../utils/resolve-styles.ts';
|
|
14
|
-
import { isArray } from '../../utils/type-guards.ts';
|
|
15
|
-
import { withPx } from '../../utils/with-px.ts';
|
|
16
|
-
|
|
17
|
-
export interface TextStyle extends RCXShapeStyle, RCXFontStyle {
|
|
18
|
-
align?: CanvasTextAlign;
|
|
19
|
-
baseline?: CanvasTextBaseline;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type TextProps = RCXPropsWithChildren<{
|
|
23
|
-
x: number;
|
|
24
|
-
y: number;
|
|
25
|
-
maxWidth?: number;
|
|
26
|
-
children?: RCXChildren;
|
|
27
|
-
style?: RCXStyleProp<TextStyle>;
|
|
28
|
-
}>;
|
|
29
|
-
|
|
30
|
-
const DEFAULT_FONT_STYLE = {
|
|
31
|
-
// font string
|
|
32
|
-
fontStyle: 'normal',
|
|
33
|
-
fontWeight: 'normal',
|
|
34
|
-
fontSize: 10,
|
|
35
|
-
fontFamily: 'sans-serif',
|
|
36
|
-
// other ctx2d properties
|
|
37
|
-
fontStretch: 'normal',
|
|
38
|
-
fontVariant: 'normal',
|
|
39
|
-
fontKerning: 'normal',
|
|
40
|
-
} satisfies Required<RCXFontStyle>;
|
|
41
|
-
|
|
42
|
-
const getTextFromChildren = (children: RCXChildren): string => {
|
|
43
|
-
if (
|
|
44
|
-
children === null ||
|
|
45
|
-
typeof children === 'boolean' ||
|
|
46
|
-
typeof children === 'undefined'
|
|
47
|
-
) {
|
|
48
|
-
return '';
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (typeof children === 'object') {
|
|
52
|
-
if (isArray(children)) {
|
|
53
|
-
return children.reduce<string>(
|
|
54
|
-
(acc, child) => acc + getTextFromChildren(child),
|
|
55
|
-
''
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return getTextFromChildren(children.props.children);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return children.toString();
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const Text: RCXComponent<TextProps> = (props) => {
|
|
66
|
-
useRenderBeforeChildren((renderingContext) => {
|
|
67
|
-
const { x, y, maxWidth, children } = props;
|
|
68
|
-
const {
|
|
69
|
-
fill,
|
|
70
|
-
stroke,
|
|
71
|
-
strokeWidth,
|
|
72
|
-
strokeCap,
|
|
73
|
-
strokeJoin,
|
|
74
|
-
align,
|
|
75
|
-
baseline,
|
|
76
|
-
fontStyle = DEFAULT_FONT_STYLE.fontStyle,
|
|
77
|
-
fontWeight = DEFAULT_FONT_STYLE.fontWeight,
|
|
78
|
-
fontSize = DEFAULT_FONT_STYLE.fontSize,
|
|
79
|
-
fontFamily = DEFAULT_FONT_STYLE.fontFamily,
|
|
80
|
-
// other ctx2d properties
|
|
81
|
-
fontStretch = DEFAULT_FONT_STYLE.fontStretch,
|
|
82
|
-
fontVariant = DEFAULT_FONT_STYLE.fontVariant,
|
|
83
|
-
fontKerning = DEFAULT_FONT_STYLE.fontKerning,
|
|
84
|
-
} = resolveStyles(props.style);
|
|
85
|
-
|
|
86
|
-
const text = getTextFromChildren(children);
|
|
87
|
-
|
|
88
|
-
renderingContext.ctx2d.save();
|
|
89
|
-
|
|
90
|
-
if (typeof align === 'string') {
|
|
91
|
-
renderingContext.ctx2d.textAlign = align;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (typeof baseline === 'string') {
|
|
95
|
-
renderingContext.ctx2d.textBaseline = baseline;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
renderingContext.ctx2d.font = [
|
|
99
|
-
fontStyle,
|
|
100
|
-
fontWeight,
|
|
101
|
-
withPx(fontSize),
|
|
102
|
-
fontFamily,
|
|
103
|
-
].join(' ');
|
|
104
|
-
|
|
105
|
-
renderingContext.ctx2d.fontStretch = fontStretch;
|
|
106
|
-
renderingContext.ctx2d.fontVariantCaps = fontVariant;
|
|
107
|
-
renderingContext.ctx2d.fontKerning = fontKerning;
|
|
108
|
-
|
|
109
|
-
if (isValidFillOrStrokeStyle(fill)) {
|
|
110
|
-
renderingContext.ctx2d.fillStyle = fill;
|
|
111
|
-
renderingContext.ctx2d.fillText(text, x, y, maxWidth);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (typeof strokeWidth === 'number') {
|
|
115
|
-
renderingContext.ctx2d.lineWidth = strokeWidth;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (isValidStrokeCap(strokeCap)) {
|
|
119
|
-
renderingContext.ctx2d.lineCap = strokeCap;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (isValidStrokeJoin(strokeJoin)) {
|
|
123
|
-
renderingContext.ctx2d.lineJoin = strokeJoin;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (isValidFillOrStrokeStyle(stroke)) {
|
|
127
|
-
renderingContext.ctx2d.strokeStyle = stroke;
|
|
128
|
-
renderingContext.ctx2d.strokeText(text, x, y, maxWidth);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
renderingContext.ctx2d.restore();
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
return null;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
Text.displayName = 'Text';
|