create-weave-frontend-app 0.10.1 → 0.10.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 (21) hide show
  1. package/dist/{create-app-B_HqIJ_F.js → create-app-CA6IZiJb.js} +6 -6
  2. package/dist/{create-app-B_HqIJ_F.js.map → create-app-CA6IZiJb.js.map} +1 -1
  3. package/dist/create-app.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/package.json +1 -1
  6. package/template/+nextjs+azure-web-pubsub/components/room/room.tsx +2 -0
  7. package/template/+nextjs+azure-web-pubsub/components/room-components/help/help-drawer.tsx +41 -41
  8. package/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-color.tsx +14 -5
  9. package/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/fill-properties.tsx +8 -1
  10. package/template/+nextjs+azure-web-pubsub/components/room-components/overlay/node-properties.tsx +37 -3
  11. package/template/+nextjs+azure-web-pubsub/components/room-components/overlay/room-header.tsx +54 -78
  12. package/template/+nextjs+azure-web-pubsub/lib/constants.ts +9 -5
  13. package/template/+nextjs+azure-web-pubsub/store/store.ts +26 -1
  14. package/template/+nextjs+websockets/components/room/room.tsx +2 -0
  15. package/template/+nextjs+websockets/components/room-components/help/help-drawer.tsx +41 -41
  16. package/template/+nextjs+websockets/components/room-components/inputs/input-color.tsx +14 -5
  17. package/template/+nextjs+websockets/components/room-components/node-properties/fill-properties.tsx +8 -1
  18. package/template/+nextjs+websockets/components/room-components/overlay/node-properties.tsx +37 -3
  19. package/template/+nextjs+websockets/components/room-components/overlay/room-header.tsx +54 -78
  20. package/template/+nextjs+websockets/lib/constants.ts +9 -5
  21. package/template/+nextjs+websockets/store/store.ts +26 -1
@@ -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.10.1",
80
- "@inditextech/weave-sdk": "0.10.1",
81
- "@inditextech/weave-store-websockets": "0.10.1",
82
- "@inditextech/weave-store-azure-web-pubsub": "0.10.1",
83
- "@inditextech/weave-react": "0.10.1"
79
+ "@inditextech/weave-types": "0.10.2",
80
+ "@inditextech/weave-sdk": "0.10.2",
81
+ "@inditextech/weave-store-websockets": "0.10.2",
82
+ "@inditextech/weave-store-azure-web-pubsub": "0.10.2",
83
+ "@inditextech/weave-react": "0.10.2"
84
84
  };
85
85
 
86
86
  //#endregion
@@ -428,4 +428,4 @@ function pick(obj, keys) {
428
428
 
429
429
  //#endregion
430
430
  export { create, cwd, getPackageManager };
431
- //# sourceMappingURL=create-app-B_HqIJ_F.js.map
431
+ //# sourceMappingURL=create-app-CA6IZiJb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-app-B_HqIJ_F.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.10.1\",\"@inditextech/weave-sdk\":\"0.10.1\",\"@inditextech/weave-store-websockets\":\"0.10.1\",\"@inditextech/weave-store-azure-web-pubsub\":\"0.10.1\",\"@inditextech/weave-react\":\"0.10.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 \"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 '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 '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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ACxE,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;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;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-CA6IZiJb.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.10.2\",\"@inditextech/weave-sdk\":\"0.10.2\",\"@inditextech/weave-store-websockets\":\"0.10.2\",\"@inditextech/weave-store-azure-web-pubsub\":\"0.10.2\",\"@inditextech/weave-react\":\"0.10.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 \"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 '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 '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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ACxE,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;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;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-B_HqIJ_F.js";
1
+ import { create } from "./create-app-CA6IZiJb.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-B_HqIJ_F.js";
2
+ import { create, cwd, getPackageManager } from "./create-app-CA6IZiJb.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.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Create a new frontend artifact for a site with Weave.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -14,6 +14,7 @@ import useGetAzureWebPubsubProvider from '../room-components/hooks/use-get-azure
14
14
  import useHandleRouteParams from '../room-components/hooks/use-handle-route-params';
15
15
  import { UploadFile } from '../room-components/upload-file';
16
16
  import UserForm from '../room-components/user-form';
17
+ import { HelpDrawer } from '../room-components/help/help-drawer';
17
18
 
18
19
  const statusMap = {
19
20
  ['idle']: 'Idle',
@@ -132,6 +133,7 @@ export const Room = () => {
132
133
  >
133
134
  <UploadFile />
134
135
  <RoomLayout />
136
+ <HelpDrawer />
135
137
  </WeaveProvider>
136
138
  )}
137
139
  <Toaster />
@@ -1,70 +1,70 @@
1
1
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
2
2
  import {
3
- Tooltip,
4
- TooltipContent,
5
- TooltipProvider,
6
- TooltipTrigger,
7
- } from '@/components/ui/tooltip';
3
+ DropdownMenuItem,
4
+ DropdownMenuShortcut,
5
+ } from '@/components/ui/dropdown-menu';
8
6
  import {
9
7
  Drawer,
10
8
  DrawerClose,
11
9
  DrawerContent,
12
10
  DrawerHeader,
13
11
  DrawerTitle,
14
- DrawerTrigger,
15
12
  } from '@/components/ui/drawer';
16
13
  import { Keyboard, XIcon } from 'lucide-react';
17
14
  import { SYSTEM_OS } from '@/lib/utils';
18
15
  import { HelpTools } from './help-tools';
19
- import { ShortcutElement } from './shortcut-element';
20
16
  import React from 'react';
21
- import { useKeyDown } from '../hooks/use-key-down';
22
17
  import { useGetOs } from '../hooks/use-get-os';
23
18
  import { HelpZoom } from './help-zoom';
24
19
  import { HelpView } from './help-view';
25
20
  import { HelpSelection } from './help-selection';
26
21
  import { HelpEdit } from './help-edit';
27
22
  import { HelpArrange } from './help-arrange';
23
+ import { useCollaborationRoom } from '@/store/store';
24
+ import { DRAWER_ELEMENTS } from '@/lib/constants';
28
25
 
29
- export const HelpDrawer = () => {
26
+ export const HelpDrawerTrigger = () => {
30
27
  const os = useGetOs();
31
28
 
32
- const [open, setOpen] = React.useState<boolean>(false);
29
+ const keyboardShortcutsVisible = useCollaborationRoom(
30
+ (state) => state.drawer.keyboardShortcuts.visible
31
+ );
32
+ const setShowDrawer = useCollaborationRoom((state) => state.setShowDrawer);
33
33
 
34
- useKeyDown(
35
- () => {
36
- setOpen((prev) => !prev);
37
- },
38
- ['KeyK'],
39
- (e) => ([SYSTEM_OS.MAC as string].includes(os) ? e.metaKey : e.ctrlKey)
34
+ return (
35
+ <DropdownMenuItem
36
+ onClick={() => {
37
+ setShowDrawer(
38
+ DRAWER_ELEMENTS.keyboardShortcuts,
39
+ !keyboardShortcutsVisible
40
+ );
41
+ }}
42
+ className="w-full text-foreground cursor-pointer hover:rounded-none"
43
+ >
44
+ <Keyboard /> Keyboard shortcuts
45
+ <DropdownMenuShortcut>
46
+ {[SYSTEM_OS.MAC as string].includes(os) ? '⌘ K' : 'Ctrl K'}
47
+ </DropdownMenuShortcut>
48
+ </DropdownMenuItem>
40
49
  );
50
+ };
51
+
52
+ export const HelpDrawer = () => {
53
+ const keyboardShortcutsVisible = useCollaborationRoom(
54
+ (state) => state.drawer.keyboardShortcuts.visible
55
+ );
56
+ const setShowDrawer = useCollaborationRoom((state) => state.setShowDrawer);
57
+
58
+ const handleDrawer = React.useCallback(() => {
59
+ setShowDrawer(DRAWER_ELEMENTS.keyboardShortcuts, !keyboardShortcutsVisible);
60
+ }, [keyboardShortcutsVisible, setShowDrawer]);
41
61
 
42
62
  return (
43
- <Drawer modal={false} open={open} onOpenChange={setOpen}>
44
- <DrawerTrigger>
45
- <TooltipProvider delayDuration={300}>
46
- <Tooltip>
47
- <TooltipTrigger
48
- asChild
49
- className="pointer-events-auto cursor-pointer hover:text-black hover:bg-accent w-8 h-8 px-2 py-2"
50
- >
51
- <Keyboard />
52
- </TooltipTrigger>
53
- <TooltipContent side="top" align="end" className="rounded-none">
54
- <div className="flex flex-col gap-2 justify-start items-end">
55
- <p>Keyboard shortcuts</p>
56
- <ShortcutElement
57
- variant="light"
58
- shortcuts={{
59
- [SYSTEM_OS.MAC]: '⌘ K',
60
- [SYSTEM_OS.OTHER]: 'Ctrl K',
61
- }}
62
- />
63
- </div>
64
- </TooltipContent>
65
- </Tooltip>
66
- </TooltipProvider>
67
- </DrawerTrigger>
63
+ <Drawer
64
+ modal={false}
65
+ open={keyboardShortcutsVisible}
66
+ onOpenChange={handleDrawer}
67
+ >
68
68
  <DrawerContent className="p-0 !rounded-none bg-black flex flex-col justify-start items-center min-h-[330px]">
69
69
  <DrawerHeader className="w-[1024px] flex flex-row justify-between items-centers p-0 py-3">
70
70
  <DrawerTitle className="flex flex-row justify-start items-center text-center text-white font-questrial">
@@ -38,10 +38,6 @@ export const InputColor = ({
38
38
  setActualValue(e.target.value);
39
39
  };
40
40
 
41
- const handleBlur = () => {
42
- onChange(actualValue);
43
- };
44
-
45
41
  return (
46
42
  <div className="flex flex-col items-start justify-start relative">
47
43
  {label && (
@@ -63,6 +59,13 @@ export const InputColor = ({
63
59
  onChange={(color) => {
64
60
  onChange((color as string).slice(1));
65
61
  }}
62
+ onFocus={() => {
63
+ window.weaveOnFieldFocus = true;
64
+ }}
65
+ onBlurCapture={() => {
66
+ window.weaveOnFieldFocus = false;
67
+ onChange(actualValue);
68
+ }}
66
69
  >
67
70
  <ColorPickerSaturation />
68
71
  <div className="flex items-center gap-4">
@@ -85,7 +88,13 @@ export const InputColor = ({
85
88
  className="w-full py-0 h-[32px] rounded-none !text-xs font-normal text-gray-700 text-right focus:outline-none bg-transparent shadow-none"
86
89
  value={actualValue}
87
90
  onChange={handleInputChange}
88
- onBlur={handleBlur}
91
+ onFocus={() => {
92
+ window.weaveOnFieldFocus = true;
93
+ }}
94
+ onBlurCapture={() => {
95
+ window.weaveOnFieldFocus = false;
96
+ onChange(actualValue);
97
+ }}
89
98
  onKeyDown={(e) => {
90
99
  if (e.key === 'Enter') {
91
100
  e.preventDefault();
@@ -65,9 +65,16 @@ export function FillProperties() {
65
65
  return null;
66
66
  }
67
67
 
68
- if (actualNode.type !== 'rectangle') {
68
+ if (
69
+ actualAction &&
70
+ !['selectionTool', 'rectangleTool'].includes(actualAction)
71
+ )
72
+ return null;
73
+
74
+ if (!actualAction && !['rectangle'].includes(actualNode.type)) {
69
75
  return null;
70
76
  }
77
+
71
78
  return (
72
79
  <div className="border-b border-zinc-200">
73
80
  <div className="w-full flex justify-between items-center gap-3 p-4 py-3">
@@ -27,19 +27,41 @@ export const NodeProperties = () => {
27
27
  const setSidebarActive = useCollaborationRoom(
28
28
  (state) => state.setSidebarActive
29
29
  );
30
+ const setNodePropertiesAction = useCollaborationRoom(
31
+ (state) => state.setNodePropertiesAction
32
+ );
30
33
 
31
34
  const nodePropertiesAction = useCollaborationRoom(
32
35
  (state) => state.nodeProperties.action
33
36
  );
34
37
 
35
38
  React.useEffect(() => {
36
- if (node && sidebarRightActive !== SIDEBAR_ELEMENTS.nodeProperties) {
39
+ if (!instance) return;
40
+
41
+ if (
42
+ actualAction &&
43
+ [
44
+ 'rectangleTool',
45
+ 'brushTool',
46
+ 'penTool',
47
+ 'imageTool',
48
+ 'colorTokenTool',
49
+ 'frameTool',
50
+ ].includes(actualAction)
51
+ ) {
52
+ setNodePropertiesAction('create');
37
53
  setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
38
54
  }
39
- if (!node && sidebarRightActive === SIDEBAR_ELEMENTS.nodeProperties) {
55
+
56
+ if (!actualAction) {
57
+ setNodePropertiesAction(undefined);
40
58
  setSidebarActive(null, 'right');
41
59
  }
42
- }, [node, sidebarRightActive, setSidebarActive]);
60
+
61
+ if (node) {
62
+ setNodePropertiesAction('update');
63
+ }
64
+ }, [actualAction, node]);
43
65
 
44
66
  const nodeType = React.useMemo(() => {
45
67
  switch (node?.type) {
@@ -81,6 +103,18 @@ export const NodeProperties = () => {
81
103
  }
82
104
  }, [actualAction]);
83
105
 
106
+ React.useEffect(() => {
107
+ if (nodePropertiesAction === 'create' && actionType) {
108
+ setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
109
+ return;
110
+ }
111
+ if (node && nodePropertiesAction === 'update' && nodeType) {
112
+ setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
113
+ return;
114
+ }
115
+ setSidebarActive(null, 'right');
116
+ }, [node, sidebarRightActive, setSidebarActive]);
117
+
84
118
  const title = React.useMemo(() => {
85
119
  if (nodePropertiesAction === 'create') {
86
120
  return actionType;
@@ -12,13 +12,9 @@ import {
12
12
  DropdownMenuItem,
13
13
  DropdownMenuSeparator,
14
14
  DropdownMenuTrigger,
15
+ DropdownMenuShortcut,
16
+ DropdownMenuGroup,
15
17
  } from '@/components/ui/dropdown-menu';
16
- import {
17
- Tooltip,
18
- TooltipContent,
19
- TooltipProvider,
20
- TooltipTrigger,
21
- } from '@/components/ui/tooltip';
22
18
  import { Logo } from '@/components/utils/logo';
23
19
  import {
24
20
  Image as ImageIcon,
@@ -31,7 +27,6 @@ import {
31
27
  GripIcon,
32
28
  CheckIcon,
33
29
  Braces,
34
- Cog,
35
30
  } from 'lucide-react';
36
31
  import {
37
32
  WEAVE_GRID_TYPES,
@@ -44,10 +39,8 @@ import { topElementVariants } from './variants';
44
39
  import { DropdownMenuLabel } from '@radix-ui/react-dropdown-menu';
45
40
  import { ConnectedUsers } from '../connected-users';
46
41
  import { Divider } from './divider';
47
- import { ToolbarButton } from '../toolbar/toolbar-button';
48
- import { ShortcutElement } from '../help/shortcut-element';
49
42
  import { ZoomToolbar } from './zoom-toolbar';
50
- import { HelpDrawer } from '../help/help-drawer';
43
+ import { HelpDrawerTrigger } from '../help/help-drawer';
51
44
 
52
45
  export function RoomHeader() {
53
46
  const router = useRouter();
@@ -143,67 +136,6 @@ export function RoomHeader() {
143
136
  >
144
137
  <div className="w-full bg-white shadow-md flex justify-between items-center gap-0 px-3 rounded-xl border border-zinc-200">
145
138
  <div className="flex justify-start items-center gap-3">
146
- <div className="h-[60px] flex justify-start items-center">
147
- <Logo kind="small" />
148
- </div>
149
- <Divider />
150
- <div className="flex justify-start items-center gap-1">
151
- <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
152
- <div className="font-questrial text-lg">{room}</div>
153
- </div>
154
- </div>
155
- <Divider />
156
- <TooltipProvider delayDuration={300}>
157
- <Tooltip>
158
- <TooltipTrigger asChild>
159
- <button
160
- className="pointer-events-auto cursor-pointer font-questrial text-sm hover:text-zinc-200 !normal-case min-h-[32px]"
161
- onClick={handleExitRoom}
162
- >
163
- <LogOut />
164
- </button>
165
- </TooltipTrigger>
166
- <TooltipContent
167
- side="top"
168
- align="center"
169
- className="rounded-none"
170
- >
171
- Exit room
172
- </TooltipContent>
173
- </Tooltip>
174
- </TooltipProvider>
175
- </div>
176
- <div className="flex justify-end items-center gap-3">
177
- <ConnectionStatus weaveConnectionStatus={weaveConnectionStatus} />
178
- <Divider />
179
- <div className="max-w-[320px]">
180
- <ConnectedUsers />
181
- </div>
182
- <Divider />
183
- <ZoomToolbar />
184
- <Divider />
185
- <div className="flex justify-start items-center gap-0">
186
- <HelpDrawer />
187
- <ToolbarButton
188
- icon={<Braces />}
189
- onClick={handlePrintToConsoleState}
190
- label={
191
- <div className="flex flex-col gap-2 justify-start items-end">
192
- <p>Print model state to browser console</p>
193
- <ShortcutElement
194
- variant="light"
195
- shortcuts={{
196
- [SYSTEM_OS.MAC]: '⌥ ⌘ C',
197
- [SYSTEM_OS.OTHER]: 'Alt Ctrl C',
198
- }}
199
- />
200
- </div>
201
- }
202
- tooltipSide="top"
203
- tooltipAlign="end"
204
- />
205
- </div>
206
- <Divider />
207
139
  <DropdownMenu onOpenChange={(open: boolean) => setMenuOpen(open)}>
208
140
  <DropdownMenuTrigger
209
141
  className={cn(
@@ -214,20 +146,44 @@ export function RoomHeader() {
214
146
  }
215
147
  )}
216
148
  >
217
- <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
218
- <Cog />
149
+ <div className="flex gap-1 justify-start items-center">
150
+ <div className="h-[60px] flex justify-start items-center">
151
+ <Logo kind="small" variant="no-text" />
152
+ </div>
219
153
  {menuOpen ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
220
154
  </div>
221
155
  </DropdownMenuTrigger>
222
156
  <DropdownMenuContent
223
- align="end"
157
+ align="start"
224
158
  side="bottom"
225
159
  alignOffset={0}
226
160
  sideOffset={4}
227
161
  className="font-questrial rounded-none"
228
162
  >
229
163
  <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
230
- Grid Visibility
164
+ Debug
165
+ </DropdownMenuLabel>
166
+ <DropdownMenuGroup>
167
+ <DropdownMenuItem
168
+ className="text-foreground cursor-pointer hover:rounded-none w-full"
169
+ onClick={handlePrintToConsoleState}
170
+ >
171
+ <Braces /> Print state to console
172
+ <DropdownMenuShortcut>
173
+ {SYSTEM_OS.MAC ? '⌥ ⌘ C' : 'Alt Ctrl C'}
174
+ </DropdownMenuShortcut>
175
+ </DropdownMenuItem>
176
+ </DropdownMenuGroup>
177
+ <DropdownMenuSeparator />
178
+ <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
179
+ Interface
180
+ </DropdownMenuLabel>
181
+ <DropdownMenuGroup>
182
+ <HelpDrawerTrigger />
183
+ </DropdownMenuGroup>
184
+ <DropdownMenuSeparator />
185
+ <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
186
+ Grid
231
187
  </DropdownMenuLabel>
232
188
  <DropdownMenuItem
233
189
  className="text-foreground cursor-pointer hover:rounded-none"
@@ -244,9 +200,6 @@ export function RoomHeader() {
244
200
  </>
245
201
  )}
246
202
  </DropdownMenuItem>
247
- <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
248
- Grid Kind
249
- </DropdownMenuLabel>
250
203
  <DropdownMenuItem
251
204
  disabled={
252
205
  !gridEnabled ||
@@ -291,8 +244,31 @@ export function RoomHeader() {
291
244
  >
292
245
  <ImageIcon /> Stage to image
293
246
  </DropdownMenuItem>
247
+ <DropdownMenuSeparator />
248
+ <DropdownMenuItem
249
+ className="text-foreground cursor-pointer hover:rounded-none"
250
+ onClick={handleExitRoom}
251
+ >
252
+ <LogOut /> Exit room
253
+ </DropdownMenuItem>
294
254
  </DropdownMenuContent>
295
255
  </DropdownMenu>
256
+ <div className="flex justify-start items-center gap-1">
257
+ <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
258
+ <div className="font-questrial text-2xl font-extralight">
259
+ {room}
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ <div className="flex justify-end items-center gap-3">
265
+ <ConnectionStatus weaveConnectionStatus={weaveConnectionStatus} />
266
+ <Divider />
267
+ <div className="max-w-[320px]">
268
+ <ConnectedUsers />
269
+ </div>
270
+ <Divider />
271
+ <ZoomToolbar />
296
272
  </div>
297
273
  </div>
298
274
  </motion.div>
@@ -1,7 +1,11 @@
1
1
  export const SIDEBAR_ELEMENTS = {
2
- images: "images",
3
- frames: "frames",
4
- colorTokens: "colorTokens",
5
- nodesTree: "nodesTree",
6
- nodeProperties: "nodeProperties",
2
+ images: 'images',
3
+ frames: 'frames',
4
+ colorTokens: 'colorTokens',
5
+ nodesTree: 'nodesTree',
6
+ nodeProperties: 'nodeProperties',
7
+ } as const;
8
+
9
+ export const DRAWER_ELEMENTS = {
10
+ keyboardShortcuts: 'keyboardShortcuts',
7
11
  } as const;
@@ -2,7 +2,7 @@ import { Vector2d } from 'konva/lib/types';
2
2
  import { create } from 'zustand';
3
3
  import { ContextMenuOption } from '@/components/room-components/context-menu';
4
4
  import { WeaveElementAttributes } from '@inditextech/weave-types';
5
- import { SIDEBAR_ELEMENTS } from '@/lib/constants';
5
+ import { DRAWER_ELEMENTS, SIDEBAR_ELEMENTS } from '@/lib/constants';
6
6
 
7
7
  type ShowcaseUser = {
8
8
  name: string;
@@ -13,6 +13,9 @@ type NodePropertiesAction = 'create' | 'update' | undefined;
13
13
 
14
14
  type FinishUploadCallback = (imageURL: string) => void;
15
15
 
16
+ type DrawerKeyKeys = keyof typeof DRAWER_ELEMENTS;
17
+ export type DrawerKey = (typeof DRAWER_ELEMENTS)[DrawerKeyKeys];
18
+
16
19
  type SidebarActiveKeys = keyof typeof SIDEBAR_ELEMENTS;
17
20
  export type SidebarActive = (typeof SIDEBAR_ELEMENTS)[SidebarActiveKeys] | null;
18
21
 
@@ -24,6 +27,11 @@ interface CollaborationRoomState {
24
27
  ui: {
25
28
  show: boolean;
26
29
  };
30
+ drawer: {
31
+ keyboardShortcuts: {
32
+ visible: boolean;
33
+ };
34
+ };
27
35
  sidebar: {
28
36
  left: {
29
37
  active: SidebarActive;
@@ -77,6 +85,7 @@ interface CollaborationRoomState {
77
85
  newSidebarActive: SidebarActive,
78
86
  position?: 'left' | 'right'
79
87
  ) => void;
88
+ setShowDrawer: (drawerKey: DrawerKey, newOpen: boolean) => void;
80
89
  }
81
90
 
82
91
  export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
@@ -97,6 +106,11 @@ export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
97
106
  active: null,
98
107
  },
99
108
  },
109
+ drawer: {
110
+ keyboardShortcuts: {
111
+ visible: false,
112
+ },
113
+ },
100
114
  contextMenu: {
101
115
  show: false,
102
116
  position: { x: 0, y: 0 },
@@ -220,4 +234,15 @@ export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
220
234
  },
221
235
  },
222
236
  })),
237
+ setShowDrawer: (drawerKey, newOpen) =>
238
+ set((state) => ({
239
+ ...state,
240
+ drawer: {
241
+ ...state.drawer,
242
+ [drawerKey]: {
243
+ ...state.drawer[drawerKey],
244
+ visible: newOpen,
245
+ },
246
+ },
247
+ })),
223
248
  }));
@@ -14,6 +14,7 @@ import useGetWsProvider from '../room-components/hooks/use-get-websockets-provid
14
14
  import useHandleRouteParams from '../room-components/hooks/use-handle-route-params';
15
15
  import { UploadFile } from '../room-components/upload-file';
16
16
  import UserForm from '../room-components/user-form';
17
+ import { HelpDrawer } from '../room-components/help/help-drawer';
17
18
 
18
19
  const statusMap = {
19
20
  ['idle']: 'Idle',
@@ -109,6 +110,7 @@ export const Room = () => {
109
110
  >
110
111
  <UploadFile />
111
112
  <RoomLayout />
113
+ <HelpDrawer />
112
114
  </WeaveProvider>
113
115
  )}
114
116
  <Toaster />
@@ -1,70 +1,70 @@
1
1
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
2
2
  import {
3
- Tooltip,
4
- TooltipContent,
5
- TooltipProvider,
6
- TooltipTrigger,
7
- } from '@/components/ui/tooltip';
3
+ DropdownMenuItem,
4
+ DropdownMenuShortcut,
5
+ } from '@/components/ui/dropdown-menu';
8
6
  import {
9
7
  Drawer,
10
8
  DrawerClose,
11
9
  DrawerContent,
12
10
  DrawerHeader,
13
11
  DrawerTitle,
14
- DrawerTrigger,
15
12
  } from '@/components/ui/drawer';
16
13
  import { Keyboard, XIcon } from 'lucide-react';
17
14
  import { SYSTEM_OS } from '@/lib/utils';
18
15
  import { HelpTools } from './help-tools';
19
- import { ShortcutElement } from './shortcut-element';
20
16
  import React from 'react';
21
- import { useKeyDown } from '../hooks/use-key-down';
22
17
  import { useGetOs } from '../hooks/use-get-os';
23
18
  import { HelpZoom } from './help-zoom';
24
19
  import { HelpView } from './help-view';
25
20
  import { HelpSelection } from './help-selection';
26
21
  import { HelpEdit } from './help-edit';
27
22
  import { HelpArrange } from './help-arrange';
23
+ import { useCollaborationRoom } from '@/store/store';
24
+ import { DRAWER_ELEMENTS } from '@/lib/constants';
28
25
 
29
- export const HelpDrawer = () => {
26
+ export const HelpDrawerTrigger = () => {
30
27
  const os = useGetOs();
31
28
 
32
- const [open, setOpen] = React.useState<boolean>(false);
29
+ const keyboardShortcutsVisible = useCollaborationRoom(
30
+ (state) => state.drawer.keyboardShortcuts.visible
31
+ );
32
+ const setShowDrawer = useCollaborationRoom((state) => state.setShowDrawer);
33
33
 
34
- useKeyDown(
35
- () => {
36
- setOpen((prev) => !prev);
37
- },
38
- ['KeyK'],
39
- (e) => ([SYSTEM_OS.MAC as string].includes(os) ? e.metaKey : e.ctrlKey)
34
+ return (
35
+ <DropdownMenuItem
36
+ onClick={() => {
37
+ setShowDrawer(
38
+ DRAWER_ELEMENTS.keyboardShortcuts,
39
+ !keyboardShortcutsVisible
40
+ );
41
+ }}
42
+ className="w-full text-foreground cursor-pointer hover:rounded-none"
43
+ >
44
+ <Keyboard /> Keyboard shortcuts
45
+ <DropdownMenuShortcut>
46
+ {[SYSTEM_OS.MAC as string].includes(os) ? '⌘ K' : 'Ctrl K'}
47
+ </DropdownMenuShortcut>
48
+ </DropdownMenuItem>
40
49
  );
50
+ };
51
+
52
+ export const HelpDrawer = () => {
53
+ const keyboardShortcutsVisible = useCollaborationRoom(
54
+ (state) => state.drawer.keyboardShortcuts.visible
55
+ );
56
+ const setShowDrawer = useCollaborationRoom((state) => state.setShowDrawer);
57
+
58
+ const handleDrawer = React.useCallback(() => {
59
+ setShowDrawer(DRAWER_ELEMENTS.keyboardShortcuts, !keyboardShortcutsVisible);
60
+ }, [keyboardShortcutsVisible, setShowDrawer]);
41
61
 
42
62
  return (
43
- <Drawer modal={false} open={open} onOpenChange={setOpen}>
44
- <DrawerTrigger>
45
- <TooltipProvider delayDuration={300}>
46
- <Tooltip>
47
- <TooltipTrigger
48
- asChild
49
- className="pointer-events-auto cursor-pointer hover:text-black hover:bg-accent w-8 h-8 px-2 py-2"
50
- >
51
- <Keyboard />
52
- </TooltipTrigger>
53
- <TooltipContent side="top" align="end" className="rounded-none">
54
- <div className="flex flex-col gap-2 justify-start items-end">
55
- <p>Keyboard shortcuts</p>
56
- <ShortcutElement
57
- variant="light"
58
- shortcuts={{
59
- [SYSTEM_OS.MAC]: '⌘ K',
60
- [SYSTEM_OS.OTHER]: 'Ctrl K',
61
- }}
62
- />
63
- </div>
64
- </TooltipContent>
65
- </Tooltip>
66
- </TooltipProvider>
67
- </DrawerTrigger>
63
+ <Drawer
64
+ modal={false}
65
+ open={keyboardShortcutsVisible}
66
+ onOpenChange={handleDrawer}
67
+ >
68
68
  <DrawerContent className="p-0 !rounded-none bg-black flex flex-col justify-start items-center min-h-[330px]">
69
69
  <DrawerHeader className="w-[1024px] flex flex-row justify-between items-centers p-0 py-3">
70
70
  <DrawerTitle className="flex flex-row justify-start items-center text-center text-white font-questrial">
@@ -38,10 +38,6 @@ export const InputColor = ({
38
38
  setActualValue(e.target.value);
39
39
  };
40
40
 
41
- const handleBlur = () => {
42
- onChange(actualValue);
43
- };
44
-
45
41
  return (
46
42
  <div className="flex flex-col items-start justify-start relative">
47
43
  {label && (
@@ -63,6 +59,13 @@ export const InputColor = ({
63
59
  onChange={(color) => {
64
60
  onChange((color as string).slice(1));
65
61
  }}
62
+ onFocus={() => {
63
+ window.weaveOnFieldFocus = true;
64
+ }}
65
+ onBlurCapture={() => {
66
+ window.weaveOnFieldFocus = false;
67
+ onChange(actualValue);
68
+ }}
66
69
  >
67
70
  <ColorPickerSaturation />
68
71
  <div className="flex items-center gap-4">
@@ -85,7 +88,13 @@ export const InputColor = ({
85
88
  className="w-full py-0 h-[32px] rounded-none !text-xs font-normal text-gray-700 text-right focus:outline-none bg-transparent shadow-none"
86
89
  value={actualValue}
87
90
  onChange={handleInputChange}
88
- onBlur={handleBlur}
91
+ onFocus={() => {
92
+ window.weaveOnFieldFocus = true;
93
+ }}
94
+ onBlurCapture={() => {
95
+ window.weaveOnFieldFocus = false;
96
+ onChange(actualValue);
97
+ }}
89
98
  onKeyDown={(e) => {
90
99
  if (e.key === 'Enter') {
91
100
  e.preventDefault();
@@ -65,9 +65,16 @@ export function FillProperties() {
65
65
  return null;
66
66
  }
67
67
 
68
- if (actualNode.type !== 'rectangle') {
68
+ if (
69
+ actualAction &&
70
+ !['selectionTool', 'rectangleTool'].includes(actualAction)
71
+ )
72
+ return null;
73
+
74
+ if (!actualAction && !['rectangle'].includes(actualNode.type)) {
69
75
  return null;
70
76
  }
77
+
71
78
  return (
72
79
  <div className="border-b border-zinc-200">
73
80
  <div className="w-full flex justify-between items-center gap-3 p-4 py-3">
@@ -27,19 +27,41 @@ export const NodeProperties = () => {
27
27
  const setSidebarActive = useCollaborationRoom(
28
28
  (state) => state.setSidebarActive
29
29
  );
30
+ const setNodePropertiesAction = useCollaborationRoom(
31
+ (state) => state.setNodePropertiesAction
32
+ );
30
33
 
31
34
  const nodePropertiesAction = useCollaborationRoom(
32
35
  (state) => state.nodeProperties.action
33
36
  );
34
37
 
35
38
  React.useEffect(() => {
36
- if (node && sidebarRightActive !== SIDEBAR_ELEMENTS.nodeProperties) {
39
+ if (!instance) return;
40
+
41
+ if (
42
+ actualAction &&
43
+ [
44
+ 'rectangleTool',
45
+ 'brushTool',
46
+ 'penTool',
47
+ 'imageTool',
48
+ 'colorTokenTool',
49
+ 'frameTool',
50
+ ].includes(actualAction)
51
+ ) {
52
+ setNodePropertiesAction('create');
37
53
  setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
38
54
  }
39
- if (!node && sidebarRightActive === SIDEBAR_ELEMENTS.nodeProperties) {
55
+
56
+ if (!actualAction) {
57
+ setNodePropertiesAction(undefined);
40
58
  setSidebarActive(null, 'right');
41
59
  }
42
- }, [node, sidebarRightActive, setSidebarActive]);
60
+
61
+ if (node) {
62
+ setNodePropertiesAction('update');
63
+ }
64
+ }, [actualAction, node]);
43
65
 
44
66
  const nodeType = React.useMemo(() => {
45
67
  switch (node?.type) {
@@ -81,6 +103,18 @@ export const NodeProperties = () => {
81
103
  }
82
104
  }, [actualAction]);
83
105
 
106
+ React.useEffect(() => {
107
+ if (nodePropertiesAction === 'create' && actionType) {
108
+ setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
109
+ return;
110
+ }
111
+ if (node && nodePropertiesAction === 'update' && nodeType) {
112
+ setSidebarActive(SIDEBAR_ELEMENTS.nodeProperties, 'right');
113
+ return;
114
+ }
115
+ setSidebarActive(null, 'right');
116
+ }, [node, sidebarRightActive, setSidebarActive]);
117
+
84
118
  const title = React.useMemo(() => {
85
119
  if (nodePropertiesAction === 'create') {
86
120
  return actionType;
@@ -12,13 +12,9 @@ import {
12
12
  DropdownMenuItem,
13
13
  DropdownMenuSeparator,
14
14
  DropdownMenuTrigger,
15
+ DropdownMenuShortcut,
16
+ DropdownMenuGroup,
15
17
  } from '@/components/ui/dropdown-menu';
16
- import {
17
- Tooltip,
18
- TooltipContent,
19
- TooltipProvider,
20
- TooltipTrigger,
21
- } from '@/components/ui/tooltip';
22
18
  import { Logo } from '@/components/utils/logo';
23
19
  import {
24
20
  Image as ImageIcon,
@@ -31,7 +27,6 @@ import {
31
27
  GripIcon,
32
28
  CheckIcon,
33
29
  Braces,
34
- Cog,
35
30
  } from 'lucide-react';
36
31
  import {
37
32
  WEAVE_GRID_TYPES,
@@ -44,10 +39,8 @@ import { topElementVariants } from './variants';
44
39
  import { DropdownMenuLabel } from '@radix-ui/react-dropdown-menu';
45
40
  import { ConnectedUsers } from '../connected-users';
46
41
  import { Divider } from './divider';
47
- import { ToolbarButton } from '../toolbar/toolbar-button';
48
- import { ShortcutElement } from '../help/shortcut-element';
49
42
  import { ZoomToolbar } from './zoom-toolbar';
50
- import { HelpDrawer } from '../help/help-drawer';
43
+ import { HelpDrawerTrigger } from '../help/help-drawer';
51
44
 
52
45
  export function RoomHeader() {
53
46
  const router = useRouter();
@@ -143,67 +136,6 @@ export function RoomHeader() {
143
136
  >
144
137
  <div className="w-full bg-white shadow-md flex justify-between items-center gap-0 px-3 rounded-xl border border-zinc-200">
145
138
  <div className="flex justify-start items-center gap-3">
146
- <div className="h-[60px] flex justify-start items-center">
147
- <Logo kind="small" />
148
- </div>
149
- <Divider />
150
- <div className="flex justify-start items-center gap-1">
151
- <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
152
- <div className="font-questrial text-lg">{room}</div>
153
- </div>
154
- </div>
155
- <Divider />
156
- <TooltipProvider delayDuration={300}>
157
- <Tooltip>
158
- <TooltipTrigger asChild>
159
- <button
160
- className="pointer-events-auto cursor-pointer font-questrial text-sm hover:text-zinc-200 !normal-case min-h-[32px]"
161
- onClick={handleExitRoom}
162
- >
163
- <LogOut />
164
- </button>
165
- </TooltipTrigger>
166
- <TooltipContent
167
- side="top"
168
- align="center"
169
- className="rounded-none"
170
- >
171
- Exit room
172
- </TooltipContent>
173
- </Tooltip>
174
- </TooltipProvider>
175
- </div>
176
- <div className="flex justify-end items-center gap-3">
177
- <ConnectionStatus weaveConnectionStatus={weaveConnectionStatus} />
178
- <Divider />
179
- <div className="max-w-[320px]">
180
- <ConnectedUsers />
181
- </div>
182
- <Divider />
183
- <ZoomToolbar />
184
- <Divider />
185
- <div className="flex justify-start items-center gap-0">
186
- <HelpDrawer />
187
- <ToolbarButton
188
- icon={<Braces />}
189
- onClick={handlePrintToConsoleState}
190
- label={
191
- <div className="flex flex-col gap-2 justify-start items-end">
192
- <p>Print model state to browser console</p>
193
- <ShortcutElement
194
- variant="light"
195
- shortcuts={{
196
- [SYSTEM_OS.MAC]: '⌥ ⌘ C',
197
- [SYSTEM_OS.OTHER]: 'Alt Ctrl C',
198
- }}
199
- />
200
- </div>
201
- }
202
- tooltipSide="top"
203
- tooltipAlign="end"
204
- />
205
- </div>
206
- <Divider />
207
139
  <DropdownMenu onOpenChange={(open: boolean) => setMenuOpen(open)}>
208
140
  <DropdownMenuTrigger
209
141
  className={cn(
@@ -214,20 +146,44 @@ export function RoomHeader() {
214
146
  }
215
147
  )}
216
148
  >
217
- <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
218
- <Cog />
149
+ <div className="flex gap-1 justify-start items-center">
150
+ <div className="h-[60px] flex justify-start items-center">
151
+ <Logo kind="small" variant="no-text" />
152
+ </div>
219
153
  {menuOpen ? <ChevronUp size={16} /> : <ChevronDown size={16} />}
220
154
  </div>
221
155
  </DropdownMenuTrigger>
222
156
  <DropdownMenuContent
223
- align="end"
157
+ align="start"
224
158
  side="bottom"
225
159
  alignOffset={0}
226
160
  sideOffset={4}
227
161
  className="font-questrial rounded-none"
228
162
  >
229
163
  <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
230
- Grid Visibility
164
+ Debug
165
+ </DropdownMenuLabel>
166
+ <DropdownMenuGroup>
167
+ <DropdownMenuItem
168
+ className="text-foreground cursor-pointer hover:rounded-none w-full"
169
+ onClick={handlePrintToConsoleState}
170
+ >
171
+ <Braces /> Print state to console
172
+ <DropdownMenuShortcut>
173
+ {SYSTEM_OS.MAC ? '⌥ ⌘ C' : 'Alt Ctrl C'}
174
+ </DropdownMenuShortcut>
175
+ </DropdownMenuItem>
176
+ </DropdownMenuGroup>
177
+ <DropdownMenuSeparator />
178
+ <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
179
+ Interface
180
+ </DropdownMenuLabel>
181
+ <DropdownMenuGroup>
182
+ <HelpDrawerTrigger />
183
+ </DropdownMenuGroup>
184
+ <DropdownMenuSeparator />
185
+ <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
186
+ Grid
231
187
  </DropdownMenuLabel>
232
188
  <DropdownMenuItem
233
189
  className="text-foreground cursor-pointer hover:rounded-none"
@@ -244,9 +200,6 @@ export function RoomHeader() {
244
200
  </>
245
201
  )}
246
202
  </DropdownMenuItem>
247
- <DropdownMenuLabel className="px-2 py-1 pt-2 text-zinc-600 text-xs">
248
- Grid Kind
249
- </DropdownMenuLabel>
250
203
  <DropdownMenuItem
251
204
  disabled={
252
205
  !gridEnabled ||
@@ -291,8 +244,31 @@ export function RoomHeader() {
291
244
  >
292
245
  <ImageIcon /> Stage to image
293
246
  </DropdownMenuItem>
247
+ <DropdownMenuSeparator />
248
+ <DropdownMenuItem
249
+ className="text-foreground cursor-pointer hover:rounded-none"
250
+ onClick={handleExitRoom}
251
+ >
252
+ <LogOut /> Exit room
253
+ </DropdownMenuItem>
294
254
  </DropdownMenuContent>
295
255
  </DropdownMenu>
256
+ <div className="flex justify-start items-center gap-1">
257
+ <div className="flex justify-start items-center gap-2 font-questrial text-foreground !normal-case min-h-[32px]">
258
+ <div className="font-questrial text-2xl font-extralight">
259
+ {room}
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ <div className="flex justify-end items-center gap-3">
265
+ <ConnectionStatus weaveConnectionStatus={weaveConnectionStatus} />
266
+ <Divider />
267
+ <div className="max-w-[320px]">
268
+ <ConnectedUsers />
269
+ </div>
270
+ <Divider />
271
+ <ZoomToolbar />
296
272
  </div>
297
273
  </div>
298
274
  </motion.div>
@@ -1,7 +1,11 @@
1
1
  export const SIDEBAR_ELEMENTS = {
2
- images: "images",
3
- frames: "frames",
4
- colorTokens: "colorTokens",
5
- nodesTree: "nodesTree",
6
- nodeProperties: "nodeProperties",
2
+ images: 'images',
3
+ frames: 'frames',
4
+ colorTokens: 'colorTokens',
5
+ nodesTree: 'nodesTree',
6
+ nodeProperties: 'nodeProperties',
7
+ } as const;
8
+
9
+ export const DRAWER_ELEMENTS = {
10
+ keyboardShortcuts: 'keyboardShortcuts',
7
11
  } as const;
@@ -2,7 +2,7 @@ import { Vector2d } from 'konva/lib/types';
2
2
  import { create } from 'zustand';
3
3
  import { ContextMenuOption } from '@/components/room-components/context-menu';
4
4
  import { WeaveElementAttributes } from '@inditextech/weave-types';
5
- import { SIDEBAR_ELEMENTS } from '@/lib/constants';
5
+ import { DRAWER_ELEMENTS, SIDEBAR_ELEMENTS } from '@/lib/constants';
6
6
 
7
7
  type ShowcaseUser = {
8
8
  name: string;
@@ -13,6 +13,9 @@ type NodePropertiesAction = 'create' | 'update' | undefined;
13
13
 
14
14
  type FinishUploadCallback = (imageURL: string) => void;
15
15
 
16
+ type DrawerKeyKeys = keyof typeof DRAWER_ELEMENTS;
17
+ export type DrawerKey = (typeof DRAWER_ELEMENTS)[DrawerKeyKeys];
18
+
16
19
  type SidebarActiveKeys = keyof typeof SIDEBAR_ELEMENTS;
17
20
  export type SidebarActive = (typeof SIDEBAR_ELEMENTS)[SidebarActiveKeys] | null;
18
21
 
@@ -24,6 +27,11 @@ interface CollaborationRoomState {
24
27
  ui: {
25
28
  show: boolean;
26
29
  };
30
+ drawer: {
31
+ keyboardShortcuts: {
32
+ visible: boolean;
33
+ };
34
+ };
27
35
  sidebar: {
28
36
  left: {
29
37
  active: SidebarActive;
@@ -77,6 +85,7 @@ interface CollaborationRoomState {
77
85
  newSidebarActive: SidebarActive,
78
86
  position?: 'left' | 'right'
79
87
  ) => void;
88
+ setShowDrawer: (drawerKey: DrawerKey, newOpen: boolean) => void;
80
89
  }
81
90
 
82
91
  export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
@@ -97,6 +106,11 @@ export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
97
106
  active: null,
98
107
  },
99
108
  },
109
+ drawer: {
110
+ keyboardShortcuts: {
111
+ visible: false,
112
+ },
113
+ },
100
114
  contextMenu: {
101
115
  show: false,
102
116
  position: { x: 0, y: 0 },
@@ -220,4 +234,15 @@ export const useCollaborationRoom = create<CollaborationRoomState>()((set) => ({
220
234
  },
221
235
  },
222
236
  })),
237
+ setShowDrawer: (drawerKey, newOpen) =>
238
+ set((state) => ({
239
+ ...state,
240
+ drawer: {
241
+ ...state.drawer,
242
+ [drawerKey]: {
243
+ ...state.drawer[drawerKey],
244
+ visible: newOpen,
245
+ },
246
+ },
247
+ })),
223
248
  }));