diff --git a/package.json b/package.json index 3ef40e36..06d8f9b5 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-toggle-group": "^1.1.0", + "@radix-ui/react-tooltip": "^1.2.3", "@remotion/media-utils": "4.0.221", "@remotion/paths": "4.0.221", "@remotion/player": "4.0.221", @@ -58,6 +59,7 @@ "react-resizable-panels": "^2.1.3", "react-router-dom": "^6.26.2", "remotion": "4.0.221", + "rxjs": "^7.8.2", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "tinycolor2": "^1.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ccd45f4..40140b03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -83,6 +83,9 @@ importers: '@radix-ui/react-toggle-group': specifier: ^1.1.0 version: 1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-tooltip': + specifier: ^1.2.3 + version: 1.2.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@remotion/media-utils': specifier: 4.0.221 version: 4.0.221(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -152,6 +155,9 @@ importers: remotion: specifier: 4.0.221 version: 4.0.221(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + rxjs: + specifier: ^7.8.2 + version: 7.8.2 tailwind-merge: specifier: ^2.5.2 version: 2.5.2 @@ -680,6 +686,9 @@ packages: '@radix-ui/primitive@1.1.1': resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} + '@radix-ui/primitive@1.1.2': + resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} + '@radix-ui/react-arrow@1.1.2': resolution: {integrity: sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg==} peerDependencies: @@ -693,6 +702,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-arrow@1.1.4': + resolution: {integrity: sha512-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-avatar@1.1.3': resolution: {integrity: sha512-Paen00T4P8L8gd9bNsRMw7Cbaz85oxiv+hzomsRZgFm2byltPFDtfcoqlWJ8GyZlIBWgLssJlzLCnKU0G0302g==} peerDependencies: @@ -728,6 +750,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-context@1.1.1': resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} peerDependencies: @@ -737,6 +768,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dialog@1.1.6': resolution: {integrity: sha512-/IVhJV5AceX620DUJ4uYVMymzsipdKBzo3edo+omeskCKGm9FRHM0ebIdbPnlQVJqyuHbuBltQUOG2mOTq2IYw==} peerDependencies: @@ -772,6 +812,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dismissable-layer@1.1.7': + resolution: {integrity: sha512-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-dropdown-menu@2.1.6': resolution: {integrity: sha512-no3X7V5fD487wab/ZYSHXq3H37u4NVeLDKI/Ks724X/eEFSSEFYZxWgsIlr1UBeEyDaM29HM5x9p1Nv8DuTYPA==} peerDependencies: @@ -821,6 +874,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-label@2.1.2': resolution: {integrity: sha512-zo1uGMTaNlHehDyFQcDZXRJhUPDuukcnHz0/jnrup0JA6qL+AFpAnty+7VKa9esuU5xTblAZzTGYJKSKaBxBhw==} peerDependencies: @@ -873,6 +935,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popper@1.2.4': + resolution: {integrity: sha512-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-portal@1.1.4': resolution: {integrity: sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA==} peerDependencies: @@ -886,6 +961,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-portal@1.1.6': + resolution: {integrity: sha512-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-presence@1.1.2': resolution: {integrity: sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==} peerDependencies: @@ -899,6 +987,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-presence@1.1.3': + resolution: {integrity: sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@2.0.2': resolution: {integrity: sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==} peerDependencies: @@ -912,6 +1013,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-primitive@2.1.0': + resolution: {integrity: sha512-/J/FhLdK0zVcILOwt5g+dH4KnkonCtkVJsa2G6JmvbbtZfBEI1gMsO3QMjseL4F/SwfAMt1Vc/0XKYKq+xJ1sw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-progress@1.1.2': resolution: {integrity: sha512-u1IgJFQ4zNAUTjGdDL5dcl/U8ntOR6jsnhxKb5RKp5Ozwl88xKR9EqRZOe/Mk8tnx0x5tNUe2F+MzsyjqMg0MA==} peerDependencies: @@ -986,6 +1100,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.2.0': + resolution: {integrity: sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-tabs@1.1.3': resolution: {integrity: sha512-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng==} peerDependencies: @@ -1025,6 +1148,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-tooltip@1.2.3': + resolution: {integrity: sha512-0KX7jUYFA02np01Y11NWkk6Ip6TqMNmD4ijLelYAzeIndl2aVeltjJFJ2gwjNa1P8U/dgjQ+8cr9Y3Ni+ZNoRA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-use-callback-ref@1.1.0': resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} peerDependencies: @@ -1034,6 +1170,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-controllable-state@1.1.0': resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} peerDependencies: @@ -1043,6 +1188,24 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-escape-keydown@1.1.0': resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} peerDependencies: @@ -1052,6 +1215,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-layout-effect@1.1.0': resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} peerDependencies: @@ -1061,6 +1233,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-previous@1.1.0': resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==} peerDependencies: @@ -1079,6 +1260,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-size@1.1.0': resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} peerDependencies: @@ -1088,6 +1278,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-visually-hidden@1.1.2': resolution: {integrity: sha512-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q==} peerDependencies: @@ -1101,9 +1300,25 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-visually-hidden@1.2.0': + resolution: {integrity: sha512-rQj0aAWOpCdCMRbI6pLQm8r7S2BM3YhTa0SzOYD55k+hJA8oo9J+H+9wLM9oMlZWOX/wJWPTzfDfmZkf7LvCfg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/rect@1.1.0': resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@remix-run/router@1.22.0': resolution: {integrity: sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==} engines: {node: '>=14.0.0'} @@ -2548,8 +2763,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -3066,7 +3281,7 @@ snapshots: '@designcombo/events@1.0.2': dependencies: - rxjs: 7.8.1 + rxjs: 7.8.2 '@designcombo/frames@0.0.3': dependencies: @@ -3086,7 +3301,7 @@ snapshots: lodash.pick: 4.4.0 microdiff: 1.5.0 nanoid: 5.0.9 - rxjs: 7.8.1 + rxjs: 7.8.2 '@designcombo/timeline@3.1.13(@designcombo/events@1.0.2)(@designcombo/types@3.1.13)(@types/lodash-es@4.17.12)': dependencies: @@ -3106,7 +3321,7 @@ snapshots: '@designcombo/types@3.1.13': dependencies: - rxjs: 7.8.1 + rxjs: 7.8.2 '@egjs/agent@2.4.4': {} @@ -3437,6 +3652,8 @@ snapshots: '@radix-ui/primitive@1.1.1': {} + '@radix-ui/primitive@1.1.2': {} + '@radix-ui/react-arrow@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3446,6 +3663,15 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-arrow@1.1.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-avatar@1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-context': 1.1.1(@types/react@18.3.8)(react@18.3.1) @@ -3476,12 +3702,24 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.8)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-context@1.1.1(@types/react@18.3.8)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-context@1.1.2(@types/react@18.3.8)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-dialog@1.1.6(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 @@ -3523,6 +3761,19 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-dismissable-layer@1.1.7(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-dropdown-menu@2.1.6(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 @@ -3566,6 +3817,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-id@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-label@2.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3642,6 +3900,24 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-popper@1.2.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-portal@1.1.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3652,6 +3928,16 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-portal@1.1.6(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-presence@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.8)(react@18.3.1) @@ -3662,6 +3948,16 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-presence@1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive@2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-slot': 1.1.2(@types/react@18.3.8)(react@18.3.1) @@ -3671,6 +3967,15 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-primitive@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.2.0(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-progress@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-context': 1.1.1(@types/react@18.3.8)(react@18.3.1) @@ -3770,6 +4075,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-slot@1.2.0(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-tabs@1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.1 @@ -3812,12 +4124,38 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-tooltip@1.2.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.2 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.7(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-popper': 1.2.4(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.6(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.3(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.0(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) @@ -3825,6 +4163,21 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.8)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.8)(react@18.3.1) @@ -3832,12 +4185,25 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: react: 18.3.1 @@ -3851,6 +4217,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-use-size@1.1.0(@types/react@18.3.8)(react@18.3.1)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.8)(react@18.3.1) @@ -3858,6 +4231,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.8 + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.8)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.8)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.8 + '@radix-ui/react-visually-hidden@1.1.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-primitive': 2.0.2(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -3867,8 +4247,19 @@ snapshots: '@types/react': 18.3.8 '@types/react-dom': 18.3.0 + '@radix-ui/react-visually-hidden@1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.8 + '@types/react-dom': 18.3.0 + '@radix-ui/rect@1.1.0': {} + '@radix-ui/rect@1.1.1': {} + '@remix-run/router@1.22.0': {} '@remotion/media-utils@4.0.221(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -5304,7 +5695,7 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rxjs@7.8.1: + rxjs@7.8.2: dependencies: tslib: 2.8.1 diff --git a/src/components/button.tsx b/src/components/button.tsx index 14bb814a..9493c1dd 100644 --- a/src/components/button.tsx +++ b/src/components/button.tsx @@ -1,37 +1,37 @@ -import { cn } from "@/lib/utils"; -import React from "react"; +import { cn } from '@/lib/utils'; +import type React from 'react'; export const Button: React.FC<{ children?: React.ReactNode; className?: string; - variant?: "simple" | "outline" | "primary"; + variant?: 'simple' | 'outline' | 'primary'; as?: React.ElementType; [x: string]: any; }> = ({ children, className, - variant = "primary", - as: Tag = "button", + variant = 'primary', + as: Tag = 'button', ...props }) => { const variantClass = - variant === "simple" - ? "bg-black relative z-10 bg-transparent hover:bg-gray-100 border border-transparent text-black text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center dark:text-white dark:hover:bg-neutral-800 dark:hover:shadow-xl" - : variant === "outline" - ? "bg-white relative z-10 hover:bg-black/90 hover:shadow-xl text-black border border-black hover:text-white text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center" - : variant === "primary" - ? "bg-neutral-900 relative z-10 hover:bg-black/90 border border-transparent text-white text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center shadow-[0px_-1px_0px_0px_#FFFFFF40_inset,_0px_1px_0px_0px_#FFFFFF40_inset]" - : ""; + variant === 'simple' + ? 'bg-black relative z-10 bg-transparent hover:bg-gray-100 border border-transparent text-black text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center dark:text-white dark:hover:bg-neutral-800 dark:hover:shadow-xl' + : variant === 'outline' + ? 'bg-white relative z-10 hover:bg-black/90 hover:shadow-xl text-black border border-black hover:text-white text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center' + : variant === 'primary' + ? 'bg-neutral-900 relative z-10 hover:bg-black/90 border border-transparent text-white text-sm md:text-sm transition font-medium duration-200 rounded-full px-4 py-2 flex items-center justify-center shadow-[0px_-1px_0px_0px_#FFFFFF40_inset,_0px_1px_0px_0px_#FFFFFF40_inset]' + : ''; return ( - {children ?? `Get Started`} + {children ?? 'Get Started'} ); }; diff --git a/src/components/color-picker/index.tsx b/src/components/color-picker/index.tsx index e7062cff..991f1a05 100644 --- a/src/components/color-picker/index.tsx +++ b/src/components/color-picker/index.tsx @@ -1,13 +1,13 @@ -import { Fragment, FC } from "react"; -import Gradient from "./gradient"; -import Solid from "./solid"; -import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs"; -import { IPropsMain } from "./types"; -import "./colorpicker.css"; +import { type FC, Fragment } from 'react'; +import Gradient from './gradient'; +import Solid from './solid'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from './tabs'; +import type { IPropsMain } from './types'; +import './colorpicker.css'; const ColorPicker: FC = ({ - value = "#ffffff", - format = "rgb", + value = '#ffffff', + format = 'rgb', gradient = false, solid = true, debounceMS = 300, diff --git a/src/components/tooltip-button.tsx b/src/components/tooltip-button.tsx new file mode 100644 index 00000000..9d2c80fd --- /dev/null +++ b/src/components/tooltip-button.tsx @@ -0,0 +1,42 @@ +import { Button, type ButtonProps } from '@/components/ui/button'; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/ui/tooltip'; +import React, { type ReactNode } from 'react'; + +interface TooltipButtonProps extends ButtonProps { + tooltipText?: string; + icon?: ReactNode; + label?: string; +} + +const TooltipButton = React.forwardRef( + ({ className, tooltipText, icon, label, children, ...props }, ref) => { + const btn = ( + + ); + + if (!tooltipText) { + return btn; + } + + return ( + + {btn} + +

{tooltipText}

+
+
+ ); + } +); + +TooltipButton.displayName = 'TooltipButton'; + +export { TooltipButton }; diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx new file mode 100644 index 00000000..ad9375a5 --- /dev/null +++ b/src/components/ui/tooltip.tsx @@ -0,0 +1,30 @@ +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; +import * as React from 'react'; + +import { cn } from '@/lib/utils'; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/src/features/editor/control-item/basic-text.tsx b/src/features/editor/control-item/basic-text.tsx index c13ca5c0..a76160c7 100644 --- a/src/features/editor/control-item/basic-text.tsx +++ b/src/features/editor/control-item/basic-text.tsx @@ -4,11 +4,11 @@ import { loadFonts } from "../utils/fonts"; import { dispatch } from "@designcombo/events"; import { EDIT_OBJECT } from "@designcombo/state"; import { useEffect, useState } from "react"; -import { IBoxShadow, IText, ITrackItem } from "@designcombo/types"; +import type { IBoxShadow, IText, ITrackItem } from "@designcombo/types"; import Outline from "./common/outline"; import Shadow from "./common/shadow"; import { TextControls } from "./common/text"; -import { ICompactFont, IFont } from "../interfaces/editor"; +import type { ICompactFont, IFont } from "../interfaces/editor"; import { DEFAULT_FONT } from "../constants/font"; interface ITextControlProps { @@ -72,13 +72,15 @@ const BasicText = ({ trackItem }: { trackItem: ITrackItem & IText }) => { trackItem.details.fontFamily || DEFAULT_FONT.postScriptName; const currentFont = fonts.find( (font) => font.postScriptName === fontFamily, - )!; + ); const selectedFont = compactFonts.find( (font) => font.family === currentFont?.family, - )!; + ); - if (!selectedFont) return; + if (!selectedFont) { + return; + } setSelectedFont({ ...selectedFont, @@ -90,11 +92,11 @@ const BasicText = ({ trackItem }: { trackItem: ITrackItem & IText }) => { colorDisplay: trackItem.details.color || "#ffffff", backgroundColor: trackItem.details.backgroundColor || "transparent", fontSize: trackItem.details.fontSize || 62, - fontSizeDisplay: (trackItem.details.fontSize || 62) + "px", + fontSizeDisplay: `${trackItem.details.fontSize || 62}px`, fontFamily: selectedFont?.family || "Open Sans", fontFamilyDisplay: selectedFont?.family || "Open Sans", opacity: trackItem.details.opacity || 1, - opacityDisplay: (trackItem.details.opacity.toString() || "100") + "%", + opacityDisplay: `${trackItem.details.opacity.toString() || "100"}%`, textAlign: trackItem.details.textAlign || "left", textDecoration: trackItem.details.textDecoration || "none", borderWidth: trackItem.details.borderWidth || 0, @@ -351,7 +353,7 @@ const BasicText = ({ trackItem }: { trackItem: ITrackItem & IText }) => { onChangeBoxShadow(v)} - value={properties.boxShadow!} + value={properties.boxShadow} /> diff --git a/src/features/editor/control-item/common/text.tsx b/src/features/editor/control-item/common/text.tsx index 665d4328..7477eb34 100644 --- a/src/features/editor/control-item/common/text.tsx +++ b/src/features/editor/control-item/common/text.tsx @@ -152,7 +152,7 @@ const FontBackground = ({ ); }; -const FontColor = ({ +const FontColor= ({ value, handleColorChange, }: { @@ -161,9 +161,11 @@ const FontColor = ({ }) => { const [localValue, setLocalValue] = useState(value); const [open, setOpen] = useState(false); + useEffect(() => { setLocalValue(value); }, [value]); + return (
diff --git a/src/features/editor/control-item/control-item.tsx b/src/features/editor/control-item/control-item.tsx index 356c5a49..aa14e8da 100644 --- a/src/features/editor/control-item/control-item.tsx +++ b/src/features/editor/control-item/control-item.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import { +import type { IAudio, ICaption, IImage, @@ -8,15 +7,16 @@ import { ITrackItemAndDetails, IVideo, } from "@designcombo/types"; +import { LassoSelect } from "lucide-react"; +import React, { useCallback } from "react"; import { useEffect, useState } from "react"; -import BasicText from "./basic-text"; -import BasicImage from "./basic-image"; -import BasicVideo from "./basic-video"; -import BasicAudio from "./basic-audio"; -import useStore from "../store/use-store"; import useLayoutStore from "../store/use-layout-store"; +import useStore from "../store/use-store"; +import BasicAudio from "./basic-audio"; import BasicCaption from "./basic-caption"; -import { LassoSelect } from "lucide-react"; +import BasicImage from "./basic-image"; +import BasicText from "./basic-text"; +import BasicVideo from "./basic-video"; const Container = ({ children }: { children: React.ReactNode }) => { const { activeIds, trackItemsMap, trackItemDetailsMap, transitionsMap } = @@ -24,26 +24,35 @@ const Container = ({ children }: { children: React.ReactNode }) => { const [trackItem, setTrackItem] = useState(null); const { setTrackItem: setLayoutTrackItem } = useLayoutStore(); + const updateTrackItem = useCallback( + (ids: string[]) => { + if (ids.length === 1) { + const [id] = ids; + const trackItemDetails = trackItemDetailsMap[id]; + const currentTrackItem = { + ...trackItemsMap[id], + details: trackItemDetails?.details || {}, + }; + if (trackItemDetails) { + setTrackItem(currentTrackItem); + setLayoutTrackItem(currentTrackItem); + } else { + console.log('No trackItemDetails', transitionsMap[id]); + } + } else { + setTrackItem(null); + setLayoutTrackItem(null); + } + }, + [trackItemsMap, trackItemDetailsMap, setLayoutTrackItem, transitionsMap] + ); + useEffect(() => { - if (activeIds.length === 1) { - const [id] = activeIds; - const trackItemDetails = trackItemDetailsMap[id]; - const trackItem = { - ...trackItemsMap[id], - details: trackItemDetails?.details || {}, - }; - if (trackItemDetails) { - setTrackItem(trackItem); - setLayoutTrackItem(trackItem); - } else console.log(transitionsMap[id]); - } else { - setTrackItem(null); - setLayoutTrackItem(null); - } - }, [activeIds, trackItemsMap]); + updateTrackItem(activeIds); + }, [activeIds, updateTrackItem]); return ( -
+
{React.cloneElement(children as React.ReactElement, { trackItem, })} diff --git a/src/features/editor/editor.tsx b/src/features/editor/editor.tsx index bcefddfe..0e444fef 100644 --- a/src/features/editor/editor.tsx +++ b/src/features/editor/editor.tsx @@ -11,7 +11,7 @@ import { ResizablePanel, ResizablePanelGroup, } from "@/components/ui/resizable"; -import { ImperativePanelHandle } from "react-resizable-panels"; +import type { ImperativePanelHandle } from "react-resizable-panels"; import { getCompactFontData, loadFonts } from "./utils/fonts"; import { SECONDARY_FONT, SECONDARY_FONT_URL } from "./constants/constants"; import MenuList from "./menu-list"; @@ -50,7 +50,7 @@ const Editor = () => { url: SECONDARY_FONT_URL, }, ]); - }, []); + }); useEffect(() => { const screenHeight = window.innerHeight; @@ -93,7 +93,7 @@ const Editor = () => {
-
+
diff --git a/src/features/editor/menu-item/audios.tsx b/src/features/editor/menu-item/audios.tsx index b595ab2d..72e06f2a 100644 --- a/src/features/editor/menu-item/audios.tsx +++ b/src/features/editor/menu-item/audios.tsx @@ -1,13 +1,13 @@ -import Draggable from "@/components/shared/draggable"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { AUDIOS } from "../data/audio"; -import { dispatch } from "@designcombo/events"; -import { ADD_AUDIO } from "@designcombo/state"; -import { IAudio } from "@designcombo/types"; -import { Music } from "lucide-react"; -import { useIsDraggingOverTimeline } from "../hooks/is-dragging-over-timeline"; -import React from "react"; -import { generateId } from "@designcombo/timeline"; +import Draggable from '@/components/shared/draggable'; +import { ScrollArea } from '@/components/ui/scroll-area'; +import { dispatch } from '@designcombo/events'; +import { ADD_AUDIO } from '@designcombo/state'; +import { generateId } from '@designcombo/timeline'; +import type { IAudio } from '@designcombo/types'; +import { Music } from 'lucide-react'; +import React from 'react'; +import { AUDIOS } from '../data/audio'; +import { useIsDraggingOverTimeline } from '../hooks/is-dragging-over-timeline'; export const Audios = () => { const isDraggingOverTimeline = useIsDraggingOverTimeline(); @@ -22,7 +22,7 @@ export const Audios = () => { return (
-
+
Audios
@@ -54,12 +54,12 @@ const AudioItem = ({ }) => { const style = React.useMemo( () => ({ - backgroundImage: `url(https://cdn.designcombo.dev/thumbnails/music-preview.png)`, - backgroundSize: "cover", - width: "70px", - height: "70px", + backgroundImage: 'url(https://cdn.designcombo.dev/thumbnails/music-preview.png)', + backgroundSize: 'cover', + width: '70px', + height: '70px', }), - [], + [] ); return ( @@ -72,8 +72,8 @@ const AudioItem = ({ draggable={false} onClick={() => handleAddAudio(audio)} style={{ - display: "grid", - gridTemplateColumns: "48px 1fr", + display: 'grid', + gridTemplateColumns: '48px 1fr', }} className="flex cursor-pointer gap-4 px-2 py-1 text-sm hover:bg-zinc-800/70" > diff --git a/src/features/editor/menu-item/images.tsx b/src/features/editor/menu-item/images.tsx index 44e0c4f3..aa9c0fc7 100644 --- a/src/features/editor/menu-item/images.tsx +++ b/src/features/editor/menu-item/images.tsx @@ -1,12 +1,12 @@ -import { ScrollArea } from "@/components/ui/scroll-area"; -import { IMAGES } from "../data/images"; -import { dispatch } from "@designcombo/events"; -import { generateId } from "@designcombo/timeline"; -import Draggable from "@/components/shared/draggable"; -import { IImage } from "@designcombo/types"; -import React from "react"; -import { useIsDraggingOverTimeline } from "../hooks/is-dragging-over-timeline"; -import { ADD_ITEMS } from "@designcombo/state"; +import Draggable from '@/components/shared/draggable'; +import { ScrollArea } from '@/components/ui/scroll-area'; +import { dispatch } from '@designcombo/events'; +import { ADD_ITEMS } from '@designcombo/state'; +import { generateId } from '@designcombo/timeline'; +import type { IImage } from '@designcombo/types'; +import React from 'react'; +import { IMAGES } from '../data/images'; +import { useIsDraggingOverTimeline } from '../hooks/is-dragging-over-timeline'; export const Images = () => { const isDraggingOverTimeline = useIsDraggingOverTimeline(); @@ -51,7 +51,7 @@ export const Images = () => { return (
-
+
Photos
@@ -84,11 +84,11 @@ const ImageItem = ({ const style = React.useMemo( () => ({ backgroundImage: `url(${image.preview})`, - backgroundSize: "cover", - width: "80px", - height: "80px", + backgroundSize: 'cover', + width: '80px', + height: '80px', }), - [image.preview], + [image.preview] ); return ( @@ -102,7 +102,7 @@ const ImageItem = ({ handleAddImage({ id: generateId(), details: { - src: image.details!.src, + src: image.details.src, }, } as IImage) } @@ -112,7 +112,7 @@ const ImageItem = ({ draggable={false} src={image.preview} className="h-full w-full rounded-md object-cover" - alt="image" + alt="timeline element" />
diff --git a/src/features/editor/store/use-store.ts b/src/features/editor/store/use-store.ts index 0dbf3047..4d0d8eae 100644 --- a/src/features/editor/store/use-store.ts +++ b/src/features/editor/store/use-store.ts @@ -1,15 +1,16 @@ -import Timeline from "@designcombo/timeline"; -import { +import type Timeline from '@designcombo/timeline'; +import type { ISize, ITimelineScaleState, ITimelineScrollState, ITrack, ITrackItem, ITransition, -} from "@designcombo/types"; -import Moveable from "@interactify/moveable"; -import { PlayerRef } from "@remotion/player"; -import { create } from "zustand"; +} from '@designcombo/types'; +import type Moveable from '@interactify/moveable'; +import type { PlayerRef } from '@remotion/player'; +import type { RefObject } from 'react'; +import { create } from 'zustand'; interface ITimelineStore { duration: number; @@ -28,11 +29,11 @@ interface ITimelineStore { setTimeline: (timeline: Timeline) => void; setScale: (scale: ITimelineScaleState) => void; setScroll: (scroll: ITimelineScrollState) => void; - playerRef: React.RefObject | null; - setPlayerRef: (playerRef: React.RefObject | null) => void; + playerRef: RefObject | null; + setPlayerRef: (playerRef: RefObject | null) => void; - sceneMoveableRef: React.RefObject | null; - setSceneMoveableRef: (ref: React.RefObject) => void; + sceneMoveableRef: RefObject | null; + setSceneMoveableRef: (ref: RefObject) => void; setState: (state: any) => Promise; } @@ -82,8 +83,7 @@ const useStore = create((set) => ({ setState: async (state) => { return set({ ...state }); }, - setPlayerRef: (playerRef: React.RefObject | null) => - set({ playerRef }), + setPlayerRef: (playerRef: RefObject | null) => set({ playerRef }), setSceneMoveableRef: (ref) => set({ sceneMoveableRef: ref }), })); diff --git a/src/features/editor/timeline/header.tsx b/src/features/editor/timeline/header.tsx index 6da1e330..48d9dced 100644 --- a/src/features/editor/timeline/header.tsx +++ b/src/features/editor/timeline/header.tsx @@ -1,26 +1,27 @@ -import { Button } from "@/components/ui/button"; -import { dispatch } from "@designcombo/events"; +import { TooltipButton } from '@/components/tooltip-button'; +import { Button } from '@/components/ui/button'; +import { Slider } from '@/components/ui/slider'; +import { dispatch } from '@designcombo/events'; import { ACTIVE_SPLIT, LAYER_CLONE, LAYER_DELETE, TIMELINE_SCALE_CHANGED, -} from "@designcombo/state"; -import { PLAYER_PAUSE, PLAYER_PLAY } from "../constants/events"; -import { frameToTimeString, getCurrentTime, timeToString } from "../utils/time"; -import useStore from "../store/use-store"; -import { SquareSplitHorizontal, Trash, ZoomIn, ZoomOut } from "lucide-react"; +} from '@designcombo/state'; +import type { ITimelineScaleState } from '@designcombo/types'; +import { SquareSplitHorizontal, Trash, ZoomIn, ZoomOut } from 'lucide-react'; +import { useCallback, useEffect, useState } from 'react'; +import { PLAYER_PAUSE, PLAYER_PLAY } from '../constants/events'; +import { useCurrentPlayerFrame } from '../hooks/use-current-frame'; +import useUpdateAnsestors from '../hooks/use-update-ansestors'; +import useStore from '../store/use-store'; +import { frameToTimeString, getCurrentTime, timeToString } from '../utils/time'; import { getFitZoomLevel, getNextZoomLevel, getPreviousZoomLevel, getZoomByIndex, -} from "../utils/timeline"; -import { useCurrentPlayerFrame } from "../hooks/use-current-frame"; -import { Slider } from "@/components/ui/slider"; -import { useEffect, useState } from "react"; -import useUpdateAnsestors from "../hooks/use-update-ansestors"; -import { ITimelineScaleState } from "@designcombo/types"; +} from '../utils/timeline'; const IconPlayerPlayFilled = ({ size }: { size: number }) => ( { const [playing, setPlaying] = useState(false); const { duration, fps, scale, playerRef, activeIds } = useStore(); + const handleKeyPress = useCallback( + (e: KeyboardEvent) => { + e.preventDefault(); + if (!activeIds.length) { + return; + } + + const key = e.key.toLowerCase(); + if (key === 'delete' || key === 'backspace') { + doActiveDelete(); + } else if (key === 's') { + doActiveSplit(); + } else if (e.key === ' ') { + doActiveClone(); + } + }, + [activeIds.length] + ); + + useEffect(() => { + window.addEventListener('keydown', handleKeyPress); + return () => window.removeEventListener('keydown', handleKeyPress); + }, [handleKeyPress]); + useUpdateAnsestors({ playing, playerRef }); - const currentFrame = useCurrentPlayerFrame(playerRef!); + const currentFrame = useCurrentPlayerFrame(playerRef); const doActiveDelete = () => { dispatch(LAYER_DELETE); @@ -100,6 +125,10 @@ const Header = () => { }); }; + const doActiveClone = () => { + dispatch(LAYER_CLONE); + }; + const changeScale = (scale: ITimelineScaleState) => { dispatch(TIMELINE_SCALE_CHANGED, { payload: { @@ -117,17 +146,17 @@ const Header = () => { }; useEffect(() => { - playerRef?.current?.addEventListener("play", () => { + playerRef?.current?.addEventListener('play', () => { setPlaying(true); }); - playerRef?.current?.addEventListener("pause", () => { + playerRef?.current?.addEventListener('pause', () => { setPlaying(false); }); return () => { - playerRef?.current?.removeEventListener("play", () => { + playerRef?.current?.removeEventListener('play', () => { setPlaying(true); }); - playerRef?.current?.removeEventListener("pause", () => { + playerRef?.current?.removeEventListener('pause', () => { setPlaying(false); }); }; @@ -136,64 +165,66 @@ const Header = () => { return (
- + - - +
- -
{
{timeToString({ time: duration })} @@ -293,8 +324,8 @@ const ZoomControl = ({ return (
-
- - -