pixedi 1.0.0 → 1.0.2

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 (113) hide show
  1. package/README.md +65 -60
  2. package/README.npm.md +80 -0
  3. package/dist/lib/index.js +1602 -0
  4. package/dist/lib/index.umd.js +28 -0
  5. package/package.json +9 -4
  6. package/.github/workflows/deploy.yml +0 -54
  7. package/.prettierr +0 -9
  8. package/.storybook/main.ts +0 -16
  9. package/.storybook/preview.ts +0 -53
  10. package/.vscode/extensions.json +0 -6
  11. package/eslint.config.js +0 -22
  12. package/index.html +0 -13
  13. package/pnpm-workspace.yaml +0 -2
  14. package/public/favicon.svg +0 -1
  15. package/src/app/App.tsx +0 -10
  16. package/src/app/entries/index.ts +0 -145
  17. package/src/app/providers/RouterProvider.tsx +0 -6
  18. package/src/app/providers/index.ts +0 -1
  19. package/src/app/router/AppRouter.tsx +0 -12
  20. package/src/app/router/index.ts +0 -0
  21. package/src/app/styles/index.css +0 -4
  22. package/src/features/gallery/GalleryPage.tsx +0 -33
  23. package/src/features/gallery/ImageEditPage.tsx +0 -37
  24. package/src/features/gallery/index.ts +0 -2
  25. package/src/main.tsx +0 -10
  26. package/src/shared/components/ImageCard/ImageCard.tsx +0 -54
  27. package/src/shared/components/ImageCard/index.ts +0 -1
  28. package/src/shared/components/ImageEditor/ImageEditor.tsx +0 -48
  29. package/src/shared/components/ImageEditor/assets/icons.tsx +0 -114
  30. package/src/shared/components/ImageEditor/constants.ts +0 -118
  31. package/src/shared/components/ImageEditor/crop/Crop.tsx +0 -60
  32. package/src/shared/components/ImageEditor/crop/CropBorders.tsx +0 -28
  33. package/src/shared/components/ImageEditor/crop/CropLines.tsx +0 -8
  34. package/src/shared/components/ImageEditor/crop/CropPointer.tsx +0 -21
  35. package/src/shared/components/ImageEditor/crop/CropPointers.tsx +0 -44
  36. package/src/shared/components/ImageEditor/crop/CropTools.tsx +0 -138
  37. package/src/shared/components/ImageEditor/crop/crop.css +0 -180
  38. package/src/shared/components/ImageEditor/crop/index.ts +0 -8
  39. package/src/shared/components/ImageEditor/crop/useCropInteraction.ts +0 -230
  40. package/src/shared/components/ImageEditor/eventBus.ts +0 -8
  41. package/src/shared/components/ImageEditor/frame/Frame.tsx +0 -48
  42. package/src/shared/components/ImageEditor/frame/frame.css +0 -40
  43. package/src/shared/components/ImageEditor/frame/index.ts +0 -1
  44. package/src/shared/components/ImageEditor/header/Header.tsx +0 -81
  45. package/src/shared/components/ImageEditor/header/header.css +0 -27
  46. package/src/shared/components/ImageEditor/header/index.ts +0 -1
  47. package/src/shared/components/ImageEditor/hooks/index.ts +0 -5
  48. package/src/shared/components/ImageEditor/hooks/useAbove.tsx +0 -18
  49. package/src/shared/components/ImageEditor/hooks/useBellow.tsx +0 -18
  50. package/src/shared/components/ImageEditor/hooks/useImageLoader.tsx +0 -110
  51. package/src/shared/components/ImageEditor/hooks/useImageProcessor.test.tsx +0 -147
  52. package/src/shared/components/ImageEditor/hooks/useImageProcessor.ts +0 -225
  53. package/src/shared/components/ImageEditor/hooks/useMobile.tsx +0 -33
  54. package/src/shared/components/ImageEditor/index.css +0 -145
  55. package/src/shared/components/ImageEditor/index.ts +0 -1
  56. package/src/shared/components/ImageEditor/provider/ImageEditorProvider.test.tsx +0 -126
  57. package/src/shared/components/ImageEditor/provider/ImageEditorProvider.tsx +0 -107
  58. package/src/shared/components/ImageEditor/provider/StoreContext.tsx +0 -20
  59. package/src/shared/components/ImageEditor/provider/initialState.ts +0 -30
  60. package/src/shared/components/ImageEditor/provider/useImageEditorContext.tsx +0 -12
  61. package/src/shared/components/ImageEditor/resize/ResizeTools.tsx +0 -183
  62. package/src/shared/components/ImageEditor/resize/index.ts +0 -1
  63. package/src/shared/components/ImageEditor/resize/resize.css +0 -56
  64. package/src/shared/components/ImageEditor/sidebar/Sidebar.tsx +0 -54
  65. package/src/shared/components/ImageEditor/sidebar/SidebarCrop.tsx +0 -57
  66. package/src/shared/components/ImageEditor/sidebar/SidebarPresets.tsx +0 -54
  67. package/src/shared/components/ImageEditor/sidebar/SidebarResize.tsx +0 -26
  68. package/src/shared/components/ImageEditor/sidebar/index.ts +0 -1
  69. package/src/shared/components/ImageEditor/sidebar/sidebar.css +0 -101
  70. package/src/shared/components/ImageEditor/types.ts +0 -59
  71. package/src/shared/components/ImageEditor/ui/button/Button.stories.tsx +0 -42
  72. package/src/shared/components/ImageEditor/ui/button/Button.tsx +0 -21
  73. package/src/shared/components/ImageEditor/ui/button/button.css +0 -69
  74. package/src/shared/components/ImageEditor/ui/button-crop/ButtonCrop.stories.tsx +0 -26
  75. package/src/shared/components/ImageEditor/ui/button-crop/ButtonCrop.tsx +0 -29
  76. package/src/shared/components/ImageEditor/ui/button-crop/button-crop.css +0 -38
  77. package/src/shared/components/ImageEditor/ui/index.ts +0 -6
  78. package/src/shared/components/ImageEditor/ui/input/Input.stories.tsx +0 -45
  79. package/src/shared/components/ImageEditor/ui/input/Input.tsx +0 -20
  80. package/src/shared/components/ImageEditor/ui/input/input.css +0 -48
  81. package/src/shared/components/ImageEditor/ui/input-pixel/InputPixel.stories.tsx +0 -33
  82. package/src/shared/components/ImageEditor/ui/input-pixel/InputPixel.tsx +0 -23
  83. package/src/shared/components/ImageEditor/ui/input-pixel/input-pixel.css +0 -24
  84. package/src/shared/components/ImageEditor/ui/select/Select.stories.tsx +0 -67
  85. package/src/shared/components/ImageEditor/ui/select/Select.tsx +0 -161
  86. package/src/shared/components/ImageEditor/ui/select/select.css +0 -147
  87. package/src/shared/components/ImageEditor/ui/separator/Separator.stories.tsx +0 -37
  88. package/src/shared/components/ImageEditor/ui/separator/Separator.tsx +0 -27
  89. package/src/shared/components/ImageEditor/ui/separator/separator.css +0 -19
  90. package/src/shared/components/ImageEditor/utils.test.ts +0 -136
  91. package/src/shared/components/ImageEditor/utils.ts +0 -497
  92. package/src/shared/components/ui/index.ts +0 -1
  93. package/src/shared/components/ui/preloader.tsx +0 -78
  94. package/src/shared/config/index.ts +0 -3
  95. package/src/shared/config/routes.ts +0 -4
  96. package/src/shared/features/gallery/GalleryPage.tsx +0 -33
  97. package/src/shared/features/gallery/ImageEditPage.tsx +0 -37
  98. package/src/shared/features/gallery/index.ts +0 -2
  99. package/src/shared/hooks/index.ts +0 -1
  100. package/src/shared/hooks/useImagePreload.tsx +0 -49
  101. package/src/shared/types/index.ts +0 -11
  102. package/src/test/setup.ts +0 -14
  103. package/src/virtual-css-injected-by-js.d.ts +0 -8
  104. package/src/widget.tsx +0 -119
  105. package/tsconfig.app.json +0 -29
  106. package/tsconfig.json +0 -12
  107. package/tsconfig.lib.json +0 -18
  108. package/tsconfig.node.json +0 -23
  109. package/vite-env.d.ts +0 -1
  110. package/vite.config.ts +0 -24
  111. package/vite.lib.config.ts +0 -33
  112. package/vite.widget.config.ts +0 -39
  113. package/wrangler.json +0 -5
@@ -1,33 +0,0 @@
1
- import { imagesData } from "@/app/entries";
2
- import { ImageCard } from "@/shared/components/ImageCard";
3
- import { Preloader } from "@/shared/components/ui";
4
- import { useImagePreload } from "@/shared/hooks";
5
-
6
- export const GalleryPage = () => {
7
- const isLoaded = useImagePreload(imagesData.map((image) => image.original));
8
-
9
- if (!isLoaded) {
10
- return (
11
- <div className="w-full min-h-screen flex items-center justify-center">
12
- <Preloader size={64} />
13
- </div>
14
- );
15
- }
16
-
17
- return (
18
- <div
19
- className={`
20
- max-w-4xl mx-6
21
- my-6
22
- grid content-start gap-6
23
- grid-cols-1
24
- sm:grid-cols-2
25
- md:grid-cols-3 md:mx-auto
26
- `}
27
- >
28
- {imagesData.map((image) => (
29
- <ImageCard key={image.id} image={image} />
30
- ))}
31
- </div>
32
- );
33
- };
@@ -1,37 +0,0 @@
1
- import { useParams, useNavigate } from "react-router";
2
- import { imagesData } from "@/app/entries";
3
- import { ImageEditor } from "@/shared/components/ImageEditor";
4
-
5
- export const ImageEditPage = () => {
6
- const navigate = useNavigate();
7
- const { id } = useParams<{ id: string }>();
8
- const image = imagesData.find((img) => img.id === id);
9
-
10
- if (!image) {
11
- return <div>Image not found</div>;
12
- }
13
-
14
- const handleSave = async (base64: string) => {
15
- return new Promise<void>((resolve) => {
16
- setTimeout(() => {
17
- // TODO: Save the image
18
- console.log(base64);
19
- resolve();
20
- }, 2000);
21
- });
22
- };
23
-
24
- const handleCancel = () => {
25
- navigate("/");
26
- };
27
-
28
- return (
29
- <div className="w-full h-screen">
30
- <ImageEditor
31
- image={image.original}
32
- onBack={handleCancel}
33
- onSave={handleSave}
34
- />
35
- </div>
36
- );
37
- };
@@ -1,2 +0,0 @@
1
- export { GalleryPage } from "./GalleryPage";
2
- export { ImageEditPage } from "./ImageEditPage";
@@ -1 +0,0 @@
1
- export { useImagePreload } from "./useImagePreload";
@@ -1,49 +0,0 @@
1
- import { useState, useEffect } from "react";
2
-
3
- export function useImagePreload(
4
- imageUrls: string[],
5
- delay: number = 1000,
6
- ): boolean {
7
- const [loadedUrls, setLoadedUrls] = useState<string[]>([]);
8
-
9
- const isAlreadyLoaded =
10
- imageUrls.length === loadedUrls.length &&
11
- imageUrls.every((url, i) => url === loadedUrls[i]);
12
-
13
- useEffect(() => {
14
- if (imageUrls.length === 0 || isAlreadyLoaded) {
15
- return;
16
- }
17
-
18
- let isMounted = true;
19
-
20
- const minimumDelayPromise = new Promise((resolve) =>
21
- setTimeout(resolve, delay),
22
- );
23
-
24
- const imagePromises = imageUrls.map((src) => {
25
- return new Promise<void>((resolve) => {
26
- const img = new Image();
27
- img.src = src;
28
- img.onload = () => resolve();
29
- img.onerror = () => resolve();
30
- });
31
- });
32
-
33
- Promise.all([...imagePromises, minimumDelayPromise]).then(() => {
34
- if (isMounted) {
35
- setLoadedUrls(imageUrls);
36
- }
37
- });
38
-
39
- return () => {
40
- isMounted = false;
41
- };
42
- }, [imageUrls, isAlreadyLoaded]);
43
-
44
- if (imageUrls.length === 0) {
45
- return true;
46
- }
47
-
48
- return isAlreadyLoaded;
49
- }
@@ -1,11 +0,0 @@
1
- export type Image = {
2
- id: string;
3
- author: string;
4
- title: string;
5
- width: number;
6
- height: number;
7
- ext: string;
8
- fileName: string;
9
- thumbnail: string;
10
- original: string;
11
- };
package/src/test/setup.ts DELETED
@@ -1,14 +0,0 @@
1
- import "@testing-library/jest-dom/vitest";
2
- import { vi } from "vitest";
3
-
4
- vi.stubGlobal("createImageBitmap", vi.fn());
5
- vi.spyOn(HTMLCanvasElement.prototype, "getContext").mockReturnValue(null);
6
- vi.spyOn(HTMLCanvasElement.prototype, "toDataURL").mockReturnValue("");
7
-
8
- if (!globalThis.ImageBitmap) {
9
- class ImageBitmapMock {
10
- close() {}
11
- }
12
-
13
- vi.stubGlobal("ImageBitmap", ImageBitmapMock);
14
- }
@@ -1,8 +0,0 @@
1
- declare module "virtual:css-injected-by-js" {
2
- interface CSSInjectionOptions {
3
- target?: HTMLElement | ShadowRoot;
4
- }
5
-
6
- export function injectCSS(options?: CSSInjectionOptions): void;
7
- export function removeCSS(options?: CSSInjectionOptions): void;
8
- }
package/src/widget.tsx DELETED
@@ -1,119 +0,0 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom/client";
3
- import { injectCSS, removeCSS } from "virtual:css-injected-by-js";
4
- import type { FuncSaveArgs } from "@/shared/components/ImageEditor/types";
5
- import { ImageEditor } from "@/shared/components/ImageEditor";
6
-
7
- type WidgetTheme = "light" | "dark";
8
-
9
- interface WidgetOptions {
10
- containerId: string;
11
- image: string;
12
- onSave: FuncSaveArgs;
13
- onBack: () => void;
14
- theme?: WidgetTheme;
15
- }
16
-
17
- interface ImageEditorWidgetInstance {
18
- destroy: () => void;
19
- }
20
-
21
- interface ImageEditorWidget {
22
- init: (options: WidgetOptions) => ImageEditorWidgetInstance | undefined;
23
- }
24
-
25
- interface ActiveWidget {
26
- root: ReactDOM.Root;
27
- shadowRoot: ShadowRoot;
28
- mountElement: HTMLDivElement;
29
- container: HTMLElement;
30
- previousTheme: string | null;
31
- }
32
-
33
- declare global {
34
- interface Window {
35
- ImageEditorWidget?: ImageEditorWidget;
36
- }
37
- }
38
-
39
- let activeWidget: ActiveWidget | null = null;
40
-
41
- const destroyActiveWidget = () => {
42
- if (!activeWidget) {
43
- return;
44
- }
45
-
46
- activeWidget.root.unmount();
47
- removeCSS({ target: activeWidget.shadowRoot });
48
- activeWidget.mountElement.remove();
49
-
50
- if (activeWidget.previousTheme === null) {
51
- activeWidget.container.removeAttribute("data-theme");
52
- } else {
53
- activeWidget.container.setAttribute(
54
- "data-theme",
55
- activeWidget.previousTheme,
56
- );
57
- }
58
-
59
- activeWidget = null;
60
- };
61
-
62
- const ImageEditorWidget: ImageEditorWidget = {
63
- init: (options) => {
64
- const container = document.getElementById(options.containerId);
65
- if (!container) return;
66
-
67
- destroyActiveWidget();
68
-
69
- let shadowRoot = container.shadowRoot;
70
- if (!shadowRoot) {
71
- try {
72
- shadowRoot = container.attachShadow({ mode: "open" });
73
- } catch {
74
- return;
75
- }
76
- }
77
-
78
- const previousTheme = container.getAttribute("data-theme");
79
- container.setAttribute("data-theme", options.theme ?? "light");
80
-
81
- injectCSS({ target: shadowRoot });
82
-
83
- const mountElement = document.createElement("div");
84
- shadowRoot.append(mountElement);
85
-
86
- const root = ReactDOM.createRoot(mountElement);
87
- activeWidget = {
88
- root,
89
- shadowRoot,
90
- mountElement,
91
- container,
92
- previousTheme,
93
- };
94
-
95
- root.render(
96
- <React.StrictMode>
97
- <ImageEditor
98
- image={options.image}
99
- onSave={options.onSave}
100
- onBack={options.onBack}
101
- />
102
- </React.StrictMode>,
103
- );
104
-
105
- return {
106
- destroy: () => {
107
- if (activeWidget?.root === root) {
108
- destroyActiveWidget();
109
- }
110
- },
111
- };
112
- },
113
- };
114
-
115
- if (typeof window !== "undefined") {
116
- window.ImageEditorWidget = ImageEditorWidget;
117
- }
118
-
119
- export default ImageEditorWidget;
package/tsconfig.app.json DELETED
@@ -1,29 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
- "target": "es2023",
5
- "lib": ["ES2023", "DOM"],
6
- "module": "esnext",
7
- "types": ["vite/client"],
8
- "skipLibCheck": true,
9
-
10
- /* Bundler mode */
11
- "moduleResolution": "bundler",
12
- "allowImportingTsExtensions": true,
13
- "verbatimModuleSyntax": true,
14
- "moduleDetection": "force",
15
- "noEmit": true,
16
- "jsx": "react-jsx",
17
-
18
- /* Linting */
19
- "noUnusedLocals": true,
20
- "noUnusedParameters": true,
21
- "erasableSyntaxOnly": true,
22
- "noFallthroughCasesInSwitch": true,
23
-
24
- "paths": {
25
- "@/*": ["./src/*"]
26
- }
27
- },
28
- "include": ["src"]
29
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "files": [],
3
- "references": [
4
- { "path": "./tsconfig.app.json" },
5
- { "path": "./tsconfig.node.json" }
6
- ],
7
- "compilerOptions": {
8
- "paths": {
9
- "@/*": ["./src/*"]
10
- }
11
- }
12
- }
package/tsconfig.lib.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "extends": "./tsconfig.app.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "emitDeclarationOnly": true,
6
- "outDir": "./dist/lib",
7
- "rootDir": "."
8
- },
9
- "include": ["src/shared/components/ImageEditor/**/*"],
10
- "exclude": [
11
- "src/shared/components/ImageEditor/**/*.stories.tsx",
12
- "src/shared/components/ImageEditor/**/*.stories.ts",
13
- "src/shared/components/ImageEditor/**/*.test.tsx",
14
- "src/shared/components/ImageEditor/**/*.test.ts",
15
- "src/shared/components/ImageEditor/**/*.spec.tsx",
16
- "src/shared/components/ImageEditor/**/*.spec.ts"
17
- ]
18
- }
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
- "target": "es2023",
5
- "lib": ["ES2023"],
6
- "types": ["node"],
7
- "skipLibCheck": true,
8
-
9
- /* Bundler mode */
10
- "module": "nodenext",
11
- "allowImportingTsExtensions": true,
12
- "verbatimModuleSyntax": true,
13
- "moduleDetection": "force",
14
- "noEmit": true,
15
-
16
- /* Linting */
17
- "noUnusedLocals": true,
18
- "noUnusedParameters": true,
19
- "erasableSyntaxOnly": true,
20
- "noFallthroughCasesInSwitch": true
21
- },
22
- "include": ["vite.config.ts"]
23
- }
package/vite-env.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />
package/vite.config.ts DELETED
@@ -1,24 +0,0 @@
1
- import path from "path";
2
- import { defineConfig } from "vitest/config";
3
- import react from "@vitejs/plugin-react";
4
-
5
- // https://vite.dev/config/
6
- export default defineConfig({
7
- plugins: [react()],
8
- server: {
9
- port: 3000,
10
- },
11
- resolve: {
12
- alias: {
13
- "@": path.resolve(__dirname, "./src"),
14
- },
15
- },
16
- build: {
17
- outDir: "dist/app",
18
- minify: true,
19
- },
20
- test: {
21
- environment: "jsdom",
22
- setupFiles: ["./src/test/setup.ts"],
23
- },
24
- });
@@ -1,33 +0,0 @@
1
- import path from "path";
2
- import { defineConfig } from "vite";
3
- import react from "@vitejs/plugin-react";
4
- import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
5
-
6
- export default defineConfig({
7
- plugins: [react(), cssInjectedByJsPlugin()],
8
- publicDir: false,
9
- resolve: {
10
- alias: {
11
- "@": path.resolve(__dirname, "./src"),
12
- },
13
- },
14
- build: {
15
- outDir: "dist/lib",
16
- emptyOutDir: false,
17
- lib: {
18
- entry: "src/shared/components/ImageEditor/ImageEditor.tsx",
19
- name: "Pixedi",
20
- fileName: (format) => `index.${format === "es" ? "js" : "umd.js"}`,
21
- formats: ["es", "umd"],
22
- },
23
- rollupOptions: {
24
- external: ["react", "react-dom"],
25
- output: {
26
- globals: {
27
- react: "React",
28
- "react-dom": "ReactDOM",
29
- },
30
- },
31
- },
32
- },
33
- });
@@ -1,39 +0,0 @@
1
- import path from "path";
2
- import { defineConfig } from "vite";
3
- import react from "@vitejs/plugin-react";
4
- import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
5
-
6
- export default defineConfig({
7
- plugins: [
8
- react(),
9
- cssInjectedByJsPlugin({
10
- attributes: { "data-image-editor-widget": "" },
11
- }),
12
- ],
13
- publicDir: false,
14
- define: {
15
- "process.env.NODE_ENV": '"production"',
16
- },
17
- resolve: {
18
- alias: {
19
- "@": path.resolve(__dirname, "./src"),
20
- },
21
- },
22
- build: {
23
- outDir: "dist/widget",
24
- emptyOutDir: false,
25
- minify: "oxc",
26
- lib: {
27
- entry: "src/widget.tsx",
28
- name: "ImageEditorWidget",
29
- formats: ["umd"],
30
- },
31
- rolldownOptions: {
32
- output: {
33
- comments: { legal: false },
34
- entryFileNames: "pixedi-widget.js",
35
- assetFileNames: "[name].[ext]",
36
- },
37
- },
38
- },
39
- });
package/wrangler.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "$schema": "node_modules/wrangler/config-schema.json",
3
- "name": "pixedi",
4
- "pages_build_output_dir": "dist"
5
- }