create-weave-frontend-app 0.21.1 → 0.21.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.
@@ -76,11 +76,11 @@ function tryGitInit(root) {
76
76
  //#endregion
77
77
  //#region src/versions.js
78
78
  const versions = {
79
- "@inditextech/weave-types": "0.21.1",
80
- "@inditextech/weave-sdk": "0.21.1",
81
- "@inditextech/weave-store-websockets": "0.21.1",
82
- "@inditextech/weave-store-azure-web-pubsub": "0.21.1",
83
- "@inditextech/weave-react": "0.21.1"
79
+ "@inditextech/weave-types": "0.21.2",
80
+ "@inditextech/weave-sdk": "0.21.2",
81
+ "@inditextech/weave-store-websockets": "0.21.2",
82
+ "@inditextech/weave-store-azure-web-pubsub": "0.21.2",
83
+ "@inditextech/weave-react": "0.21.2"
84
84
  };
85
85
 
86
86
  //#endregion
@@ -431,4 +431,4 @@ function pick(obj, keys) {
431
431
 
432
432
  //#endregion
433
433
  export { create, cwd, getPackageManager };
434
- //# sourceMappingURL=create-app-C1gmYK6w.js.map
434
+ //# sourceMappingURL=create-app-CekXcOg7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-app-C1gmYK6w.js","names":["cwd: string","root: string","manager: PackageManager","dest: string","options: Options","file: string","dest: string","projectName: string","from: string","to: string","rename: (s: string) => string","obj: T","keys: K[]","result: Partial<T>"],"sources":["../src/git.ts","../src/versions.js","../template/package.json","../src/auto-install.ts","../src/constants.ts","../src/create-app.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/*\nInitialize a Git repo on the project.\n\nBased on https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/git.ts\n*/\n\nfunction isInGitRepository(cwd: string): boolean {\n try {\n execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isInMercurialRepository(cwd: string): boolean {\n try {\n execSync('hg --cwd . root', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isDefaultBranchSet(cwd: string): boolean {\n try {\n execSync('git config init.defaultBranch', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function tryGitInit(root: string): boolean {\n let didInit = false;\n\n try {\n execSync('git --version', { stdio: 'ignore' });\n if (isInGitRepository(root) || isInMercurialRepository(root)) {\n return false;\n }\n\n execSync('git init', { stdio: 'ignore', cwd: root });\n didInit = true;\n\n if (!isDefaultBranchSet(root)) {\n execSync('git checkout -b main', { stdio: 'ignore', cwd: root });\n }\n\n execSync('git add -A', { stdio: 'ignore', cwd: root });\n execSync('git commit -m \"Initial commit from Create Fumadocs App\"', {\n stdio: 'ignore',\n cwd: root,\n });\n return true;\n } catch {\n if (didInit) {\n try {\n rmSync(join(root, '.git'), { recursive: true, force: true });\n } catch {\n // do nothing\n }\n }\n\n return false;\n }\n}\n","export const versions = {\"@inditextech/weave-types\":\"0.21.1\",\"@inditextech/weave-sdk\":\"0.21.1\",\"@inditextech/weave-store-websockets\":\"0.21.1\",\"@inditextech/weave-store-azure-web-pubsub\":\"0.21.1\",\"@inditextech/weave-react\":\"0.21.1\"}","{\n \"name\": \"example-versions\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"description\": \"Used to track dependency versions in create-*-app\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@hookform/resolvers\": \"^4.1.3\",\n \"@inditextech/weave-react\": \"0.0.0\",\n \"@inditextech/weave-sdk\": \"0.0.0\",\n \"@inditextech/weave-store-websockets\": \"0.0.0\",\n \"@inditextech/weave-store-azure-web-pubsub\": \"0.0.0\",\n \"@next/env\": \"^15.2.1\",\n \"@radix-ui/react-accordion\": \"^1.2.3\",\n \"@radix-ui/react-avatar\": \"^1.1.3\",\n \"@radix-ui/react-checkbox\": \"^1.1.4\",\n \"@radix-ui/react-dialog\": \"^1.1.6\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.6\",\n \"@radix-ui/react-label\": \"^2.1.2\",\n \"@radix-ui/react-popover\": \"^1.1.6\",\n \"@radix-ui/react-scroll-area\": \"^1.2.3\",\n \"@radix-ui/react-select\": \"^2.1.6\",\n \"@radix-ui/react-slider\": \"^1.2.3\",\n \"@radix-ui/react-slot\": \"^1.1.2\",\n \"@radix-ui/react-tabs\": \"^1.1.3\",\n \"@radix-ui/react-tooltip\": \"^1.1.8\",\n \"@react-three/fiber\": \"^8.18.0\",\n \"@react-three/postprocessing\": \"^2.19.1\",\n \"@tanstack/react-query\": \"^5.67.1\",\n \"boring-avatars\": \"^1.11.2\",\n \"change-case\": \"^5.4.4\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cmdk\": \"^1.0.0\",\n \"color\": \"^5.0.0\",\n \"framer-motion\": \"^11.18.2\",\n \"konva\": \"^9.3.18\",\n \"motion\": \"^12.4.7\",\n \"next\": \"14.2.28\",\n \"next-themes\": \"^0.4.6\",\n \"ogl\": \"^1.0.11\",\n \"onnxruntime-web\": \"^1.21.0-dev.20250206-d981b153d3\",\n \"pdf-lib\": \"^1.17.1\",\n \"platform-detect\": \"^3.0.1\",\n \"postprocessing\": \"^6.37.1\",\n \"react\": \"18.2.0\",\n \"react-dom\": \"18.2.0\",\n \"react-hook-form\": \"^7.54.2\",\n \"react-number-format\": \"^5.4.3\",\n \"sharp\": \"^0.33.5\",\n \"sonner\": \"^2.0.3\",\n \"tailwind-merge\": \"^3.0.2\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"three\": \"^0.167.1\",\n \"uuid\": \"^11.1.0\",\n \"vaul\": \"^1.1.2\",\n \"zod\": \"^3.24.2\",\n \"zustand\": \"^5.0.3\"\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"^3\",\n \"@tailwindcss/postcss\": \"^4\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^20\",\n \"@types/react\": \"^18\",\n \"@types/react-dom\": \"^18\",\n \"@vitejs/plugin-react\": \"^4.3.4\",\n \"@vitest/coverage-v8\": \"^3.0.7\",\n \"eslint\": \"^8\",\n \"eslint-config-next\": \"14.2.24\",\n \"eslint-config-prettier\": \"^10.0.2\",\n \"jsdom\": \"^26.0.0\",\n \"lucide-react\": \"^0.477.0\",\n \"tailwindcss\": \"^4\",\n \"typescript\": \"^5\",\n \"vite-tsconfig-paths\": \"^5.1.4\",\n \"vitest\": \"^3.0.7\"\n }\n}\n","import { spawn } from 'cross-spawn';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nexport function getPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent ?? '';\n\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n }\n\n if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n }\n\n if (userAgent.startsWith('bun')) {\n return 'bun';\n }\n\n return 'npm';\n}\n\nexport function autoInstall(\n manager: PackageManager,\n dest: string,\n): Promise<void> {\n return new Promise((res, reject) => {\n const installProcess = spawn(manager, ['install'], {\n stdio: 'ignore',\n env: {\n ...process.env,\n NODE_ENV: 'development',\n DISABLE_OPENCOLLECTIVE: '1',\n },\n cwd: dest,\n });\n\n installProcess.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Install failed'));\n } else {\n res();\n }\n });\n });\n}\n","import { fileURLToPath } from 'node:url';\n\nexport const sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);\nexport const cwd = process.cwd();\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { tryGitInit } from '@/git';\nimport { versions as localVersions } from '@/versions';\nimport versionPkg from './../template/package.json';\nimport type { PackageManager } from './auto-install';\nimport { autoInstall } from './auto-install';\nimport { cwd, sourceDir } from './constants';\n\nexport type Template = '+nextjs+websockets' | '+nextjs+azure-web-pubsub';\n\nexport interface Options {\n outputDir: string;\n template: Template;\n packageManager: PackageManager;\n installDeps?: boolean;\n initializeGit?: boolean;\n log?: (message: string) => void;\n}\n\nexport async function create(options: Options): Promise<void> {\n const {\n installDeps = true,\n initializeGit = true,\n log = console.log,\n } = options;\n const projectName = path.basename(options.outputDir);\n const dest = path.resolve(cwd, options.outputDir);\n\n function defaultRename(file: string): string {\n file = file.replace('example.gitignore', '.gitignore');\n file = file.replace('example.env', '.env');\n\n return file;\n }\n\n await copy(\n path.join(sourceDir, `template/${options.template}`),\n dest,\n defaultRename\n );\n\n const packageJson = createPackageJson(projectName, options);\n await fs.writeFile(\n path.join(dest, 'package.json'),\n JSON.stringify(packageJson, null, 2)\n );\n\n const readMe = await getReadme(dest, projectName);\n await fs.writeFile(path.join(dest, 'README.md'), readMe);\n\n if (installDeps) {\n await autoInstall(options.packageManager, dest);\n log('Installed dependencies');\n }\n\n if (initializeGit && tryGitInit(dest)) {\n log('Initialized Git repository');\n }\n}\n\nasync function getReadme(dest: string, projectName: string): Promise<string> {\n const template = await fs\n .readFile(path.join(dest, 'README.md'))\n .then((res) => res.toString());\n\n return `# ${projectName}\\n\\n${template}`;\n}\n\nasync function copy(\n from: string,\n to: string,\n rename: (s: string) => string = (s) => s\n): Promise<void> {\n const stats = await fs.stat(from);\n\n if (stats.isDirectory()) {\n const files = await fs.readdir(from);\n\n await Promise.all(\n files.map((file) =>\n copy(path.join(from, file), rename(path.join(to, file)))\n )\n );\n } else {\n await fs.mkdir(path.dirname(to), { recursive: true });\n await fs.copyFile(from, to);\n }\n}\n\nfunction createPackageJson(projectName: string, options: Options): object {\n if (options.template === '+nextjs+azure-web-pubsub') {\n const dependencies = {\n ...pick(versionPkg.dependencies, [\n '@hookform/resolvers',\n '@next/env',\n '@radix-ui/react-accordion',\n '@radix-ui/react-avatar',\n '@radix-ui/react-checkbox',\n '@radix-ui/react-dialog',\n '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-label',\n '@radix-ui/react-popover',\n '@radix-ui/react-scroll-area',\n '@radix-ui/react-select',\n '@radix-ui/react-slider',\n '@radix-ui/react-slot',\n '@radix-ui/react-tabs',\n '@radix-ui/react-tooltip',\n '@react-three/fiber',\n '@react-three/postprocessing',\n '@tanstack/react-query',\n 'boring-avatars',\n 'change-case',\n 'class-variance-authority',\n 'clsx',\n 'cmdk',\n 'color',\n 'framer-motion',\n 'konva',\n 'motion',\n 'next',\n 'next-themes',\n 'ogl',\n 'onnxruntime-web',\n 'pdf-lib',\n 'platform-detect',\n 'postprocessing',\n 'react',\n 'react-dom',\n 'react-hook-form',\n 'react-number-format',\n 'sharp',\n 'sonner',\n 'tailwind-merge',\n 'tailwindcss-animate',\n 'three',\n 'uuid',\n 'vaul',\n 'zod',\n 'zustand',\n ]),\n ...pick(localVersions, [\n '@inditextech/weave-react',\n '@inditextech/weave-sdk',\n '@inditextech/weave-store-azure-web-pubsub',\n ]),\n };\n\n const devDependencies = {\n ...pick(versionPkg.devDependencies, [\n '@eslint/eslintrc',\n '@tailwindcss/postcss',\n '@testing-library/dom',\n '@testing-library/react',\n '@types/node',\n '@types/react',\n '@types/react-dom',\n '@vitejs/plugin-react',\n 'eslint',\n 'eslint-config-next',\n 'eslint-config-prettier',\n 'jsdom',\n 'lucide-react',\n 'tailwindcss',\n 'typescript',\n 'vite-tsconfig-paths',\n ]),\n };\n\n return {\n name: projectName,\n version: '0.0.0',\n private: true,\n scripts: {\n build: 'next build',\n dev: 'next dev --experimental-https',\n lint: 'next lint',\n start: 'next start',\n },\n dependencies: sortObjectKeys(dependencies),\n devDependencies: sortObjectKeys(devDependencies),\n };\n }\n\n const dependencies = {\n ...pick(versionPkg.dependencies, [\n '@hookform/resolvers',\n '@next/env',\n '@radix-ui/react-accordion',\n '@radix-ui/react-avatar',\n '@radix-ui/react-checkbox',\n '@radix-ui/react-dialog',\n '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-label',\n '@radix-ui/react-popover',\n '@radix-ui/react-scroll-area',\n '@radix-ui/react-select',\n '@radix-ui/react-slider',\n '@radix-ui/react-slot',\n '@radix-ui/react-tabs',\n '@radix-ui/react-tooltip',\n '@react-three/fiber',\n '@react-three/postprocessing',\n '@tanstack/react-query',\n 'boring-avatars',\n 'change-case',\n 'class-variance-authority',\n 'clsx',\n 'cmdk',\n 'color',\n 'framer-motion',\n 'konva',\n 'motion',\n 'next',\n 'next-themes',\n 'ogl',\n 'onnxruntime-web',\n 'pdf-lib',\n 'platform-detect',\n 'postprocessing',\n 'react',\n 'react-dom',\n 'react-hook-form',\n 'react-number-format',\n 'sharp',\n 'sonner',\n 'tailwind-merge',\n 'tailwindcss-animate',\n 'three',\n 'uuid',\n 'vaul',\n 'zod',\n 'zustand',\n ]),\n ...pick(localVersions, [\n '@inditextech/weave-react',\n '@inditextech/weave-sdk',\n '@inditextech/weave-store-websockets',\n ]),\n };\n\n const devDependencies = {\n ...pick(versionPkg.devDependencies, [\n '@eslint/eslintrc',\n '@tailwindcss/postcss',\n '@testing-library/dom',\n '@testing-library/react',\n '@types/node',\n '@types/react',\n '@types/react-dom',\n '@vitejs/plugin-react',\n 'eslint',\n 'eslint-config-next',\n 'eslint-config-prettier',\n 'jsdom',\n 'lucide-react',\n 'tailwindcss',\n 'typescript',\n 'vite-tsconfig-paths',\n ]),\n };\n\n return {\n name: projectName,\n version: '0.0.0',\n private: true,\n scripts: {\n build: 'next build',\n dev: 'next dev --experimental-https',\n lint: 'next lint',\n start: 'next start',\n },\n dependencies: sortObjectKeys(dependencies),\n devDependencies: sortObjectKeys(devDependencies),\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction sortObjectKeys<T extends Record<string, any>>(obj: T): T {\n const sortedEntries = Object.keys(obj)\n .sort()\n .map((key) => [key, obj[key]] as [keyof T, T[keyof T]]);\n\n return Object.fromEntries(sortedEntries) as T;\n}\n\nfunction pick<T extends object, K extends keyof T>(\n obj: T,\n keys: K[]\n): Pick<T, K> {\n const result: Partial<T> = {};\n\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n\n return result as Pick<T, K>;\n}\n"],"mappings":"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BH,SAA0B;AACxE,KAAI,QAAQ,aAAa,4BAA4B;EACnD,MAAM,iBAAe;GACnB,GAAG,KAAK,gBAAW,cAAc;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACD,EAAC;GACF,GAAG,KAAK,UAAe;IACrB;IACA;IACA;GACD,EAAC;EACH;EAED,MAAM,oBAAkB,EACtB,GAAG,KAAK,gBAAW,iBAAiB;GAClC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD,EAAC,CACH;AAED,SAAO;GACL,MAAM;GACN,SAAS;GACT,SAAS;GACT,SAAS;IACP,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;GACR;GACD,cAAc,eAAe,eAAa;GAC1C,iBAAiB,eAAe,kBAAgB;EACjD;CACF;CAED,MAAM,iBAAe;EACnB,GAAG,KAAK,gBAAW,cAAc;GAC/B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD,EAAC;EACF,GAAG,KAAK,UAAe;GACrB;GACA;GACA;EACD,EAAC;CACH;CAED,MAAM,oBAAkB,EACtB,GAAG,KAAK,gBAAW,iBAAiB;EAClC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACD,EAAC,CACH;AAED,QAAO;EACL,MAAM;EACN,SAAS;EACT,SAAS;EACT,SAAS;GACP,OAAO;GACP,KAAK;GACL,MAAM;GACN,OAAO;EACR;EACD,cAAc,eAAe,eAAa;EAC1C,iBAAiB,eAAe,kBAAgB;CACjD;AACF;AAGD,SAAS,eAA8CO,KAAW;CAChE,MAAM,gBAAgB,OAAO,KAAK,IAAI,CACnC,MAAM,CACN,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAK,EAA0B;AAEzD,QAAO,OAAO,YAAY,cAAc;AACzC;AAED,SAAS,KACPA,KACAC,MACY;CACZ,MAAMC,SAAqB,CAAE;AAE7B,MAAK,MAAM,OAAO,KAChB,KAAI,OAAO,IACT,QAAO,OAAO,IAAI;AAItB,QAAO;AACR"}
1
+ {"version":3,"file":"create-app-CekXcOg7.js","names":["cwd: string","root: string","manager: PackageManager","dest: string","options: Options","file: string","dest: string","projectName: string","from: string","to: string","rename: (s: string) => string","obj: T","keys: K[]","result: Partial<T>"],"sources":["../src/git.ts","../src/versions.js","../template/package.json","../src/auto-install.ts","../src/constants.ts","../src/create-app.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\n/*\nInitialize a Git repo on the project.\n\nBased on https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/git.ts\n*/\n\nfunction isInGitRepository(cwd: string): boolean {\n try {\n execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isInMercurialRepository(cwd: string): boolean {\n try {\n execSync('hg --cwd . root', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isDefaultBranchSet(cwd: string): boolean {\n try {\n execSync('git config init.defaultBranch', { stdio: 'ignore', cwd });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function tryGitInit(root: string): boolean {\n let didInit = false;\n\n try {\n execSync('git --version', { stdio: 'ignore' });\n if (isInGitRepository(root) || isInMercurialRepository(root)) {\n return false;\n }\n\n execSync('git init', { stdio: 'ignore', cwd: root });\n didInit = true;\n\n if (!isDefaultBranchSet(root)) {\n execSync('git checkout -b main', { stdio: 'ignore', cwd: root });\n }\n\n execSync('git add -A', { stdio: 'ignore', cwd: root });\n execSync('git commit -m \"Initial commit from Create Fumadocs App\"', {\n stdio: 'ignore',\n cwd: root,\n });\n return true;\n } catch {\n if (didInit) {\n try {\n rmSync(join(root, '.git'), { recursive: true, force: true });\n } catch {\n // do nothing\n }\n }\n\n return false;\n }\n}\n","export const versions = {\"@inditextech/weave-types\":\"0.21.2\",\"@inditextech/weave-sdk\":\"0.21.2\",\"@inditextech/weave-store-websockets\":\"0.21.2\",\"@inditextech/weave-store-azure-web-pubsub\":\"0.21.2\",\"@inditextech/weave-react\":\"0.21.2\"}","{\n \"name\": \"example-versions\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"description\": \"Used to track dependency versions in create-*-app\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@hookform/resolvers\": \"^4.1.3\",\n \"@inditextech/weave-react\": \"0.0.0\",\n \"@inditextech/weave-sdk\": \"0.0.0\",\n \"@inditextech/weave-store-websockets\": \"0.0.0\",\n \"@inditextech/weave-store-azure-web-pubsub\": \"0.0.0\",\n \"@next/env\": \"^15.2.1\",\n \"@radix-ui/react-accordion\": \"^1.2.3\",\n \"@radix-ui/react-avatar\": \"^1.1.3\",\n \"@radix-ui/react-checkbox\": \"^1.1.4\",\n \"@radix-ui/react-dialog\": \"^1.1.6\",\n \"@radix-ui/react-dropdown-menu\": \"^2.1.6\",\n \"@radix-ui/react-label\": \"^2.1.2\",\n \"@radix-ui/react-popover\": \"^1.1.6\",\n \"@radix-ui/react-scroll-area\": \"^1.2.3\",\n \"@radix-ui/react-select\": \"^2.1.6\",\n \"@radix-ui/react-slider\": \"^1.2.3\",\n \"@radix-ui/react-slot\": \"^1.1.2\",\n \"@radix-ui/react-tabs\": \"^1.1.3\",\n \"@radix-ui/react-tooltip\": \"^1.1.8\",\n \"@react-three/fiber\": \"^8.18.0\",\n \"@react-three/postprocessing\": \"^2.19.1\",\n \"@tanstack/react-query\": \"^5.67.1\",\n \"boring-avatars\": \"^1.11.2\",\n \"change-case\": \"^5.4.4\",\n \"class-variance-authority\": \"^0.7.1\",\n \"clsx\": \"^2.1.1\",\n \"cmdk\": \"^1.0.0\",\n \"color\": \"^5.0.0\",\n \"framer-motion\": \"^11.18.2\",\n \"konva\": \"^9.3.18\",\n \"motion\": \"^12.4.7\",\n \"next\": \"14.2.28\",\n \"next-themes\": \"^0.4.6\",\n \"ogl\": \"^1.0.11\",\n \"onnxruntime-web\": \"^1.21.0-dev.20250206-d981b153d3\",\n \"pdf-lib\": \"^1.17.1\",\n \"platform-detect\": \"^3.0.1\",\n \"postprocessing\": \"^6.37.1\",\n \"react\": \"18.2.0\",\n \"react-dom\": \"18.2.0\",\n \"react-hook-form\": \"^7.54.2\",\n \"react-number-format\": \"^5.4.3\",\n \"sharp\": \"^0.33.5\",\n \"sonner\": \"^2.0.3\",\n \"tailwind-merge\": \"^3.0.2\",\n \"tailwindcss-animate\": \"^1.0.7\",\n \"three\": \"^0.167.1\",\n \"uuid\": \"^11.1.0\",\n \"vaul\": \"^1.1.2\",\n \"zod\": \"^3.24.2\",\n \"zustand\": \"^5.0.3\"\n },\n \"devDependencies\": {\n \"@eslint/eslintrc\": \"^3\",\n \"@tailwindcss/postcss\": \"^4\",\n \"@testing-library/dom\": \"^10.4.0\",\n \"@testing-library/react\": \"^16.2.0\",\n \"@types/node\": \"^20\",\n \"@types/react\": \"^18\",\n \"@types/react-dom\": \"^18\",\n \"@vitejs/plugin-react\": \"^4.3.4\",\n \"@vitest/coverage-v8\": \"^3.0.7\",\n \"eslint\": \"^8\",\n \"eslint-config-next\": \"14.2.24\",\n \"eslint-config-prettier\": \"^10.0.2\",\n \"jsdom\": \"^26.0.0\",\n \"lucide-react\": \"^0.477.0\",\n \"tailwindcss\": \"^4\",\n \"typescript\": \"^5\",\n \"vite-tsconfig-paths\": \"^5.1.4\",\n \"vitest\": \"^3.0.7\"\n }\n}\n","import { spawn } from 'cross-spawn';\n\nexport type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';\n\nexport function getPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent ?? '';\n\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n }\n\n if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n }\n\n if (userAgent.startsWith('bun')) {\n return 'bun';\n }\n\n return 'npm';\n}\n\nexport function autoInstall(\n manager: PackageManager,\n dest: string,\n): Promise<void> {\n return new Promise((res, reject) => {\n const installProcess = spawn(manager, ['install'], {\n stdio: 'ignore',\n env: {\n ...process.env,\n NODE_ENV: 'development',\n DISABLE_OPENCOLLECTIVE: '1',\n },\n cwd: dest,\n });\n\n installProcess.on('close', (code) => {\n if (code !== 0) {\n reject(new Error('Install failed'));\n } else {\n res();\n }\n });\n });\n}\n","import { fileURLToPath } from 'node:url';\n\nexport const sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);\nexport const cwd = process.cwd();\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { tryGitInit } from '@/git';\nimport { versions as localVersions } from '@/versions';\nimport versionPkg from './../template/package.json';\nimport type { PackageManager } from './auto-install';\nimport { autoInstall } from './auto-install';\nimport { cwd, sourceDir } from './constants';\n\nexport type Template = '+nextjs+websockets' | '+nextjs+azure-web-pubsub';\n\nexport interface Options {\n outputDir: string;\n template: Template;\n packageManager: PackageManager;\n installDeps?: boolean;\n initializeGit?: boolean;\n log?: (message: string) => void;\n}\n\nexport async function create(options: Options): Promise<void> {\n const {\n installDeps = true,\n initializeGit = true,\n log = console.log,\n } = options;\n const projectName = path.basename(options.outputDir);\n const dest = path.resolve(cwd, options.outputDir);\n\n function defaultRename(file: string): string {\n file = file.replace('example.gitignore', '.gitignore');\n file = file.replace('example.env', '.env');\n\n return file;\n }\n\n await copy(\n path.join(sourceDir, `template/${options.template}`),\n dest,\n defaultRename\n );\n\n const packageJson = createPackageJson(projectName, options);\n await fs.writeFile(\n path.join(dest, 'package.json'),\n JSON.stringify(packageJson, null, 2)\n );\n\n const readMe = await getReadme(dest, projectName);\n await fs.writeFile(path.join(dest, 'README.md'), readMe);\n\n if (installDeps) {\n await autoInstall(options.packageManager, dest);\n log('Installed dependencies');\n }\n\n if (initializeGit && tryGitInit(dest)) {\n log('Initialized Git repository');\n }\n}\n\nasync function getReadme(dest: string, projectName: string): Promise<string> {\n const template = await fs\n .readFile(path.join(dest, 'README.md'))\n .then((res) => res.toString());\n\n return `# ${projectName}\\n\\n${template}`;\n}\n\nasync function copy(\n from: string,\n to: string,\n rename: (s: string) => string = (s) => s\n): Promise<void> {\n const stats = await fs.stat(from);\n\n if (stats.isDirectory()) {\n const files = await fs.readdir(from);\n\n await Promise.all(\n files.map((file) =>\n copy(path.join(from, file), rename(path.join(to, file)))\n )\n );\n } else {\n await fs.mkdir(path.dirname(to), { recursive: true });\n await fs.copyFile(from, to);\n }\n}\n\nfunction createPackageJson(projectName: string, options: Options): object {\n if (options.template === '+nextjs+azure-web-pubsub') {\n const dependencies = {\n ...pick(versionPkg.dependencies, [\n '@hookform/resolvers',\n '@next/env',\n '@radix-ui/react-accordion',\n '@radix-ui/react-avatar',\n '@radix-ui/react-checkbox',\n '@radix-ui/react-dialog',\n '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-label',\n '@radix-ui/react-popover',\n '@radix-ui/react-scroll-area',\n '@radix-ui/react-select',\n '@radix-ui/react-slider',\n '@radix-ui/react-slot',\n '@radix-ui/react-tabs',\n '@radix-ui/react-tooltip',\n '@react-three/fiber',\n '@react-three/postprocessing',\n '@tanstack/react-query',\n 'boring-avatars',\n 'change-case',\n 'class-variance-authority',\n 'clsx',\n 'cmdk',\n 'color',\n 'framer-motion',\n 'konva',\n 'motion',\n 'next',\n 'next-themes',\n 'ogl',\n 'onnxruntime-web',\n 'pdf-lib',\n 'platform-detect',\n 'postprocessing',\n 'react',\n 'react-dom',\n 'react-hook-form',\n 'react-number-format',\n 'sharp',\n 'sonner',\n 'tailwind-merge',\n 'tailwindcss-animate',\n 'three',\n 'uuid',\n 'vaul',\n 'zod',\n 'zustand',\n ]),\n ...pick(localVersions, [\n '@inditextech/weave-react',\n '@inditextech/weave-sdk',\n '@inditextech/weave-store-azure-web-pubsub',\n ]),\n };\n\n const devDependencies = {\n ...pick(versionPkg.devDependencies, [\n '@eslint/eslintrc',\n '@tailwindcss/postcss',\n '@testing-library/dom',\n '@testing-library/react',\n '@types/node',\n '@types/react',\n '@types/react-dom',\n '@vitejs/plugin-react',\n 'eslint',\n 'eslint-config-next',\n 'eslint-config-prettier',\n 'jsdom',\n 'lucide-react',\n 'tailwindcss',\n 'typescript',\n 'vite-tsconfig-paths',\n ]),\n };\n\n return {\n name: projectName,\n version: '0.0.0',\n private: true,\n scripts: {\n build: 'next build',\n dev: 'next dev --experimental-https',\n lint: 'next lint',\n start: 'next start',\n },\n dependencies: sortObjectKeys(dependencies),\n devDependencies: sortObjectKeys(devDependencies),\n };\n }\n\n const dependencies = {\n ...pick(versionPkg.dependencies, [\n '@hookform/resolvers',\n '@next/env',\n '@radix-ui/react-accordion',\n '@radix-ui/react-avatar',\n '@radix-ui/react-checkbox',\n '@radix-ui/react-dialog',\n '@radix-ui/react-dropdown-menu',\n '@radix-ui/react-label',\n '@radix-ui/react-popover',\n '@radix-ui/react-scroll-area',\n '@radix-ui/react-select',\n '@radix-ui/react-slider',\n '@radix-ui/react-slot',\n '@radix-ui/react-tabs',\n '@radix-ui/react-tooltip',\n '@react-three/fiber',\n '@react-three/postprocessing',\n '@tanstack/react-query',\n 'boring-avatars',\n 'change-case',\n 'class-variance-authority',\n 'clsx',\n 'cmdk',\n 'color',\n 'framer-motion',\n 'konva',\n 'motion',\n 'next',\n 'next-themes',\n 'ogl',\n 'onnxruntime-web',\n 'pdf-lib',\n 'platform-detect',\n 'postprocessing',\n 'react',\n 'react-dom',\n 'react-hook-form',\n 'react-number-format',\n 'sharp',\n 'sonner',\n 'tailwind-merge',\n 'tailwindcss-animate',\n 'three',\n 'uuid',\n 'vaul',\n 'zod',\n 'zustand',\n ]),\n ...pick(localVersions, [\n '@inditextech/weave-react',\n '@inditextech/weave-sdk',\n '@inditextech/weave-store-websockets',\n ]),\n };\n\n const devDependencies = {\n ...pick(versionPkg.devDependencies, [\n '@eslint/eslintrc',\n '@tailwindcss/postcss',\n '@testing-library/dom',\n '@testing-library/react',\n '@types/node',\n '@types/react',\n '@types/react-dom',\n '@vitejs/plugin-react',\n 'eslint',\n 'eslint-config-next',\n 'eslint-config-prettier',\n 'jsdom',\n 'lucide-react',\n 'tailwindcss',\n 'typescript',\n 'vite-tsconfig-paths',\n ]),\n };\n\n return {\n name: projectName,\n version: '0.0.0',\n private: true,\n scripts: {\n build: 'next build',\n dev: 'next dev --experimental-https',\n lint: 'next lint',\n start: 'next start',\n },\n dependencies: sortObjectKeys(dependencies),\n devDependencies: sortObjectKeys(devDependencies),\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction sortObjectKeys<T extends Record<string, any>>(obj: T): T {\n const sortedEntries = Object.keys(obj)\n .sort()\n .map((key) => [key, obj[key]] as [keyof T, T[keyof T]]);\n\n return Object.fromEntries(sortedEntries) as T;\n}\n\nfunction pick<T extends object, K extends keyof T>(\n obj: T,\n keys: K[]\n): Pick<T, K> {\n const result: Partial<T> = {};\n\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n\n return result as Pick<T, K>;\n}\n"],"mappings":"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BH,SAA0B;AACxE,KAAI,QAAQ,aAAa,4BAA4B;EACnD,MAAM,iBAAe;GACnB,GAAG,KAAK,gBAAW,cAAc;IAC/B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;GACD,EAAC;GACF,GAAG,KAAK,UAAe;IACrB;IACA;IACA;GACD,EAAC;EACH;EAED,MAAM,oBAAkB,EACtB,GAAG,KAAK,gBAAW,iBAAiB;GAClC;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD,EAAC,CACH;AAED,SAAO;GACL,MAAM;GACN,SAAS;GACT,SAAS;GACT,SAAS;IACP,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;GACR;GACD,cAAc,eAAe,eAAa;GAC1C,iBAAiB,eAAe,kBAAgB;EACjD;CACF;CAED,MAAM,iBAAe;EACnB,GAAG,KAAK,gBAAW,cAAc;GAC/B;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD,EAAC;EACF,GAAG,KAAK,UAAe;GACrB;GACA;GACA;EACD,EAAC;CACH;CAED,MAAM,oBAAkB,EACtB,GAAG,KAAK,gBAAW,iBAAiB;EAClC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACD,EAAC,CACH;AAED,QAAO;EACL,MAAM;EACN,SAAS;EACT,SAAS;EACT,SAAS;GACP,OAAO;GACP,KAAK;GACL,MAAM;GACN,OAAO;EACR;EACD,cAAc,eAAe,eAAa;EAC1C,iBAAiB,eAAe,kBAAgB;CACjD;AACF;AAGD,SAAS,eAA8CO,KAAW;CAChE,MAAM,gBAAgB,OAAO,KAAK,IAAI,CACnC,MAAM,CACN,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAK,EAA0B;AAEzD,QAAO,OAAO,YAAY,cAAc;AACzC;AAED,SAAS,KACPA,KACAC,MACY;CACZ,MAAMC,SAAqB,CAAE;AAE7B,MAAK,MAAM,OAAO,KAChB,KAAI,OAAO,IACT,QAAO,OAAO,IAAI;AAItB,QAAO;AACR"}
@@ -1,3 +1,3 @@
1
- import { create } from "./create-app-C1gmYK6w.js";
1
+ import { create } from "./create-app-CekXcOg7.js";
2
2
 
3
3
  export { create };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { create, cwd, getPackageManager } from "./create-app-C1gmYK6w.js";
2
+ import { create, cwd, getPackageManager } from "./create-app-CekXcOg7.js";
3
3
  import path from "node:path";
4
4
  import fs from "node:fs/promises";
5
5
  import { cancel, confirm, group, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-weave-frontend-app",
3
- "version": "0.21.1",
3
+ "version": "0.21.2",
4
4
  "description": "Create a new frontend artifact for a site with Weave.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -2,11 +2,12 @@
2
2
 
3
3
  import React from 'react';
4
4
  import { WeaveStateElement } from '@inditextech/weave-types';
5
- import { Crop } from 'lucide-react';
5
+ import { RotateCcw } from 'lucide-react';
6
6
  import { useWeave } from '@inditextech/weave-react';
7
7
  import { useCollaborationRoom } from '@/store/store';
8
- import { ToggleIconButton } from '../toggle-icon-button';
9
8
  import { InputNumber } from '../inputs/input-number';
9
+ import Konva from 'konva';
10
+ import { ToggleIconButton } from '../toggle-icon-button';
10
11
 
11
12
  export function CropProperties() {
12
13
  const instance = useWeave((state) => state.instance);
@@ -48,44 +49,31 @@ export function CropProperties() {
48
49
  Crop
49
50
  </span>
50
51
  </div>
51
- <div className="flex justify-end items-center">
52
- <ToggleIconButton
53
- kind="switch"
54
- icon={<Crop size={16} strokeWidth={1} />}
55
- pressed={typeof actualNode.props.cropX !== 'undefined'}
56
- onClick={() => {
57
- const updatedNode: WeaveStateElement = {
58
- ...actualNode,
59
- props: {
60
- ...actualNode.props,
61
- ...(typeof actualNode.props.cropX !== 'undefined'
62
- ? {
63
- width: actualNode.props.imageInfo.width,
64
- height: actualNode.props.imageInfo.height,
65
- cropX: null,
66
- cropY: null,
67
- cropWidth: null,
68
- cropHeight: null,
69
- }
70
- : {
71
- width: actualNode.props.imageInfo.width,
72
- height: actualNode.props.imageInfo.height,
73
- cropX: 0,
74
- cropY: 0,
75
- cropWidth: actualNode.props.imageInfo.width,
76
- cropHeight: actualNode.props.imageInfo.height,
77
- }),
78
- },
79
- };
80
- updateElement(updatedNode);
81
- }}
82
- />
83
- </div>
52
+ <ToggleIconButton
53
+ kind="toggle"
54
+ icon={<RotateCcw size={20} strokeWidth={1} />}
55
+ pressedIcon={<RotateCcw size={20} strokeWidth={1} />}
56
+ pressed={actualNode.props.strokeEnabled ?? true}
57
+ onClick={(e) => {
58
+ e.stopPropagation();
59
+ const stage = instance.getStage();
60
+ if (!stage) return;
61
+
62
+ const node = stage.findOne(`#${actualNode.key}`) as
63
+ | Konva.Node
64
+ | undefined;
65
+
66
+ if (!node) return;
67
+
68
+ node.resetCrop();
69
+ }}
70
+ />
84
71
  </div>
85
72
  <div className="grid grid-cols-2 gap-3 w-full">
86
73
  <InputNumber
87
74
  label="X"
88
75
  value={actualNode.props.cropX ?? 0}
76
+ disabled
89
77
  onChange={(value) => {
90
78
  const updatedNode: WeaveStateElement = {
91
79
  ...actualNode,
@@ -100,6 +88,7 @@ export function CropProperties() {
100
88
  <InputNumber
101
89
  label="Y"
102
90
  value={actualNode.props.cropY ?? 0}
91
+ disabled
103
92
  onChange={(value) => {
104
93
  const updatedNode: WeaveStateElement = {
105
94
  ...actualNode,
@@ -114,6 +103,7 @@ export function CropProperties() {
114
103
  <InputNumber
115
104
  label="Width"
116
105
  value={actualNode.props.cropWidth ?? actualNode.props.width}
106
+ disabled
117
107
  onChange={(value) => {
118
108
  const updatedNode: WeaveStateElement = {
119
109
  ...actualNode,
@@ -129,6 +119,7 @@ export function CropProperties() {
129
119
  <InputNumber
130
120
  label="Height"
131
121
  value={actualNode.props.cropHeight ?? actualNode.props.height}
122
+ disabled
132
123
  onChange={(value) => {
133
124
  const updatedNode: WeaveStateElement = {
134
125
  ...actualNode,
@@ -1,15 +1,12 @@
1
- // SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
1
+ 'use client';
4
2
 
5
- "use client";
6
-
7
- import React from "react";
8
- import { WeaveStateElement } from "@inditextech/weave-types";
9
- import { useWeave } from "@inditextech/weave-react";
10
- import { useCollaborationRoom } from "@/store/store";
11
- import { InputNumber } from "../inputs/input-number";
12
- import { ToggleIconButton } from "../toggle-icon-button";
3
+ import React from 'react';
4
+ import { WeaveStateElement } from '@inditextech/weave-types';
5
+ import { useWeave } from '@inditextech/weave-react';
6
+ import { useCollaborationRoom } from '@/store/store';
7
+ import { InputNumber } from '../inputs/input-number';
8
+ import { ToggleIconButton } from '../toggle-icon-button';
9
+ import { Scaling } from 'lucide-react';
13
10
 
14
11
  export function SizeProperties() {
15
12
  const instance = useWeave((state) => state.instance);
@@ -24,17 +21,19 @@ export function SizeProperties() {
24
21
  (state) => state.nodeProperties.createProps
25
22
  );
26
23
 
24
+ const [maintainAspectRatio, setMaintainAspectRatio] = React.useState(true);
25
+
27
26
  const actualNode = React.useMemo(() => {
28
- if (actualAction && nodePropertiesAction === "create") {
27
+ if (actualAction && nodePropertiesAction === 'create') {
29
28
  return {
30
- key: "creating",
31
- type: "undefined",
29
+ key: 'creating',
30
+ type: 'undefined',
32
31
  props: {
33
32
  ...nodeCreateProps,
34
33
  },
35
34
  };
36
35
  }
37
- if (node && nodePropertiesAction === "update") {
36
+ if (node && nodePropertiesAction === 'update') {
38
37
  return node;
39
38
  }
40
39
  return undefined;
@@ -43,16 +42,22 @@ export function SizeProperties() {
43
42
  const updateElement = React.useCallback(
44
43
  (updatedNode: WeaveStateElement) => {
45
44
  if (!instance) return;
46
- if (actualAction && nodePropertiesAction === "create") {
45
+ if (actualAction && nodePropertiesAction === 'create') {
47
46
  instance.updatePropsAction(actualAction, updatedNode.props);
48
47
  }
49
- if (nodePropertiesAction === "update") {
48
+ if (nodePropertiesAction === 'update') {
50
49
  instance.updateNode(updatedNode);
51
50
  }
52
51
  },
53
52
  [instance, actualAction, nodePropertiesAction]
54
53
  );
55
54
 
55
+ React.useEffect(() => {
56
+ if (actualNode && actualNode.type === 'image') {
57
+ setMaintainAspectRatio(true);
58
+ }
59
+ }, [actualNode]);
60
+
56
61
  if (!instance || !actualNode || !nodePropertiesAction) {
57
62
  return null;
58
63
  }
@@ -61,7 +66,7 @@ export function SizeProperties() {
61
66
 
62
67
  if (
63
68
  actualAction &&
64
- !["selectionTool", "rectangleTool", "imageTool"].includes(actualAction)
69
+ !['selectionTool', 'rectangleTool', 'imageTool'].includes(actualAction)
65
70
  ) {
66
71
  return null;
67
72
  }
@@ -76,20 +81,20 @@ export function SizeProperties() {
76
81
  </div>
77
82
  </div>
78
83
  <div className="grid grid-cols-1 gap-3 w-full">
79
- {actualNode.type === "text" && (
84
+ {actualNode.type === 'text' && (
80
85
  <div className="w-full flex justify-between items-center gap-4 col-span-2">
81
86
  <div className="w-full flex justify-evenly items-center gap-1">
82
87
  <ToggleIconButton
83
88
  kind="switch"
84
89
  className="w-full"
85
90
  icon={<div className="text-[12px] uppercase">Auto width</div>}
86
- pressed={(actualNode.props.layout ?? "auto-all") === "auto-all"}
91
+ pressed={(actualNode.props.layout ?? 'auto-all') === 'auto-all'}
87
92
  onClick={() => {
88
93
  const updatedNode: WeaveStateElement = {
89
94
  ...actualNode,
90
95
  props: {
91
96
  ...actualNode.props,
92
- layout: "auto-all",
97
+ layout: 'auto-all',
93
98
  },
94
99
  };
95
100
  updateElement(updatedNode);
@@ -100,14 +105,14 @@ export function SizeProperties() {
100
105
  className="w-full"
101
106
  icon={<div className="text-[12px] uppercase">Auto height</div>}
102
107
  pressed={
103
- (actualNode.props.layout ?? "auto-all") === "auto-height"
108
+ (actualNode.props.layout ?? 'auto-all') === 'auto-height'
104
109
  }
105
110
  onClick={() => {
106
111
  const updatedNode: WeaveStateElement = {
107
112
  ...actualNode,
108
113
  props: {
109
114
  ...actualNode.props,
110
- layout: "auto-height",
115
+ layout: 'auto-height',
111
116
  },
112
117
  };
113
118
  updateElement(updatedNode);
@@ -117,13 +122,13 @@ export function SizeProperties() {
117
122
  kind="switch"
118
123
  className="w-full"
119
124
  icon={<div className="text-[12px] uppercase">Fixed size</div>}
120
- pressed={(actualNode.props.layout ?? "auto-all") === "fixed"}
125
+ pressed={(actualNode.props.layout ?? 'auto-all') === 'fixed'}
121
126
  onClick={() => {
122
127
  const updatedNode: WeaveStateElement = {
123
128
  ...actualNode,
124
129
  props: {
125
130
  ...actualNode.props,
126
- layout: "fixed",
131
+ layout: 'fixed',
127
132
  },
128
133
  };
129
134
  updateElement(updatedNode);
@@ -136,15 +141,45 @@ export function SizeProperties() {
136
141
  <InputNumber
137
142
  label="Width"
138
143
  value={actualNode.props.width ?? 0}
139
- disabled={actualNode.type === "frame"}
144
+ disabled={actualNode.type === 'frame'}
140
145
  onChange={(value) => {
141
- const isText = actualNode.type === "text";
146
+ const isImage = actualNode.type === 'image';
147
+ const isText = actualNode.type === 'text';
148
+
149
+ let newWidth = value;
150
+ let newHeight = actualNode.props.height;
151
+ if (
152
+ isImage &&
153
+ maintainAspectRatio &&
154
+ actualNode.props.imageInfo
155
+ ) {
156
+ const ratio =
157
+ actualNode.props.imageInfo.width /
158
+ actualNode.props.imageInfo.height;
159
+
160
+ newWidth = value;
161
+ newHeight = value / ratio;
162
+ }
163
+ if (!isImage && maintainAspectRatio) {
164
+ const ratio = actualNode.props.width / actualNode.props.height;
165
+
166
+ newWidth = value;
167
+ newHeight = value / ratio;
168
+ }
169
+
142
170
  const updatedNode: WeaveStateElement = {
143
171
  ...actualNode,
144
172
  props: {
145
173
  ...actualNode.props,
146
- ...(isText && { layout: "fixed" }),
147
- width: value,
174
+ ...(isImage && {
175
+ uncroppedImage: {
176
+ width: newWidth,
177
+ height: newHeight,
178
+ },
179
+ }),
180
+ ...(isText && { layout: 'fixed' }),
181
+ width: newWidth,
182
+ height: newHeight,
148
183
  },
149
184
  };
150
185
  updateElement(updatedNode);
@@ -153,25 +188,57 @@ export function SizeProperties() {
153
188
  <InputNumber
154
189
  label="Height"
155
190
  value={actualNode.props.height ?? 0}
156
- disabled={actualNode.type === "frame"}
191
+ disabled={actualNode.type === 'frame'}
157
192
  onChange={(value) => {
158
- const isText = actualNode.type === "text";
193
+ const isImage = actualNode.type === 'image';
194
+ const isText = actualNode.type === 'text';
195
+
196
+ let newWidth = actualNode.props.width;
197
+ let newHeight = value;
198
+ if (
199
+ isImage &&
200
+ actualNode.props.imageInfo &&
201
+ maintainAspectRatio
202
+ ) {
203
+ const ratio =
204
+ actualNode.props.imageInfo.height /
205
+ actualNode.props.imageInfo.width;
206
+
207
+ newWidth = value / ratio;
208
+ newHeight = value;
209
+ }
210
+ if (!isImage && maintainAspectRatio) {
211
+ const ratio =
212
+ actualNode.props.imageInfo.height /
213
+ actualNode.props.imageInfo.width;
214
+
215
+ newWidth = value / ratio;
216
+ newHeight = value;
217
+ }
218
+
159
219
  const updatedNode: WeaveStateElement = {
160
220
  ...actualNode,
161
221
  props: {
162
222
  ...actualNode.props,
163
- ...(isText && { layout: "fixed" }),
164
- height: value,
223
+ ...(isImage && {
224
+ uncroppedImage: {
225
+ width: newWidth,
226
+ height: newHeight,
227
+ },
228
+ }),
229
+ ...(isText && { layout: 'fixed' }),
230
+ width: newWidth,
231
+ height: newHeight,
165
232
  },
166
233
  };
167
234
  updateElement(updatedNode);
168
235
  }}
169
236
  />
170
- {["update"].includes(nodePropertiesAction) && (
237
+ {['update'].includes(nodePropertiesAction) && (
171
238
  <InputNumber
172
239
  label="Scale (%)"
173
240
  value={(actualNode.props.scaleX ?? 1) * 100}
174
- disabled={actualNode.type === "frame"}
241
+ disabled={actualNode.type === 'frame'}
175
242
  onChange={(value) => {
176
243
  const updatedNode: WeaveStateElement = {
177
244
  ...actualNode,
@@ -185,6 +252,23 @@ export function SizeProperties() {
185
252
  }}
186
253
  />
187
254
  )}
255
+
256
+ <div className="w-full flex justify-between items-center gap-4 col-span-3">
257
+ <div className="text-[12px] text-[#757575] font-inter font-light text-nowrap">
258
+ Maintain aspect ratio
259
+ </div>
260
+ <div className="w-full flex justify-end items-center gap-1">
261
+ <ToggleIconButton
262
+ kind="switch"
263
+ disabled={actualNode.type === 'image'}
264
+ icon={<Scaling size={20} strokeWidth={1} />}
265
+ pressed={maintainAspectRatio}
266
+ onClick={() => {
267
+ setMaintainAspectRatio((prev) => !prev);
268
+ }}
269
+ />
270
+ </div>
271
+ </div>
188
272
  </div>
189
273
  </div>
190
274
  </div>
@@ -83,8 +83,8 @@ export function StrokeProperties() {
83
83
  </div>
84
84
  <ToggleIconButton
85
85
  kind="toggle"
86
- icon={<Eye size={16} strokeWidth={1} />}
87
- pressedIcon={<EyeOff size={16} strokeWidth={1} />}
86
+ icon={<Eye size={20} strokeWidth={1} />}
87
+ pressedIcon={<EyeOff size={20} strokeWidth={1} />}
88
88
  pressed={actualNode.props.strokeEnabled ?? true}
89
89
  onClick={(e) => {
90
90
  e.stopPropagation();
@@ -1,5 +1 @@
1
- // SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
-
5
- declare module "platform-detect";
1
+ declare module 'platform-detect';
@@ -1,10 +1,6 @@
1
- // SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
1
+ import 'konva/lib/Node';
4
2
 
5
- import "konva/lib/Node";
6
-
7
- declare module "konva/lib/Node" {
3
+ declare module 'konva/lib/Node' {
8
4
  interface Node {
9
5
  getTransformerProperties(): WeaveNodeTransformerProperties;
10
6
  resetCrop(): void;
@@ -2,11 +2,12 @@
2
2
 
3
3
  import React from 'react';
4
4
  import { WeaveStateElement } from '@inditextech/weave-types';
5
- import { Crop } from 'lucide-react';
5
+ import { RotateCcw } from 'lucide-react';
6
6
  import { useWeave } from '@inditextech/weave-react';
7
7
  import { useCollaborationRoom } from '@/store/store';
8
- import { ToggleIconButton } from '../toggle-icon-button';
9
8
  import { InputNumber } from '../inputs/input-number';
9
+ import Konva from 'konva';
10
+ import { ToggleIconButton } from '../toggle-icon-button';
10
11
 
11
12
  export function CropProperties() {
12
13
  const instance = useWeave((state) => state.instance);
@@ -48,44 +49,31 @@ export function CropProperties() {
48
49
  Crop
49
50
  </span>
50
51
  </div>
51
- <div className="flex justify-end items-center">
52
- <ToggleIconButton
53
- kind="switch"
54
- icon={<Crop size={16} strokeWidth={1} />}
55
- pressed={typeof actualNode.props.cropX !== 'undefined'}
56
- onClick={() => {
57
- const updatedNode: WeaveStateElement = {
58
- ...actualNode,
59
- props: {
60
- ...actualNode.props,
61
- ...(typeof actualNode.props.cropX !== 'undefined'
62
- ? {
63
- width: actualNode.props.imageInfo.width,
64
- height: actualNode.props.imageInfo.height,
65
- cropX: null,
66
- cropY: null,
67
- cropWidth: null,
68
- cropHeight: null,
69
- }
70
- : {
71
- width: actualNode.props.imageInfo.width,
72
- height: actualNode.props.imageInfo.height,
73
- cropX: 0,
74
- cropY: 0,
75
- cropWidth: actualNode.props.imageInfo.width,
76
- cropHeight: actualNode.props.imageInfo.height,
77
- }),
78
- },
79
- };
80
- updateElement(updatedNode);
81
- }}
82
- />
83
- </div>
52
+ <ToggleIconButton
53
+ kind="toggle"
54
+ icon={<RotateCcw size={20} strokeWidth={1} />}
55
+ pressedIcon={<RotateCcw size={20} strokeWidth={1} />}
56
+ pressed={actualNode.props.strokeEnabled ?? true}
57
+ onClick={(e) => {
58
+ e.stopPropagation();
59
+ const stage = instance.getStage();
60
+ if (!stage) return;
61
+
62
+ const node = stage.findOne(`#${actualNode.key}`) as
63
+ | Konva.Node
64
+ | undefined;
65
+
66
+ if (!node) return;
67
+
68
+ node.resetCrop();
69
+ }}
70
+ />
84
71
  </div>
85
72
  <div className="grid grid-cols-2 gap-3 w-full">
86
73
  <InputNumber
87
74
  label="X"
88
75
  value={actualNode.props.cropX ?? 0}
76
+ disabled
89
77
  onChange={(value) => {
90
78
  const updatedNode: WeaveStateElement = {
91
79
  ...actualNode,
@@ -100,6 +88,7 @@ export function CropProperties() {
100
88
  <InputNumber
101
89
  label="Y"
102
90
  value={actualNode.props.cropY ?? 0}
91
+ disabled
103
92
  onChange={(value) => {
104
93
  const updatedNode: WeaveStateElement = {
105
94
  ...actualNode,
@@ -114,6 +103,7 @@ export function CropProperties() {
114
103
  <InputNumber
115
104
  label="Width"
116
105
  value={actualNode.props.cropWidth ?? actualNode.props.width}
106
+ disabled
117
107
  onChange={(value) => {
118
108
  const updatedNode: WeaveStateElement = {
119
109
  ...actualNode,
@@ -129,6 +119,7 @@ export function CropProperties() {
129
119
  <InputNumber
130
120
  label="Height"
131
121
  value={actualNode.props.cropHeight ?? actualNode.props.height}
122
+ disabled
132
123
  onChange={(value) => {
133
124
  const updatedNode: WeaveStateElement = {
134
125
  ...actualNode,
@@ -6,6 +6,7 @@ import { useWeave } from '@inditextech/weave-react';
6
6
  import { useCollaborationRoom } from '@/store/store';
7
7
  import { InputNumber } from '../inputs/input-number';
8
8
  import { ToggleIconButton } from '../toggle-icon-button';
9
+ import { Scaling } from 'lucide-react';
9
10
 
10
11
  export function SizeProperties() {
11
12
  const instance = useWeave((state) => state.instance);
@@ -20,6 +21,8 @@ export function SizeProperties() {
20
21
  (state) => state.nodeProperties.createProps
21
22
  );
22
23
 
24
+ const [maintainAspectRatio, setMaintainAspectRatio] = React.useState(true);
25
+
23
26
  const actualNode = React.useMemo(() => {
24
27
  if (actualAction && nodePropertiesAction === 'create') {
25
28
  return {
@@ -49,6 +52,12 @@ export function SizeProperties() {
49
52
  [instance, actualAction, nodePropertiesAction]
50
53
  );
51
54
 
55
+ React.useEffect(() => {
56
+ if (actualNode && actualNode.type === 'image') {
57
+ setMaintainAspectRatio(true);
58
+ }
59
+ }, [actualNode]);
60
+
52
61
  if (!instance || !actualNode || !nodePropertiesAction) {
53
62
  return null;
54
63
  }
@@ -132,14 +141,45 @@ export function SizeProperties() {
132
141
  <InputNumber
133
142
  label="Width"
134
143
  value={actualNode.props.width ?? 0}
144
+ disabled={actualNode.type === 'frame'}
135
145
  onChange={(value) => {
146
+ const isImage = actualNode.type === 'image';
136
147
  const isText = actualNode.type === 'text';
148
+
149
+ let newWidth = value;
150
+ let newHeight = actualNode.props.height;
151
+ if (
152
+ isImage &&
153
+ maintainAspectRatio &&
154
+ actualNode.props.imageInfo
155
+ ) {
156
+ const ratio =
157
+ actualNode.props.imageInfo.width /
158
+ actualNode.props.imageInfo.height;
159
+
160
+ newWidth = value;
161
+ newHeight = value / ratio;
162
+ }
163
+ if (!isImage && maintainAspectRatio) {
164
+ const ratio = actualNode.props.width / actualNode.props.height;
165
+
166
+ newWidth = value;
167
+ newHeight = value / ratio;
168
+ }
169
+
137
170
  const updatedNode: WeaveStateElement = {
138
171
  ...actualNode,
139
172
  props: {
140
173
  ...actualNode.props,
174
+ ...(isImage && {
175
+ uncroppedImage: {
176
+ width: newWidth,
177
+ height: newHeight,
178
+ },
179
+ }),
141
180
  ...(isText && { layout: 'fixed' }),
142
- width: value,
181
+ width: newWidth,
182
+ height: newHeight,
143
183
  },
144
184
  };
145
185
  updateElement(updatedNode);
@@ -148,14 +188,47 @@ export function SizeProperties() {
148
188
  <InputNumber
149
189
  label="Height"
150
190
  value={actualNode.props.height ?? 0}
191
+ disabled={actualNode.type === 'frame'}
151
192
  onChange={(value) => {
193
+ const isImage = actualNode.type === 'image';
152
194
  const isText = actualNode.type === 'text';
195
+
196
+ let newWidth = actualNode.props.width;
197
+ let newHeight = value;
198
+ if (
199
+ isImage &&
200
+ actualNode.props.imageInfo &&
201
+ maintainAspectRatio
202
+ ) {
203
+ const ratio =
204
+ actualNode.props.imageInfo.height /
205
+ actualNode.props.imageInfo.width;
206
+
207
+ newWidth = value / ratio;
208
+ newHeight = value;
209
+ }
210
+ if (!isImage && maintainAspectRatio) {
211
+ const ratio =
212
+ actualNode.props.imageInfo.height /
213
+ actualNode.props.imageInfo.width;
214
+
215
+ newWidth = value / ratio;
216
+ newHeight = value;
217
+ }
218
+
153
219
  const updatedNode: WeaveStateElement = {
154
220
  ...actualNode,
155
221
  props: {
156
222
  ...actualNode.props,
223
+ ...(isImage && {
224
+ uncroppedImage: {
225
+ width: newWidth,
226
+ height: newHeight,
227
+ },
228
+ }),
157
229
  ...(isText && { layout: 'fixed' }),
158
- height: value,
230
+ width: newWidth,
231
+ height: newHeight,
159
232
  },
160
233
  };
161
234
  updateElement(updatedNode);
@@ -165,6 +238,7 @@ export function SizeProperties() {
165
238
  <InputNumber
166
239
  label="Scale (%)"
167
240
  value={(actualNode.props.scaleX ?? 1) * 100}
241
+ disabled={actualNode.type === 'frame'}
168
242
  onChange={(value) => {
169
243
  const updatedNode: WeaveStateElement = {
170
244
  ...actualNode,
@@ -178,6 +252,23 @@ export function SizeProperties() {
178
252
  }}
179
253
  />
180
254
  )}
255
+
256
+ <div className="w-full flex justify-between items-center gap-4 col-span-3">
257
+ <div className="text-[12px] text-[#757575] font-inter font-light text-nowrap">
258
+ Maintain aspect ratio
259
+ </div>
260
+ <div className="w-full flex justify-end items-center gap-1">
261
+ <ToggleIconButton
262
+ kind="switch"
263
+ disabled={actualNode.type === 'image'}
264
+ icon={<Scaling size={20} strokeWidth={1} />}
265
+ pressed={maintainAspectRatio}
266
+ onClick={() => {
267
+ setMaintainAspectRatio((prev) => !prev);
268
+ }}
269
+ />
270
+ </div>
271
+ </div>
181
272
  </div>
182
273
  </div>
183
274
  </div>
@@ -83,8 +83,8 @@ export function StrokeProperties() {
83
83
  </div>
84
84
  <ToggleIconButton
85
85
  kind="toggle"
86
- icon={<Eye size={16} strokeWidth={1} />}
87
- pressedIcon={<EyeOff size={16} strokeWidth={1} />}
86
+ icon={<Eye size={20} strokeWidth={1} />}
87
+ pressedIcon={<EyeOff size={20} strokeWidth={1} />}
88
88
  pressed={actualNode.props.strokeEnabled ?? true}
89
89
  onClick={(e) => {
90
90
  e.stopPropagation();
@@ -1,5 +1 @@
1
- // SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
4
-
5
- declare module "platform-detect";
1
+ declare module 'platform-detect';
@@ -1,10 +1,6 @@
1
- // SPDX-FileCopyrightText: 2025 2025 INDUSTRIA DE DISEÑO TEXTIL S.A. (INDITEX S.A.)
2
- //
3
- // SPDX-License-Identifier: Apache-2.0
1
+ import 'konva/lib/Node';
4
2
 
5
- import "konva/lib/Node";
6
-
7
- declare module "konva/lib/Node" {
3
+ declare module 'konva/lib/Node' {
8
4
  interface Node {
9
5
  getTransformerProperties(): WeaveNodeTransformerProperties;
10
6
  resetCrop(): void;